diff options
-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; |