summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoakim Tjernlund <joakim.tjernlund@transmode.se>2004-08-09 08:11:54 +0000
committerJoakim Tjernlund <joakim.tjernlund@transmode.se>2004-08-09 08:11:54 +0000
commit97688568dea693a1bd1c9f7a2320f316af25a16d (patch)
treefb26c0a5c15237e45b73847b30d551ca798f54f6
parent758d1c9ff67def05e29859d4698eadc29ebb24de (diff)
This should fix the dlsym problem Peter van Hoyweghen reported.
However RTLD_LOCAL still doesn't work. Everything is RTLD_GLOBAL.
-rw-r--r--ldso/ldso/dl-hash.c99
-rw-r--r--ldso/ldso/ldso.c8
-rw-r--r--ldso/libdl/libdl.c51
3 files changed, 58 insertions, 100 deletions
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c
index 251ab6466..109ee0e76 100644
--- a/ldso/ldso/dl-hash.c
+++ b/ldso/ldso/dl-hash.c
@@ -153,89 +153,60 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
* This function resolves externals, and this is either called when we process
* relocations or when we call an entry in the PLT table for the first time.
*/
-char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1, int type_class)
+char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, int type_class)
{
struct elf_resolve *tpnt;
int si;
- int pass;
char *strtab;
Elf32_Sym *symtab;
unsigned long elf_hash_number, hn;
- struct dyn_elf *rpnt;
const ElfW(Sym) *sym;
char *weak_result = NULL;
elf_hash_number = _dl_elf_hash(name);
- /*
- * The passes are so that we can first search the regular symbols
- * for whatever module was specified, and then search anything
- * loaded with RTLD_GLOBAL. When pass is 1, it means we are just
- * starting the first dlopened module, and anything above that
- * is just the next one in the chain.
- */
- if (rpnt1 == NULL)
- rpnt1 = _dl_symbol_tables;
-
- for (pass = 0; (1 == 1); pass++) {
-
- /*
- * If we are just starting to search for RTLD_GLOBAL, setup
- * the pointer for the start of the search.
- */
- if (pass == 1)
- rpnt1 = _dl_handles;
-
- /*
- * Anything after this, we need to skip to the next module.
- */
- else if (pass >= 2)
- rpnt1 = rpnt1->next_handle;
-
- /*
- * Make sure we still have a module.
- */
- if (rpnt1 == NULL)
- break;
+ /*
+ NOTE! RTLD_LOCAL handling for dlopen not implemented yet.
+ Everything is treated as RTLD_GLOBAL.
+ */
+
+ for (; rpnt; rpnt = rpnt->next) {
+ tpnt = rpnt->dyn;
+
+ /* Don't search the executable when resolving a copy reloc. */
+ if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
+ continue;
- for (rpnt = rpnt1; rpnt; rpnt = rpnt->next) {
- tpnt = rpnt->dyn;
+ /* Avoid calling .urem here. */
+ do_rem(hn, elf_hash_number, tpnt->nbucket);
+ symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
- /* Don't search the executable when resolving a copy reloc. */
- if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
+ for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
+ sym = &symtab[si];
+
+ if (type_class & (sym->st_shndx == SHN_UNDEF))
+ continue;
+ if (_dl_strcmp(strtab + sym->st_name, name) != 0)
+ continue;
+ if (sym->st_value == 0)
+ continue;
+ if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
continue;
- /* Avoid calling .urem here. */
- do_rem(hn, elf_hash_number, tpnt->nbucket);
- symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
- strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
-
- for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
- sym = &symtab[si];
-
- if (type_class & (sym->st_shndx == SHN_UNDEF))
- continue;
- if (_dl_strcmp(strtab + sym->st_name, name) != 0)
- continue;
- if (sym->st_value == 0)
- continue;
- if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
- continue;
-
- switch (ELF32_ST_BIND(sym->st_info)) {
- case STB_WEAK:
+ switch (ELF32_ST_BIND(sym->st_info)) {
+ case STB_WEAK:
#if 0
/* Perhaps we should support old style weak symbol handling
* per what glibc does when you export LD_DYNAMIC_WEAK */
- if (!weak_result)
- weak_result = (char *)tpnt->loadaddr + sym->st_value;
- break;
+ if (!weak_result)
+ weak_result = (char *)tpnt->loadaddr + sym->st_value;
+ break;
#endif
- case STB_GLOBAL:
- return (char*)tpnt->loadaddr + sym->st_value;
- default: /* Local symbols not handled here */
- break;
- }
+ case STB_GLOBAL:
+ return (char*)tpnt->loadaddr + sym->st_value;
+ default: /* Local symbols not handled here */
+ break;
}
}
}
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index eaa8a8ff0..a4e4595bb 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -612,12 +612,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
up each symbol individually. */
- _dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("__curbrk", NULL, 0);
+ _dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("__curbrk", _dl_symbol_tables, 0);
if (_dl_brkp) {
*_dl_brkp = brk_addr;
}
- _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, 0);
+ _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", _dl_symbol_tables, 0);
if (_dl_envp) {
*_dl_envp = (unsigned long) envp;
@@ -641,10 +641,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
}
#endif
- _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, ELF_RTYPE_CLASS_PLT);
+ _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", _dl_symbol_tables, ELF_RTYPE_CLASS_PLT);
#if defined (__SUPPORT_LD_DEBUG__)
_dl_on_exit = (int (*)(void (*)(int, void *),void*))
- (intptr_t) _dl_find_hash("on_exit", NULL, ELF_RTYPE_CLASS_PLT);
+ (intptr_t) _dl_find_hash("on_exit", _dl_symbol_tables, ELF_RTYPE_CLASS_PLT);
#endif
/* Notify the debugger we have added some objects. */
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index f20041bc2..03b7834a0 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -131,7 +131,7 @@ static void __attribute__ ((destructor)) dl_cleanup(void)
void *dlopen(const char *libname, int flag)
{
struct elf_resolve *tpnt, *tfrom, *tcurr;
- struct dyn_elf *dyn_chain, *rpnt = NULL;
+ struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr;
struct dyn_elf *dpnt;
static int dl_init = 0;
ElfW(Addr) from;
@@ -175,7 +175,7 @@ void *dlopen(const char *libname, int flag)
&& (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
tfrom = tpnt;
}
-
+ for(rpnt = _dl_symbol_tables; rpnt->next; rpnt=rpnt->next);
/* Try to load the specified library */
#ifdef __SUPPORT_LD_DEBUG__
if(_dl_debug)
@@ -192,19 +192,9 @@ void *dlopen(const char *libname, int flag)
_dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
dyn_chain->dyn = tpnt;
dyn_chain->flags = flag;
- if (!tpnt->symbol_scope)
- tpnt->symbol_scope = dyn_chain;
dyn_chain->next_handle = _dl_handles;
- _dl_handles = rpnt = dyn_chain;
-
- if (tpnt->init_flag & INIT_FUNCS_CALLED) {
- /* If the init and fini stuff has already been run, that means
- * the dlopen'd library has already been loaded, and nothing
- * further needs to be done. */
- return (void *) dyn_chain;
- }
-
+ _dl_handles = dyn_ptr = dyn_chain;
#ifdef __SUPPORT_LD_DEBUG__
if(_dl_debug)
@@ -222,35 +212,32 @@ void *dlopen(const char *libname, int flag)
lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
dpnt->d_un.d_val);
name = _dl_get_last_path_component(lpntstr);
-
- if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, 0)))
- continue;
-
+ tpnt1 = _dl_check_if_named_library_is_loaded(name, 0);
#ifdef __SUPPORT_LD_DEBUG__
if(_dl_debug)
fprintf(stderr, "Trying to load '%s', needed by '%s'\n",
lpntstr, tcurr->libname);
#endif
-
- if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, 0))) {
- goto oops;
+ dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
+ _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf));
+ dyn_ptr = dyn_ptr->next;
+ dyn_ptr->dyn = tpnt1;
+ if (!tpnt1) {
+ tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, 0);
+ if (!tpnt1)
+ goto oops;
+ dyn_ptr->dyn = tpnt1;
}
-
- rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
- _dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
- rpnt = rpnt->next;
- if (!tpnt1->symbol_scope) tpnt1->symbol_scope = rpnt;
- rpnt->dyn = tpnt1;
-
}
}
}
- /*
- * OK, now attach the entire chain at the end
- */
- rpnt->next = _dl_symbol_tables;
-
+ if (dyn_chain->dyn->init_flag & INIT_FUNCS_CALLED) {
+ /* If the init and fini stuff has already been run, that means
+ * the dlopen'd library has already been loaded, and nothing
+ * further needs to be done. */
+ return (void *) dyn_chain;
+ }
#ifdef __mips__
/*
* Relocation of the GOT entries for MIPS have to be done