diff options
author | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2004-11-10 15:27:26 +0000 |
---|---|---|
committer | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2004-11-10 15:27:26 +0000 |
commit | 0038f6a2297be2b66a0177bc74b468dddb0a89fa (patch) | |
tree | 2413de564ae1751210c6fd82924636d2b09cebda /ldso | |
parent | 0657ab0d0b7d9a879091653b2e23f0b46c3ecefa (diff) |
Add RTLD_LOCAL support for dlopened libs. Reported by
Andrew de Quincey, who has been most helpful getting this sorted
out, thanks. Thanks also to Peter Mazinger who did alot of testing.
Removed all traces of dl_parse_copy_information() since it is no longer used.
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/include/dl-hash.h | 4 | ||||
-rw-r--r-- | ldso/ldso/arm/elfinterp.c | 59 | ||||
-rw-r--r-- | ldso/ldso/cris/elfinterp.c | 4 | ||||
-rw-r--r-- | ldso/ldso/dl-hash.c | 23 | ||||
-rw-r--r-- | ldso/ldso/i386/elfinterp.c | 64 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 8 | ||||
-rw-r--r-- | ldso/ldso/m68k/elfinterp.c | 64 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 16 | ||||
-rw-r--r-- | ldso/ldso/powerpc/elfinterp.c | 4 | ||||
-rw-r--r-- | ldso/ldso/sh/elfinterp.c | 12 | ||||
-rw-r--r-- | ldso/ldso/sh64/elfinterp.c | 64 | ||||
-rw-r--r-- | ldso/ldso/sparc/elfinterp.c | 62 | ||||
-rw-r--r-- | ldso/libdl/libdl.c | 36 |
13 files changed, 67 insertions, 353 deletions
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index 60fdd2856..cc0d389f6 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -35,7 +35,7 @@ struct elf_resolve{ unsigned int nbucket; unsigned long * elf_buckets; struct init_fini_list *init_fini; - + struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */ /* * These are only used with ELF style shared libraries */ @@ -71,7 +71,7 @@ extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, unsigned long dynamic_addr, unsigned long dynamic_size); extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, - int type_class); + struct elf_resolve *mytpnt, int type_class); extern int _dl_linux_dynamic_link(void); diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index 9e0a6d702..eef82679c 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -149,8 +149,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) got_addr = (char **) instr_addr; /* Get the address of the GOT entry */ - new_addr = _dl_find_hash(symname, - tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, + tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -278,7 +278,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, if (symtab_index) { symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, - scope, elf_machine_type_class(reloc_type)); + scope, tpnt, elf_machine_type_class(reloc_type)); /* * We want to allow undefined references to weak symbols - this might @@ -391,53 +391,6 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, } -/* This is done as a separate step, because there are cases where - information is first copied and later initialized. This results in - the wrong information being copied. Someone at Sun was complaining about - a bug in the handling of _COPY by SVr4, and this may in fact be what he - was talking about. Sigh. */ - -/* No, there are cases where the SVr4 linker fails to emit COPY relocs - at all */ -static int -_dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, - ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) -{ - int reloc_type; - int symtab_index; - unsigned long *reloc_addr; - unsigned long symbol_addr; - int goof = 0; - return 0; /* disable now, remove later */ - reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - if (reloc_type != R_ARM_COPY) - return 0; - symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - - if (symtab_index) { - - symbol_addr = (unsigned long) _dl_find_hash(strtab + - symtab[symtab_index].st_name, scope, - ELF_RTYPE_CLASS_COPY); - if (!symbol_addr) goof++; - } - if (!goof) { -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug_move) - _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", - strtab + symtab[symtab_index].st_name, - symtab[symtab_index].st_size, - symbol_addr, symtab[symtab_index].st_value); -#endif - _dl_memcpy((char *) symtab[symtab_index].st_value, - (char *) symbol_addr, symtab[symtab_index].st_size); - } - - return goof; -} - void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) { @@ -450,9 +403,3 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } -int _dl_parse_copy_information(struct dyn_elf *rpnt, - unsigned long rel_addr, unsigned long rel_size) -{ - return _dl_parse(rpnt->dyn, rpnt->next, rel_addr, rel_size, _dl_do_copy_reloc); -} - diff --git a/ldso/ldso/cris/elfinterp.c b/ldso/ldso/cris/elfinterp.c index 37955cc6f..675fb0117 100644 --- a/ldso/ldso/cris/elfinterp.c +++ b/ldso/ldso/cris/elfinterp.c @@ -144,7 +144,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) got_addr = (char **)instr_addr; /* Get the address of the GOT entry. */ - new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); @@ -253,7 +253,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL) { symbol_addr = (unsigned long)tpnt->loadaddr; } else { - symbol_addr = (unsigned long)_dl_find_hash(symname, scope, + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type)); } diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index a119e77f9..4719315ee 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -137,7 +137,7 @@ 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 *rpnt, int type_class) +char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, int type_class) { struct elf_resolve *tpnt; int si; @@ -148,17 +148,24 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, int type_class) char *weak_result = NULL; elf_hash_number = _dl_elf_hash(name); - - /* - NOTE! RTLD_LOCAL handling for dlopen not implemented yet. - Everything is treated as RTLD_GLOBAL. - */ for (; rpnt; rpnt = rpnt->next) { tpnt = rpnt->dyn; - if (!(tpnt->rtld_flags & RTLD_GLOBAL)) - continue; + if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) { + if (mytpnt == tpnt) + ; + else { + struct init_fini_list *tmp; + + for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) { + if (tmp->tpnt == tpnt) + break; + } + if (!tmp) + continue; + } + } /* Don't search the executable when resolving a copy reloc. */ if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) continue; diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index 12e67f5d2..cb5a24a9e 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -147,7 +147,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) got_addr = (char **)instr_addr; /* Get the address of the GOT entry. */ - new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); @@ -253,7 +253,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { - symbol_addr = (unsigned long)_dl_find_hash(symname, scope, + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type)); /* @@ -355,56 +355,6 @@ _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, return 0; } -/* This is done as a separate step, because there are cases where - information is first copied and later initialized. This results in - the wrong information being copied. Someone at Sun was complaining about - a bug in the handling of _COPY by SVr4, and this may in fact be what he - was talking about. Sigh. */ - -/* No, there are cases where the SVr4 linker fails to emit COPY relocs - at all */ -static int -_dl_do_copy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, - ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) -{ - int reloc_type; - int symtab_index; - unsigned long *reloc_addr; - unsigned long symbol_addr; - int goof = 0; - char *symname; - - reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - if (reloc_type != R_386_COPY) - return 0; - - symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - symname = strtab + symtab[symtab_index].st_name; - - if (symtab_index) { - symbol_addr = (unsigned long)_dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY); - if (!symbol_addr) - goof++; - } - - if (!goof) { -#if defined (__SUPPORT_LD_DEBUG__) - if (_dl_debug_move) - _dl_dprintf(_dl_debug_file, - "\n%s move %x bytes from %x to %x", - symname, symtab[symtab_index].st_size, - symbol_addr, symtab[symtab_index].st_value); -#endif - - _dl_memcpy((char *)symtab[symtab_index].st_value, - (char *)symbol_addr, symtab[symtab_index].st_size); - } - - return goof; -} - void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, @@ -420,13 +370,3 @@ _dl_parse_relocation_information(struct dyn_elf *rpnt, { return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } - -int -_dl_parse_copy_information(struct dyn_elf *rpnt, - unsigned long rel_addr, - unsigned long rel_size) -{ - return 0; - /* just disable for now, remove when we know that it works */ - /* return _dl_parse(rpnt->dyn, rpnt->next, rel_addr, rel_size, _dl_do_copy_reloc); */ -} diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index d231969f8..476dae629 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -774,7 +774,7 @@ next_lib2: * ld.so.1, so we have to look up each symbol individually. */ - _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", _dl_symbol_tables, 0); + _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", _dl_symbol_tables, NULL, 0); if (_dl_envp) *_dl_envp = (unsigned long) envp; @@ -798,10 +798,10 @@ next_lib2: } #endif - _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", _dl_symbol_tables, ELF_RTYPE_CLASS_PLT); + _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); #if defined (__SUPPORT_LD_DEBUG__) _dl_on_exit = (int (*)(void (*)(int, void *),void*)) - (intptr_t) _dl_find_hash("on_exit", _dl_symbol_tables, ELF_RTYPE_CLASS_PLT); + (intptr_t) _dl_find_hash("on_exit", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); #endif /* Notify the debugger we have added some objects. */ @@ -853,7 +853,7 @@ next_lib2: _dl_debug_state(); /* Find the real malloc function and make ldso functions use that from now on */ - _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash("malloc", _dl_symbol_tables, ELF_RTYPE_CLASS_PLT); + _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash("malloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); } char *_dl_getenv(const char *symbol, char **envp) diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c index dc5713422..3b2f13b48 100644 --- a/ldso/ldso/m68k/elfinterp.c +++ b/ldso/ldso/m68k/elfinterp.c @@ -98,7 +98,7 @@ unsigned int _dl_linux_resolver (int dummy1, int dummy2, /* Get the address of the GOT entry. */ new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", @@ -204,7 +204,7 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, { symbol_addr = (unsigned int) _dl_find_hash (strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, + tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type)); /* We want to allow undefined references to weak symbols - @@ -272,63 +272,3 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, } return goof; } - -/* This is done as a separate step, because there are cases where - information is first copied and later initialized. This results in - the wrong information being copied. Someone at Sun was complaining about - a bug in the handling of _COPY by SVr4, and this may in fact be what he - was talking about. Sigh. */ - -/* No, there are cases where the SVr4 linker fails to emit COPY relocs - at all. */ - -int _dl_parse_copy_information(struct dyn_elf *xpnt, - unsigned long rel_addr, unsigned long rel_size) -{ - int i; - char *strtab; - int reloc_type; - int goof = 0; - Elf32_Sym *symtab; - Elf32_Rela *rpnt; - unsigned int *reloc_addr; - unsigned int symbol_addr; - struct elf_resolve *tpnt; - int symtab_index; - /* Now parse the relocation information */ - return 0; /* disable now, remove later */ - tpnt = xpnt->dyn; - - rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr); - rel_size = rel_size / sizeof (Elf32_Rela); - - symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] - + tpnt->loadaddr); - strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); - - for (i = 0; i < rel_size; i++, rpnt++) - { - reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset); - reloc_type = ELF32_R_TYPE (rpnt->r_info); - if (reloc_type != R_68K_COPY) - continue; - symtab_index = ELF32_R_SYM (rpnt->r_info); - symbol_addr = 0; - if (symtab_index) - { - symbol_addr = (unsigned int) - _dl_find_hash (strtab + symtab[symtab_index].st_name, - xpnt->next, ELF_RTYPE_CLASS_COPY); - if (!symbol_addr) - { - _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - goof++; - } - } - if (!goof) - _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr, - symtab[symtab_index].st_size); - } - return goof; -} diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 74521823e..79a681d35 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -129,7 +129,7 @@ unsigned long _dl_linux_resolver(unsigned long sym_index, symname = strtab + sym->st_name; new_addr = (unsigned long) _dl_find_hash(symname, - tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -164,14 +164,6 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, return; } -int _dl_parse_copy_information(struct dyn_elf *rpnt, - unsigned long rel_addr, unsigned long rel_size) -{ - /* Nothing to do */ - return 0; -} - - int _dl_parse_relocation_information(struct dyn_elf *xpnt, unsigned long rel_addr, unsigned long rel_size) { @@ -290,12 +282,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) } else { *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); } } else if (sym->st_shndx == SHN_COMMON) { *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); } else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && *got_entry != sym->st_value) { @@ -307,7 +299,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) } else { *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); } got_entry++; diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c index d154a18a4..8175a0178 100644 --- a/ldso/ldso/powerpc/elfinterp.c +++ b/ldso/ldso/powerpc/elfinterp.c @@ -210,7 +210,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) /* Get the address of the GOT entry */ finaladdr = (Elf32_Addr) _dl_find_hash(symname, - tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!finaladdr)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); @@ -269,7 +269,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, symtab_index = ELF32_R_SYM(rpnt->r_info); symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { - symbol_addr = (unsigned long) _dl_find_hash(symname, scope, + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type)); /* We want to allow undefined references to weak symbols - this might * have been intentional. We should not be linking local symbols diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c index 821b44cbc..18551841c 100644 --- a/ldso/ldso/sh/elfinterp.c +++ b/ldso/ldso/sh/elfinterp.c @@ -149,7 +149,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) /* Get the address of the GOT entry */ - new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); @@ -253,9 +253,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { - - - symbol_addr = (unsigned long) _dl_find_hash(symname, scope, + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type)); /* @@ -360,9 +358,3 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } -int _dl_parse_copy_information(struct dyn_elf __attribute__((unused))*rpnt, - unsigned long __attribute__((unused))rel_addr, unsigned long __attribute__((unused))rel_size) -{ - return 0; -} - diff --git a/ldso/ldso/sh64/elfinterp.c b/ldso/ldso/sh64/elfinterp.c index 3152881b3..82d66552a 100644 --- a/ldso/ldso/sh64/elfinterp.c +++ b/ldso/ldso/sh64/elfinterp.c @@ -190,7 +190,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) /* Get the address of the GOT entry */ - new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if (unlikely(!new_addr)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -305,7 +305,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope, if (symtab_index) { int stb; - symbol_addr = (unsigned long)_dl_find_hash(symname, scope, + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, elf_machine_type_class(reloc_type)); /* @@ -445,59 +445,6 @@ static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, return 0; } -/* This is done as a separate step, because there are cases where - information is first copied and later initialized. This results in - the wrong information being copied. Someone at Sun was complaining about - a bug in the handling of _COPY by SVr4, and this may in fact be what he - was talking about. Sigh. */ - -/* No, there are cases where the SVr4 linker fails to emit COPY relocs - at all */ -static int _dl_do_copy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, - ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) -{ - int reloc_type; - int symtab_index; - unsigned long *reloc_addr; - unsigned long symbol_addr; - char *symname; - int goof = 0; - return 0; /* disable now, remove later */ - reloc_addr = (unsigned long *)(intptr_t) - (tpnt->loadaddr + (unsigned long)rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - - if (reloc_type != R_SH_COPY) - return 0; - - symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - symname = strtab + symtab[symtab_index].st_name; - - if (symtab_index) { - symbol_addr = (unsigned long) - _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY); - - if (!symbol_addr) - goof++; - } - - if (!goof) { -#ifdef __SUPPORT_LD_DEBUG__ - if (_dl_debug_move) - _dl_dprintf(_dl_debug_file, - "\n%s move %x bytes from %x to %x", - symname, symtab[symtab_index].st_size, - symbol_addr, symtab[symtab_index].st_value); -#endif - - _dl_memcpy((char *)symtab[symtab_index].st_value, - (char *)symbol_addr, symtab[symtab_index].st_size); - } - - return goof; -} - void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) { @@ -509,10 +456,3 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, { return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } - -int _dl_parse_copy_information(struct dyn_elf *rpnt, - unsigned long rel_addr, unsigned long rel_size) -{ - return _dl_parse(rpnt->dyn, rpnt->next, rel_addr, rel_size, _dl_do_copy_reloc); -} - diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c index 89993cd84..704837092 100644 --- a/ldso/ldso/sparc/elfinterp.c +++ b/ldso/ldso/sparc/elfinterp.c @@ -113,7 +113,7 @@ unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt) /* Get the address of the GOT entry */ new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); if(unlikely(!new_addr)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, strtab + symtab[symtab_index].st_name); @@ -216,7 +216,7 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, symbol_addr = (unsigned int) _dl_find_hash(strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, elf_machine_type_class(reloc_type)); + tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type)); if(!symbol_addr && ELF32_ST_BIND(symtab [symtab_index].st_info) != STB_WEAK) { @@ -278,61 +278,3 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, }; return goof; } - - -/* This is done as a separate step, because there are cases where - information is first copied and later initialized. This results in - the wrong information being copied. Someone at Sun was complaining about - a bug in the handling of _COPY by SVr4, and this may in fact be what he - was talking about. Sigh. */ - -/* No, there are cases where the SVr4 linker fails to emit COPY relocs - at all */ - -int _dl_parse_copy_information(struct dyn_elf *xpnt, - unsigned long rel_addr, unsigned long rel_size) -{ - int i; - char * strtab; - int reloc_type; - int goof = 0; - Elf32_Sym * symtab; - Elf32_Rela * rpnt; - unsigned int * reloc_addr; - unsigned int symbol_addr; - struct elf_resolve *tpnt; - int symtab_index; - /* Now parse the relocation information */ - return 0; /* disable for now, remove later */ - tpnt = xpnt->dyn; - - rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr); - - symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr); - strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); - - for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){ - reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset); - reloc_type = ELF32_R_TYPE(rpnt->r_info); - if(reloc_type != R_SPARC_COPY) continue; - symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - if(symtab_index) { - symbol_addr = (unsigned int) - _dl_find_hash(strtab + symtab[symtab_index].st_name, - xpnt->next, ELF_RTYPE_CLASS_COPY); - if(!symbol_addr) { - _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); - goof++; - }; - }; - if (!goof) - _dl_memcpy((char *) symtab[symtab_index].st_value, - (char *) symbol_addr, - symtab[symtab_index].st_size); - }; - return goof; -} - - diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 1bb68bdc8..5a4bb0dce 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -39,7 +39,7 @@ /* When libdl is loaded as a shared library, we need to load in * and use a pile of symbols from ldso... */ -extern char *_dl_find_hash(const char *, struct dyn_elf *, int) +extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, int) __attribute__ ((__weak__)); extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *, int) __attribute__ ((__weak__)); @@ -136,7 +136,7 @@ void *dlopen(const char *libname, int flag) struct elf_resolve *tpnt1; void (*dl_brk) (void); int now_flag; - struct init_fini_list *tmp; + struct init_fini_list *tmp, *runp; int nlist, i; struct elf_resolve **init_fini_list; @@ -190,7 +190,7 @@ void *dlopen(const char *libname, int flag) dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf)); _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf)); dyn_chain->dyn = tpnt; - tpnt->rtld_flags |= RTLD_GLOBAL; + tpnt->rtld_flags |= (flag & RTLD_GLOBAL); dyn_chain->next_handle = _dl_handles; _dl_handles = dyn_ptr = dyn_chain; @@ -227,7 +227,7 @@ void *dlopen(const char *libname, int flag) if (!tpnt1) goto oops; } - tpnt1->rtld_flags |= RTLD_GLOBAL; + tpnt1->rtld_flags |= (flag & RTLD_GLOBAL); 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; @@ -246,6 +246,15 @@ void *dlopen(const char *libname, int flag) i = 0; for (tcurr = tpnt; tcurr; tcurr = tcurr->next) { init_fini_list[i++] = tcurr; + for(runp = tcurr->init_fini; runp; runp = runp->next){ + if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) { + tmp = malloc(sizeof(struct init_fini_list)); + tmp->tpnt = runp->tpnt; + tmp->next = tcurr->rtld_local; + tcurr->rtld_local = tmp; + } + } + } /* Sort the INIT/FINI list in dependency order. */ for (tcurr = tpnt; tcurr; tcurr = tcurr->next) { @@ -275,12 +284,10 @@ void *dlopen(const char *libname, int flag) if(_dl_debug) { fprintf(stderr, "\nINIT/FINI order and dependencies:\n"); for (i=0;i < nlist;i++) { - struct init_fini_list *tmp; - fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname); - tmp = init_fini_list[i]->init_fini; - for ( ;tmp; tmp = tmp->next) - printf(" %s ", tmp->tpnt->libname); + runp = init_fini_list[i]->init_fini; + for ( ;runp; runp = runp->next) + printf(" %s ", runp->tpnt->libname); printf("\n"); } } @@ -409,7 +416,7 @@ void *dlsym(void *vhandle, const char *name) } } - ret = _dl_find_hash((char*)name, handle, 0); + ret = _dl_find_hash((char*)name, handle, NULL, 0); /* * Nothing found. @@ -422,6 +429,7 @@ void *dlsym(void *vhandle, const char *name) static int do_dlclose(void *vhandle, int need_fini) { struct dyn_elf *rpnt, *rpnt1; + struct init_fini_list *runp, *tmp; ElfW(Phdr) *ppnt; struct elf_resolve *tpnt; int (*dl_elf_fini) (void); @@ -461,7 +469,8 @@ static int do_dlclose(void *vhandle, int need_fini) } } } - free(handle->init_fini.init_fini); + if (handle->dyn->usage_count == 1) + free(handle->init_fini.init_fini); /* OK, this is a valid handle - now close out the file */ for (rpnt = handle; rpnt; rpnt = rpnt->next) { tpnt = rpnt->dyn; @@ -475,6 +484,11 @@ static int do_dlclose(void *vhandle, int need_fini) end = ppnt->p_vaddr + ppnt->p_memsz; } _dl_munmap((void*)tpnt->loadaddr, end); + /* Free elements in RTLD_LOCAL scope list */ + for (runp = tpnt->rtld_local; runp; runp = tmp) { + tmp = runp->next; + free(runp); + } /* Next, remove tpnt from the loaded_module list */ if (_dl_loaded_modules == tpnt) { _dl_loaded_modules = tpnt->next; |