summaryrefslogtreecommitdiff
path: root/libexec/ld.so/resolve.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/ld.so/resolve.c')
-rw-r--r--libexec/ld.so/resolve.c165
1 files changed, 100 insertions, 65 deletions
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index 852c38aeadf..07b464ff2cf 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.19 2003/06/22 21:39:01 drahn Exp $ */
+/* $OpenBSD: resolve.c,v 1.20 2003/09/02 15:17:51 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -184,17 +184,20 @@ _dl_lookup_object(const char *name)
return(0);
}
+int find_symbol_obj(elf_object_t *object, const char *name, unsigned long hash,
+ int flags, const Elf_Sym **ref, const Elf_Sym **weak_sym,
+ elf_object_t **weak_object);
Elf_Addr
_dl_find_symbol(const char *name, elf_object_t *startlook,
- const Elf_Sym **ref, int flags, int req_size, const char *module_name)
+ const Elf_Sym **ref, int flags, int req_size, elf_object_t *req_obj)
{
const Elf_Sym *weak_sym = NULL;
- const char *weak_symn = NULL; /* remove warning */
- Elf_Addr weak_offs = 0;
unsigned long h = 0;
const char *p = name;
elf_object_t *object, *weak_object = NULL;
+ int found = 0;
+ int lastchance = 0;
while (*p) {
unsigned long g;
@@ -204,76 +207,108 @@ _dl_find_symbol(const char *name, elf_object_t *startlook,
h &= ~g;
}
+ if (req_obj->dyn.symbolic)
+ if (find_symbol_obj(req_obj, name, h, flags, ref, &weak_sym,
+ &weak_object)) {
+ object = req_obj;
+ found = 1;
+ goto found;
+ }
+
+retry_nonglobal_dlo:
for (object = startlook; object;
object = ((flags & SYM_SEARCH_SELF) ? 0 : object->next)) {
- const Elf_Sym *symt = object->dyn.symtab;
- const char *strt = object->dyn.strtab;
- long si;
- const char *symn;
- for (si = object->buckets[h % object->nbuckets];
- si != STN_UNDEF; si = object->chains[si]) {
- const Elf_Sym *sym = symt + si;
+ if ((lastchance == 0) &&
+ ((object->obj_flags & RTLD_GLOBAL) == 0) &&
+ (object->obj_type == OBJTYPE_DLO) &&
+ (object != req_obj))
+ continue;
- if (sym->st_value == 0)
- continue;
+ if (find_symbol_obj(object, name, h, flags, ref, &weak_sym,
+ &weak_object)) {
+ found = 1;
+ break;
+ }
+ }
- if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE &&
- ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
- ELF_ST_TYPE(sym->st_info) != STT_FUNC)
- continue;
+found:
+ if (weak_object != NULL && found == 0) {
+ object=weak_object;
+ *ref = weak_sym;
+ found = 1;
+ }
- symn = strt + sym->st_name;
- if (sym != *ref && _dl_strcmp(symn, name))
- continue;
+ if (found == 0) {
+ if (lastchance == 0) {
+ lastchance = 1;
+ goto retry_nonglobal_dlo;
+ }
+ if (flags & SYM_WARNNOTFOUND)
+ _dl_printf("%s:%s: undefined symbol '%s'\n",
+ _dl_progname, req_obj->load_name, name);
+ return (0);
+ }
- /* allow this symbol if we are referring to a function
- * which has a value, even if section is UNDEF.
- * this allows &func to refer to PLT as per the
- * ELF spec. st_value is checked above.
- * if flags has SYM_PLT set, we must have actual
- * symbol, so this symbol is skipped.
- */
- if (sym->st_shndx == SHN_UNDEF) {
- if ((flags & SYM_PLT) || sym->st_value == 0 ||
- ELF_ST_TYPE(sym->st_info) != STT_FUNC)
- continue;
- }
+ if (req_size != (*ref)->st_size && req_size != 0 &&
+ (ELF_ST_TYPE((*ref)->st_info) != STT_FUNC)) {
+ _dl_printf("%s:%s: %s : WARNING: "
+ "symbol(%s) size mismatch, relink your program\n",
+ _dl_progname, req_obj->load_name,
+ object->load_name, name);
+ }
+
+ return (object->load_offs);
+}
- if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) {
- *ref = sym;
- if (req_size != sym->st_size &&
- req_size != 0 &&
- (ELF_ST_TYPE(sym->st_info) != STT_FUNC)) {
- _dl_printf("%s: %s : WARNING: "
- "symbol(%s) size mismatch ",
- _dl_progname, object->load_name,
- symn);
- _dl_printf("relink your program\n");
- }
- return(object->load_offs);
- } else if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
- if (!weak_sym) {
- weak_sym = sym;
- weak_symn = symn;
- weak_offs = object->load_offs;
- weak_object = object;
- }
+int
+find_symbol_obj(elf_object_t *object, const char *name, unsigned long hash,
+ int flags, const Elf_Sym **ref, const Elf_Sym **weak_sym,
+ elf_object_t **weak_object)
+{
+ const Elf_Sym *symt = object->dyn.symtab;
+ const char *strt = object->dyn.strtab;
+ long si;
+ const char *symn;
+
+ for (si = object->buckets[hash % object->nbuckets];
+ si != STN_UNDEF; si = object->chains[si]) {
+ const Elf_Sym *sym = symt + si;
+
+ if (sym->st_value == 0)
+ continue;
+
+ if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE &&
+ ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
+ ELF_ST_TYPE(sym->st_info) != STT_FUNC)
+ continue;
+
+ symn = strt + sym->st_name;
+ if (sym != *ref && _dl_strcmp(symn, name))
+ continue;
+
+ /* allow this symbol if we are referring to a function
+ * which has a value, even if section is UNDEF.
+ * this allows &func to refer to PLT as per the
+ * ELF spec. st_value is checked above.
+ * if flags has SYM_PLT set, we must have actual
+ * symbol, so this symbol is skipped.
+ */
+ if (sym->st_shndx == SHN_UNDEF) {
+ if ((flags & SYM_PLT) || sym->st_value == 0 ||
+ ELF_ST_TYPE(sym->st_info) != STT_FUNC)
+ continue;
+ }
+
+ if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) {
+ *ref = sym;
+ return 1;
+ } else if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
+ if (!*weak_sym) {
+ *weak_sym = sym;
+ *weak_object = object;
}
}
}
- if (flags & SYM_WARNNOTFOUND && weak_sym == NULL) {
- _dl_printf("%s:%s: undefined symbol '%s'\n",
- _dl_progname, module_name, name);
- }
- *ref = weak_sym;
- if (weak_sym != NULL && req_size != weak_sym->st_size &&
- req_size != 0 && (ELF_ST_TYPE(weak_sym->st_info) != STT_FUNC)) {
- _dl_printf("%s:%s: %s : WARNING: "
- "symbol(%s) size mismatch ",
- _dl_progname, module_name, weak_object->load_name,
- weak_symn);
- _dl_printf("relink your program\n");
- }
- return (weak_offs);
+ return 0;
}