From 4418bcd8245d1be69f59c3508fac853c9ad5e38b Mon Sep 17 00:00:00 2001 From: Dale Rahn Date: Tue, 2 Sep 2003 15:17:53 +0000 Subject: Fix PR 3371, symbol lookup in dlopen()ed objects is not correct. Correct behavior for RTLD_GLOBAL/RTLD_LOCAL is now supported. ok espie@ --- libexec/ld.so/alpha/rtld_machine.c | 19 ++-- libexec/ld.so/dlfcn.c | 11 +-- libexec/ld.so/i386/rtld_machine.c | 12 +-- libexec/ld.so/library.c | 7 +- libexec/ld.so/library_mquery.c | 7 +- libexec/ld.so/loader.c | 11 ++- libexec/ld.so/mips/rtld_machine.c | 16 ++-- libexec/ld.so/powerpc/rtld_machine.c | 17 ++-- libexec/ld.so/resolve.c | 165 +++++++++++++++++++++-------------- libexec/ld.so/resolve.h | 8 +- libexec/ld.so/sparc/rtld_machine.c | 16 ++-- libexec/ld.so/sparc64/rtld_machine.c | 16 ++-- 12 files changed, 176 insertions(+), 129 deletions(-) (limited to 'libexec') diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c index 8705cc97a4e..8a2c61b9230 100644 --- a/libexec/ld.so/alpha/rtld_machine.c +++ b/libexec/ld.so/alpha/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.25 2003/07/28 03:11:00 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.26 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -109,7 +109,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) case R_TYPE(REFQUAD): ooff = _dl_find_symbol(symn, _dl_objects, &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT, - sym->st_size, object->load_name); + sym->st_size, object); if (this == NULL) goto resolve_failed; *r_addr += ooff + this->st_value + relas->r_addend; @@ -134,7 +134,7 @@ _dl_printf("unaligned RELATIVE: %p type: %d %s 0x%lx -> 0x%lx\n", r_addr, case R_TYPE(JMP_SLOT): ooff = _dl_find_symbol(symn, _dl_objects, &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, - sym->st_size, object->load_name); + sym->st_size, object); if (this == NULL) goto resolve_failed; *r_addr = ooff + this->st_value + relas->r_addend; @@ -142,7 +142,7 @@ _dl_printf("unaligned RELATIVE: %p type: %d %s 0x%lx -> 0x%lx\n", r_addr, case R_TYPE(GLOB_DAT): ooff = _dl_find_symbol(symn, _dl_objects, &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT, - sym->st_size, object->load_name); + sym->st_size, object); if (this == NULL) goto resolve_failed; *r_addr = ooff + this->st_value + relas->r_addend; @@ -196,8 +196,7 @@ _dl_bind(elf_object_t *object, int reloff) addr = (Elf_Addr *)(object->load_offs + rela->r_offset); this = NULL; ooff = _dl_find_symbol(symn, _dl_objects, &this, - SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, - object->load_name); + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, object); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ @@ -241,13 +240,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__got_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; @@ -255,13 +254,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->plt_size = 0; this = NULL; ooff = _dl_find_symbol("__plt_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) plt_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__plt_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->plt_size = ooff + this->st_value - plt_addr; diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c index f7d51e18607..b1e03fcca79 100644 --- a/libexec/ld.so/dlfcn.c +++ b/libexec/ld.so/dlfcn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn.c,v 1.29 2003/06/26 07:53:27 deraadt Exp $ */ +/* $OpenBSD: dlfcn.c,v 1.30 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -47,7 +47,7 @@ static void _dl_thread_kern_go(void); static void (*_dl_thread_fnc)(int) = NULL; void * -dlopen(const char *libname, int how) +dlopen(const char *libname, int flags) { elf_object_t *object, *dynobj; Elf_Dyn *dynp; @@ -58,7 +58,7 @@ dlopen(const char *libname, int how) DL_DEB(("dlopen: loading: %s\n", libname)); _dl_thread_kern_stop(); - object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO); + object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, flags); /* this add_object should not be here, XXX */ if (object == 0) { _dl_thread_kern_go(); @@ -91,7 +91,8 @@ dlopen(const char *libname, int how) libname = dynobj->dyn.strtab + dynp->d_un.d_val; _dl_thread_kern_stop(); - depobj = _dl_load_shlib(libname, dynobj, OBJTYPE_LIB); + depobj = _dl_load_shlib(libname, dynobj, OBJTYPE_LIB, + flags|RTLD_GLOBAL); if (!depobj) _dl_exit(4); /* this add_object should not be here, XXX */ @@ -137,7 +138,7 @@ dlsym(void *handle, const char *name) } retval = (void *)_dl_find_symbol(name, object, &sym, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_NOTPLT, 0, ""); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_NOTPLT, 0, object); if (sym != NULL) retval += sym->st_value; else diff --git a/libexec/ld.so/i386/rtld_machine.c b/libexec/ld.so/i386/rtld_machine.c index 1f501216e46..971c1a9ea3e 100644 --- a/libexec/ld.so/i386/rtld_machine.c +++ b/libexec/ld.so/i386/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.10 2003/07/28 03:11:00 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.11 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -241,7 +241,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz) &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND| ((type == R_TYPE(JUMP_SLOT))? SYM_PLT:SYM_NOTPLT), - sym->st_size, object->load_name); + sym->st_size, object); if (this == NULL) { resolve_failed: _dl_printf("%s: %s: can't resolve " @@ -270,7 +270,7 @@ resolve_failed: soff = _dl_find_symbol(symn, object->next, &srcsym, SYM_SEARCH_ALL|SYM_WARNNOTFOUND| ((type == R_TYPE(JUMP_SLOT)) ? SYM_PLT:SYM_NOTPLT), - size, object->load_name); + size, object); if (srcsym == NULL) goto resolve_failed; @@ -367,7 +367,7 @@ _dl_bind(elf_object_t *object, int index) addr = (Elf_Word *)(object->load_offs + rel->r_offset); this = NULL; ooff = _dl_find_symbol(symn, _dl_objects, &this, - SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 0, object->load_name); + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, object); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ @@ -417,13 +417,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__got_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c index 731ae183252..d2c7e2d1504 100644 --- a/libexec/ld.so/library.c +++ b/libexec/ld.so/library.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library.c,v 1.32 2003/07/18 14:09:02 drahn Exp $ */ +/* $OpenBSD: library.c,v 1.33 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -236,7 +236,7 @@ nohints: */ elf_object_t * -_dl_load_shlib(const char *libname, elf_object_t *parent, int type) +_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags) { int try_any_minor, ignore_hints; struct sod sod, req_sod; @@ -270,6 +270,7 @@ again: object = _dl_tryload_shlib(hint, type); if (object != NULL) { _dl_free((char *)sod.sod_name); + object->obj_flags = flags; return (object); } } @@ -291,6 +292,7 @@ again: object = _dl_tryload_shlib(hint, type); if (object != NULL) { _dl_free((char *)sod.sod_name); + object->obj_flags = flags; return (object); } } @@ -308,6 +310,7 @@ again: object = _dl_tryload_shlib(hint, type); if (object != NULL) { _dl_free((char *)sod.sod_name); + object->obj_flags = flags; return(object); } } diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c index 17f04c4d5e3..97691a42311 100644 --- a/libexec/ld.so/library_mquery.c +++ b/libexec/ld.so/library_mquery.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library_mquery.c,v 1.12 2003/07/18 14:09:02 drahn Exp $ */ +/* $OpenBSD: library_mquery.c,v 1.13 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -236,7 +236,7 @@ nohints: */ elf_object_t * -_dl_load_shlib(const char *libname, elf_object_t *parent, int type) +_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags) { int try_any_minor, ignore_hints; struct sod sod, req_sod; @@ -270,6 +270,7 @@ again: object = _dl_tryload_shlib(hint, type); if (object != NULL) { _dl_free((char *)sod.sod_name); + object->obj_flags = flags; return (object); } } @@ -291,6 +292,7 @@ again: object = _dl_tryload_shlib(hint, type); if (object != NULL) { _dl_free((char *)sod.sod_name); + object->obj_flags = flags; return (object); } } @@ -308,6 +310,7 @@ again: object = _dl_tryload_shlib(hint, type); if (object != NULL) { _dl_free((char *)sod.sod_name); + object->obj_flags = flags; return(object); } } diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index 2299ad6027c..a6d77780a1f 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.66 2003/07/09 21:01:10 drahn Exp $ */ +/* $OpenBSD: loader.c,v 1.67 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -36,6 +36,7 @@ #include #include #include +#include #include "syscall.h" #include "archdep.h" @@ -109,7 +110,8 @@ _dl_dopreload(char *paths) } while ((cp = _dl_strsep(&dp, ":")) != NULL) { - shlib = _dl_load_shlib(cp, _dl_objects, OBJTYPE_LIB); + shlib = _dl_load_shlib(cp, _dl_objects, OBJTYPE_LIB, + DL_LAZY|RTLD_GLOBAL); if (shlib == NULL) { _dl_printf("%s: can't load library '%s'\n", _dl_progname, cp); @@ -304,7 +306,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data) liblist[randomlist[i]].dynp->d_un.d_val; DL_DEB(("needs: '%s'\n", libname)); depobj = _dl_load_shlib(libname, dynobj, - OBJTYPE_LIB); + OBJTYPE_LIB, DL_LAZY|RTLD_GLOBAL); if (depobj == 0) { _dl_printf( "%s: can't load library '%s'\n", @@ -361,7 +363,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data) sym = NULL; ooff = _dl_find_symbol("atexit", _dl_objects, &sym, - SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT, 0, ""); + SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT, 0, dyn_obj); if (sym == NULL) _dl_printf("cannot find atexit, destructors will not be run!\n"); else @@ -407,6 +409,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data) _dl_exit(0); DL_DEB(("entry point: 0x%lx\n", dl_data[AUX_entry])); + /* * Return the entry point. */ diff --git a/libexec/ld.so/mips/rtld_machine.c b/libexec/ld.so/mips/rtld_machine.c index eaca0b86c0e..15a5356239f 100644 --- a/libexec/ld.so/mips/rtld_machine.c +++ b/libexec/ld.so/mips/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.13 2003/07/28 03:11:00 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.14 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 1998-2002 Opsycon AB, Sweden. @@ -72,7 +72,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz) ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE)) { ooff = _dl_find_symbol(symn, _dl_objects, &this, SYM_SEARCH_ALL | SYM_NOWARNNOTFOUND | SYM_PLT, - sym->st_size, object->load_name); + sym->st_size, object); if (!this && ELF32_ST_BIND(sym->st_info) == STB_GLOBAL) { _dl_printf("%s: can't resolve reference '%s'\n", _dl_progname, symn); @@ -158,25 +158,25 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__got_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; this = NULL; ooff = _dl_find_symbol("__plt_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->plt_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__plt_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->plt_size = ooff + this->st_value - object->plt_addr; @@ -193,7 +193,7 @@ DL_DEB(("got: '%s' = %x\n", strt + symp->st_name, symp->st_value)); ooff = _dl_find_symbol(strt + symp->st_name, _dl_objects, &this, SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT, - symp->st_size, object->load_name); + symp->st_size, object); if (this) *gotp = this->st_value + ooff; } else @@ -204,7 +204,7 @@ DL_DEB(("got: '%s' = %x\n", strt + symp->st_name, symp->st_value)); ooff = _dl_find_symbol(strt + symp->st_name, _dl_objects, &this, SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT, - symp->st_size, object->load_name); + symp->st_size, object); if (this) *gotp = this->st_value + ooff; } else if (ELF32_ST_TYPE(symp->st_info) == STT_FUNC) { diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c index 648b49efbad..bd4f2040e94 100644 --- a/libexec/ld.so/powerpc/rtld_machine.c +++ b/libexec/ld.so/powerpc/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.29 2003/08/19 04:15:54 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.30 2003/09/02 15:17:52 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -70,6 +70,7 @@ void _dl_syncicache(char *from, size_t len); ((((x) & 0xfe000000) == 0x00000000) || (((x) & 0xfe000000) == 0xfe000000)) void _dl_bind_start(void); /* XXX */ +Elf_Addr _dl_bind(elf_object_t *object, int reloff); void _dl_bcopy(const void *src, void *dest, int size) @@ -206,7 +207,7 @@ _dl_printf("object relocation size %x, numrela %x\n", ooff = _dl_find_symbol(symn, _dl_objects, &this, SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND| ((type == RELOC_JMP_SLOT) ? SYM_PLT:SYM_NOTPLT), - sym->st_size, object->load_name); + sym->st_size, object); if (!this && ELF32_ST_BIND(sym->st_info) == STB_GLOBAL) { _dl_printf("%s: %s :can't resolve reference '%s'\n", @@ -397,7 +398,7 @@ _dl_printf(" symn [%s] val 0x%x\n", symn, val); SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND| ((type == RELOC_JMP_SLOT) ? SYM_PLT : SYM_NOTPLT), - sym->st_size, object->load_name); + sym->st_size, object); } } if (cpysrc == NULL) { @@ -467,13 +468,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__got_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; @@ -481,13 +482,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->plt_size = 0; this = NULL; ooff = _dl_find_symbol("__plt_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) plt_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__plt_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->plt_size = ooff + this->st_value - plt_addr; @@ -569,7 +570,7 @@ _dl_bind(elf_object_t *object, int reloff) r_addr = (Elf_Addr *)(object->load_offs + relas->r_offset); this = NULL; ooff = _dl_find_symbol(symn, _dl_objects, &this, - SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 0, object->load_name); + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, object); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ 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; } diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index b2ce3c5e556..e5b31ae562b 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.27 2003/07/06 20:03:57 deraadt Exp $ */ +/* $OpenBSD: resolve.h,v 1.28 2003/09/02 15:17:51 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -30,6 +30,7 @@ #define _RESOLVE_H_ #include +#include struct load_list { struct load_list *next; @@ -111,6 +112,7 @@ typedef struct elf_object { #define OBJTYPE_EXE 2 #define OBJTYPE_LIB 3 #define OBJTYPE_DLO 4 + int obj_flags; Elf_Word *buckets; u_int32_t nbuckets; @@ -135,14 +137,14 @@ extern elf_object_t *_dl_finalize_object(const char *objname, Elf_Dyn *dynp, extern void _dl_remove_object(elf_object_t *object); extern elf_object_t *_dl_lookup_object(const char *objname); -extern elf_object_t *_dl_load_shlib(const char *, elf_object_t *, int); +extern elf_object_t *_dl_load_shlib(const char *, elf_object_t *, int, int); extern void _dl_unload_shlib(elf_object_t *object); extern int _dl_md_reloc(elf_object_t *object, int rel, int relsz); extern void _dl_md_reloc_got(elf_object_t *object, int lazy); Elf_Addr _dl_find_symbol(const char *name, elf_object_t *startlook, - const Elf_Sym **ref, int flags, int sym_size, const char *module_name); + const Elf_Sym **ref, int flags, int sym_size, elf_object_t *object); /* * defines for _dl_find_symbol() flag field, three bits of meaning * myself - clear: search all objects, set: search only this object diff --git a/libexec/ld.so/sparc/rtld_machine.c b/libexec/ld.so/sparc/rtld_machine.c index af60b9cf25e..c39b6886ed2 100644 --- a/libexec/ld.so/sparc/rtld_machine.c +++ b/libexec/ld.so/sparc/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.17 2003/07/28 03:11:00 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.18 2003/09/02 15:17:52 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -256,7 +256,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) SYM_SEARCH_ALL|SYM_WARNNOTFOUND| ((type == R_TYPE(JMP_SLOT)) ? SYM_PLT : SYM_NOTPLT), - sym->st_size, object->load_name); + sym->st_size, object); if (this == NULL) { resolve_failed: _dl_printf("%s: %s: can't resolve " @@ -281,7 +281,7 @@ resolve_failed: soff = _dl_find_symbol(symn, object->next, &srcsym, SYM_SEARCH_ALL|SYM_WARNNOTFOUND| ((type == R_TYPE(JMP_SLOT)) ? SYM_PLT : SYM_NOTPLT), - size, object->load_name); + size, object); if (srcsym == NULL) goto resolve_failed; @@ -341,7 +341,7 @@ _dl_bind(elf_object_t *object, int reloff) addr = (Elf_Addr *)(object->load_offs + rela->r_offset); this = NULL; ooff = _dl_find_symbol(symn, _dl_objects, &this, - SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 0, object->load_name); + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, object); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ @@ -413,13 +413,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__got_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; @@ -427,13 +427,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->plt_size = 0; this = NULL; ooff = _dl_find_symbol("__plt_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) plt_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__plt_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->plt_size = ooff + this->st_value - plt_addr; diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c index 3dea5af724c..dbdf035323c 100644 --- a/libexec/ld.so/sparc64/rtld_machine.c +++ b/libexec/ld.so/sparc64/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.28 2003/07/28 03:11:00 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.29 2003/09/02 15:17:52 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -276,7 +276,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz) &this, SYM_SEARCH_ALL|SYM_WARNNOTFOUND| ((type == R_TYPE(JMP_SLOT))? SYM_PLT:SYM_NOTPLT), - sym->st_size, object->load_name); + sym->st_size, object); if (this == NULL) { resolve_failed: _dl_printf("%s: %s: can't resolve " @@ -304,7 +304,7 @@ resolve_failed: soff = _dl_find_symbol(symn, object->next, &srcsym, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT, - size, object->load_name); + size, object); if (srcsym == NULL) goto resolve_failed; @@ -632,7 +632,7 @@ _dl_bind(elf_object_t *object, int index) addr = (Elf_Word *)(object->load_offs + rela->r_offset); this = NULL; ooff = _dl_find_symbol(symn, _dl_objects, &this, - SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 0, object->load_name); + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, object); if (this == NULL) { _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ @@ -705,13 +705,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__got_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; @@ -719,13 +719,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->plt_size = 0; this = NULL; ooff = _dl_find_symbol("__plt_start", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) plt_addr = ooff + this->st_value; this = NULL; ooff = _dl_find_symbol("__plt_end", object, &this, - SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, NULL); + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object); if (this != NULL) object->plt_size = ooff + this->st_value - plt_addr; -- cgit v1.2.3