diff options
-rw-r--r-- | ldso/include/dl-hash.h | 16 | ||||
-rw-r--r-- | ldso/ldso/arm/elfinterp.c | 6 | ||||
-rw-r--r-- | ldso/ldso/avr32/elfinterp.c | 13 | ||||
-rw-r--r-- | ldso/ldso/bfin/elfinterp.c | 18 | ||||
-rw-r--r-- | ldso/ldso/cris/elfinterp.c | 5 | ||||
-rw-r--r-- | ldso/ldso/dl-hash.c | 20 | ||||
-rw-r--r-- | ldso/ldso/i386/elfinterp.c | 6 | ||||
-rw-r--r-- | ldso/ldso/m68k/elfinterp.c | 15 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 22 | ||||
-rw-r--r-- | ldso/ldso/powerpc/elfinterp.c | 20 | ||||
-rw-r--r-- | ldso/ldso/sh/elfinterp.c | 10 | ||||
-rw-r--r-- | ldso/ldso/sh64/elfinterp.c | 7 | ||||
-rw-r--r-- | ldso/ldso/sparc/elfinterp.c | 24 | ||||
-rw-r--r-- | ldso/ldso/x86_64/elfinterp.c | 20 | ||||
-rw-r--r-- | ldso/ldso/xtensa/elfinterp.c | 11 | ||||
-rw-r--r-- | ldso/libdl/libdl.c | 7 |
16 files changed, 131 insertions, 89 deletions
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index 34bed1b4b..d1f9accc5 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -25,6 +25,11 @@ struct dyn_elf { struct dyn_elf * prev; }; +struct symbol_ref { + const ElfW(Sym) *sym; + struct elf_resolve *tpnt; +}; + struct elf_resolve { /* These entries must be in this order to be compatible with the interface used by gdb to obtain the list of symbols. */ @@ -137,19 +142,14 @@ extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info, unsigned long dynamic_addr, unsigned long dynamic_size); -/* Only need extra arg with some configurations */ -#if !((defined(USE_TLS) && USE_TLS) || defined __FDPIC__) -# define _dl_lookup_hash(n, r, m, c, tpntp) _dl_lookup_hash(n, r, m, c) -# define _dl_find_hash(n, r, m, t, tpntp) _dl_find_hash(n, r, m, t) -#endif extern char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, int type_class, - struct elf_resolve **tpntp); + struct symbol_ref *symbol); static __always_inline char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, int type_class, - struct elf_resolve **tpntp) + struct symbol_ref *symbol) { - return _dl_lookup_hash(name, rpnt, mytpnt, type_class, tpntp); + return _dl_lookup_hash(name, rpnt, mytpnt, type_class, symbol); } extern int _dl_linux_dynamic_link(void); diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index 9bbf92c8c..707b31743 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -189,6 +189,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, unsigned long *reloc_addr; unsigned long symbol_addr; const Elf32_Sym *def = 0; + struct symbol_ref sym_ref; struct elf_resolve *def_mod = 0; int goof = 0; @@ -197,10 +198,12 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; if (symtab_index) { symbol_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, - scope, tpnt, elf_machine_type_class(reloc_type), &def_mod); + scope, tpnt, elf_machine_type_class(reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this might @@ -213,6 +216,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, return 1; } + def_mod = sym_ref.tpnt; } else { /* * Relocs against STN_UNDEF are usually treated as using a diff --git a/ldso/ldso/avr32/elfinterp.c b/ldso/ldso/avr32/elfinterp.c index 797f8513e..2d0dbf366 100644 --- a/ldso/ldso/avr32/elfinterp.c +++ b/ldso/ldso/avr32/elfinterp.c @@ -50,9 +50,8 @@ unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got) strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); symname = strtab + sym->st_name; - new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name, - tpnt->symbol_scope, tpnt, - resolver); + new_addr = (unsigned long) _dl_find_hash(symname, + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); entry = (unsigned long *)(got + local_gotno + sym_index - gotsym); *entry = new_addr; @@ -127,18 +126,20 @@ static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, #if defined(__SUPPORT_LD_DEBUG__) unsigned long old_val; #endif + struct symbol_ref sym_ref; reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { symbol_addr = (unsigned long) - _dl_find_hash(strtab + symtab[symtab_index].st_name, - tpnt->symbol_scope, tpnt, - elf_machine_type_class(reloc_type), NULL); + _dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); /* Allow undefined references to weak symbols */ if (!symbol_addr && diff --git a/ldso/ldso/bfin/elfinterp.c b/ldso/ldso/bfin/elfinterp.c index e8d88bd5a..5accbfc2c 100644 --- a/ldso/ldso/bfin/elfinterp.c +++ b/ldso/ldso/bfin/elfinterp.c @@ -46,11 +46,11 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) ElfW(Sym) *symtab; int symtab_index; char *rel_addr; - struct elf_resolve *new_tpnt; char *new_addr; struct funcdesc_value funcval; struct funcdesc_value volatile *got_entry; char *symname; + struct symbol_ref sym_ref; rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; @@ -59,15 +59,17 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symname= strtab + symtab[symtab_index].st_name; /* Address of GOT entry fix up */ got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset); /* Get the address to be used to fill in the GOT entry. */ - new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &new_tpnt); + new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &sym_ref); if (!new_addr) { - new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &new_tpnt); + new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &sym_ref); if (!new_addr) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -76,7 +78,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) } funcval.entry_point = new_addr; - funcval.got_value = new_tpnt->loadaddr.got_value; + funcval.got_value = sym_ref.tpnt->loadaddr.got_value; #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_bindings) { @@ -165,12 +167,15 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, #if defined (__SUPPORT_LD_DEBUG__) unsigned long old_val; #endif + struct symbol_ref sym_ref; reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr)); reloc_type = ELF_R_TYPE(rpnt->r_info); symtab_index = ELF_R_SYM(rpnt->r_info); symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symname = strtab + symtab[symtab_index].st_name; if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) { @@ -179,7 +184,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, } else { symbol_addr = (unsigned long) - _dl_lookup_hash(symname, scope, NULL, 0, &symbol_tpnt); + _dl_lookup_hash(symname, scope, NULL, 0, &sym_ref); /* * We want to allow undefined references to weak symbols - this might @@ -189,9 +194,10 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, if (!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_progname, symname); _dl_exit (1); } + symbol_tpnt = sym_ref.tpnt; } #if defined (__SUPPORT_LD_DEBUG__) diff --git a/ldso/ldso/cris/elfinterp.c b/ldso/ldso/cris/elfinterp.c index 32ea2da9e..3cb8297e1 100644 --- a/ldso/ldso/cris/elfinterp.c +++ b/ldso/ldso/cris/elfinterp.c @@ -161,11 +161,14 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, #if defined (__SUPPORT_LD_DEBUG__) unsigned long old_val; #endif + struct symbol_ref sym_ref; reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { @@ -174,7 +177,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, symbol_addr = (unsigned long)tpnt->loadaddr; } else { symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), NULL); + elf_machine_type_class(reloc_type), &sym_ref); } if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 0048734ba..6db81a90c 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -269,7 +269,7 @@ _dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long * relocations or when we call an entry in the PLT table for the first time. */ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, - int type_class, struct elf_resolve **tpntp) + int type_class, struct symbol_ref *sym_ref) { struct elf_resolve *tpnt = NULL; ElfW(Sym) *symtab; @@ -283,6 +283,11 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name); #endif + if ((sym_ref) && (sym_ref->sym) && (ELF32_ST_VISIBILITY(sym_ref->sym->st_other) == STV_PROTECTED)) { + sym = sym_ref->sym; + if (mytpnt) + tpnt = mytpnt; + } else for (; rpnt; rpnt = rpnt->next) { tpnt = rpnt->dyn; @@ -337,9 +342,8 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve /* At this point we have found the requested symbol, do binding */ #if defined(USE_TLS) && USE_TLS if (ELF_ST_TYPE(sym->st_info) == STT_TLS) { - _dl_assert(tpntp != NULL); - *tpntp = tpnt; - + _dl_assert(sym_ref != NULL); + sym_ref->tpnt = tpnt; return (char *)sym->st_value; } #endif @@ -355,8 +359,8 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve #endif case STB_GLOBAL: #ifdef __FDPIC__ - if (tpntp) - *tpntp = tpnt; + if (sym_ref) + sym_ref->tpnt = tpnt; #endif return (char *)DL_FIND_HASH_VALUE(tpnt, type_class, sym); default: /* Local symbols not handled here */ @@ -364,8 +368,8 @@ char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve } } #ifdef __FDPIC__ - if (tpntp) - *tpntp = tpnt; + if (sym_ref) + sym_ref->tpnt = tpnt; #endif return weak_result; } diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index a01c1d020..0017c239b 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -168,16 +168,19 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, #if defined (__SUPPORT_LD_DEBUG__) unsigned long old_val; #endif + struct symbol_ref sym_ref; reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symname = strtab + symtab[symtab_index].st_name; if (symtab_index) { symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), &tls_tpnt); + elf_machine_type_class(reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this @@ -187,6 +190,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, if (unlikely(!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) return 1; + tls_tpnt = sym_ref.tpnt; } else { symbol_addr = symtab[symtab_index].st_value; tls_tpnt = tpnt; diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c index 04c301ebb..3dfd50e96 100644 --- a/ldso/ldso/m68k/elfinterp.c +++ b/ldso/ldso/m68k/elfinterp.c @@ -157,7 +157,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, int reloc_type; int symtab_index; char *symname; - ElfW(Sym) *sym; + struct symbol_ref sym_ref; ElfW(Addr) *reloc_addr; ElfW(Addr) symbol_addr; #if defined (__SUPPORT_LD_DEBUG__) @@ -167,19 +167,20 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF_R_TYPE(rpnt->r_info); symtab_index = ELF_R_SYM(rpnt->r_info); - sym = &symtab[symtab_index]; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symbol_addr = 0; - symname = strtab + sym->st_name; + symname = strtab + sym_ref.sym->st_name; if (symtab_index) { symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), NULL); + elf_machine_type_class(reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this * might have been intentional. We should not be linking local * symbols here, so all bases should be covered. */ - if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + if (unlikely(!symbol_addr && ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit(1); } @@ -230,12 +231,12 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, if (_dl_debug_move) _dl_dprintf(_dl_debug_file, "\t%s move %d bytes from %x to %x\n", - symname, sym->st_size, + symname, sym_ref.sym->st_size, symbol_addr, reloc_addr); #endif _dl_memcpy ((void *) reloc_addr, (void *) symbol_addr, - sym->st_size); + sym_ref.sym->st_size); } else _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); break; diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index a56ee81b4..2886f333d 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -212,23 +212,27 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, case R_MIPS_TLS_TPREL32: # endif { - struct elf_resolve *tpnt_tls = NULL; + struct elf_resolve *tls_tpnt = NULL; + struct symbol_ref sym_ref; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) { symbol_addr = (unsigned long) _dl_find_hash(symname, tpnt->symbol_scope, - tpnt, elf_machine_type_class(reloc_type), &tpnt_tls); + tpnt, elf_machine_type_class(reloc_type), &sym_ref); + tls_tpnt = sym_ref.tpnt; } - /* In case of a TLS reloc, tpnt_tls NULL means we have an 'anonymous' + /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous' symbol. This is the case for a static tls variable, so the lookup module is just that one is referencing the tls variable. */ - if (!tpnt_tls) - tpnt_tls = tpnt; + if (!tls_tpnt) + tls_tpnt = tpnt; switch (reloc_type) { case R_MIPS_TLS_DTPMOD64: case R_MIPS_TLS_DTPMOD32: - if (tpnt_tls) - *(ElfW(Word) *)reloc_addr = tpnt_tls->l_tls_modid; + if (tls_tpnt) + *(ElfW(Word) *)reloc_addr = tls_tpnt->l_tls_modid; #ifdef __SUPPORT_LD_DEBUG__ _dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n", symname, old_val, *((unsigned int *)reloc_addr)); @@ -247,9 +251,9 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, case R_MIPS_TLS_TPREL32: case R_MIPS_TLS_TPREL64: - CHECK_STATIC_TLS((struct link_map *)tpnt_tls); + CHECK_STATIC_TLS((struct link_map *)tls_tpnt); *(ElfW(Word) *)reloc_addr += - TLS_TPREL_VALUE (tpnt_tls, symbol_addr); + TLS_TPREL_VALUE (tls_tpnt, symbol_addr); #ifdef __SUPPORT_LD_DEBUG__ _dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n", symname, old_val, *((unsigned int *)reloc_addr)); diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c index 855c040d3..dd35eef54 100644 --- a/ldso/ldso/powerpc/elfinterp.c +++ b/ldso/ldso/powerpc/elfinterp.c @@ -187,7 +187,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, { int reloc_type; int symtab_index; - ElfW(Sym) *sym; + struct symbol_ref sym_ref; Elf32_Addr *reloc_addr; Elf32_Addr finaladdr; struct elf_resolve *tls_tpnt = NULL; @@ -201,21 +201,23 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, reloc_addr = (Elf32_Addr *)(intptr_t) (symbol_addr + (unsigned long) rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); - sym = &symtab[symtab_index]; - symname = strtab + sym->st_name; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + sym_ref.sym->st_name; if (symtab_index) { symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), &tls_tpnt); + elf_machine_type_class(reloc_type), &sym_ref); /* We want to allow undefined references to weak symbols - this might * have been intentional. We should not be linking local symbols * here, so all bases should be covered. */ if (unlikely(!symbol_addr - && (ELF32_ST_TYPE(sym->st_info) != STT_TLS - && ELF32_ST_BIND(sym->st_info) != STB_WEAK))) + && (ELF32_ST_TYPE(sym_ref.sym->st_info) != STT_TLS + && ELF32_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) return 1; + tls_tpnt = sym_ref.tpnt; } else { - symbol_addr = sym->st_value; + symbol_addr = sym_ref.sym->st_value; tls_tpnt = tpnt; } #if defined (__SUPPORT_LD_DEBUG__) @@ -265,10 +267,10 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, #if defined (__SUPPORT_LD_DEBUG__) if (_dl_debug_move) _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", - symname, sym->st_size, + symname, sym_ref.sym->st_size, symbol_addr, reloc_addr); #endif - _dl_memcpy((char *) reloc_addr, (char *) finaladdr, sym->st_size); + _dl_memcpy((char *) reloc_addr, (char *) finaladdr, sym_ref.sym->st_size); goto out_nocode; /* No code code modified */ case R_PPC_ADDR16_HA: finaladdr += 0x8000; /* fall through. */ diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c index 715eadc15..be3b98cf6 100644 --- a/ldso/ldso/sh/elfinterp.c +++ b/ldso/ldso/sh/elfinterp.c @@ -161,16 +161,19 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, #endif struct elf_resolve *tls_tpnt = NULL; + struct symbol_ref sym_ref; reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; - symname = strtab + symtab[symtab_index].st_name; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; if (symtab_index) { + symname = strtab + symtab[symtab_index].st_name; symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), &tls_tpnt); + elf_machine_type_class(reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this might * have been intentional. We should not be linking local symbols @@ -181,11 +184,12 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) && (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_progname, symname); /* Let the caller to handle the error: it may be non fatal if called from dlopen */ return 1; } + tls_tpnt = sym_ref.tpnt; } #if defined (__SUPPORT_LD_DEBUG__) diff --git a/ldso/ldso/sh64/elfinterp.c b/ldso/ldso/sh64/elfinterp.c index 74fda04dc..990aed155 100644 --- a/ldso/ldso/sh64/elfinterp.c +++ b/ldso/ldso/sh64/elfinterp.c @@ -173,11 +173,14 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope, #ifdef __SUPPORT_LD_DEBUG__ unsigned long old_val; #endif + struct symbol_ref sym_ref; reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; lsb = !!(symtab[symtab_index].st_other & STO_SH5_ISA32); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symname = strtab + symtab[symtab_index].st_name; reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long)rpnt->r_offset); @@ -186,7 +189,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope, int stb; symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), NULL); + elf_machine_type_class(reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this @@ -197,7 +200,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope, if (stb != STB_WEAK && !symbol_addr) { _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", - _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_progname, symname); _dl_exit (1); } } diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c index 56335cb5c..443f65bde 100644 --- a/ldso/ldso/sparc/elfinterp.c +++ b/ldso/ldso/sparc/elfinterp.c @@ -171,7 +171,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, int symtab_index; char *symname; struct elf_resolve *tls_tpnt = 0; - ElfW(Sym) *sym; + struct symbol_ref sym_ref; ElfW(Addr) *reloc_addr; ElfW(Addr) symbol_addr; #if defined (__SUPPORT_LD_DEBUG__) @@ -181,29 +181,31 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF_R_TYPE(rpnt->r_info); symtab_index = ELF_R_SYM(rpnt->r_info); - sym = &symtab[symtab_index]; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symbol_addr = 0; - symname = strtab + sym->st_name; + symname = strtab + sym_ref.sym->st_name; if (symtab_index) { symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), &tls_tpnt); + elf_machine_type_class(reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this * might have been intentional. We should not be linking local * symbols here, so all bases should be covered. */ - if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym->st_info) != STT_TLS) - && (ELF_ST_BIND(sym->st_info) != STB_WEAK))) { + if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS) + && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) { /* This may be non-fatal if called from dlopen. */ return 1; } + tls_tpnt = sym_ref.tpnt; } else { /* Relocs against STN_UNDEF are usually treated as using a * symbol value of zero, and using the module containing the * reloc itself. */ - symbol_addr = sym->st_value; + symbol_addr = sym_ref.sym->st_value; tls_tpnt = tpnt; } @@ -262,13 +264,13 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, if (_dl_debug_move) _dl_dprintf(_dl_debug_file, "\t%s move %d bytes from %x to %x\n", - symname, sym->st_size, + symname, sym_ref.sym->st_size, symbol_addr, reloc_addr); #endif _dl_memcpy((char *)reloc_addr, (char *)symbol_addr, - sym->st_size); + sym_ref.sym->st_size); } else _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); break; @@ -280,7 +282,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, case R_SPARC_TLS_DTPOFF32: /* During relocation all TLS symbols are defined and used. * Therefore the offset is already correct. */ - *reloc_addr = sym->st_value + rpnt->r_addend; + *reloc_addr = sym_ref.sym->st_value + rpnt->r_addend; break; case R_SPARC_TLS_TPOFF32: @@ -289,7 +291,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, * It is a negative value which will be added to the * thread pointer. */ CHECK_STATIC_TLS ((struct link_map *) tls_tpnt); - *reloc_addr = sym->st_value - tls_tpnt->l_tls_offset + rpnt->r_addend; + *reloc_addr = sym_ref.sym->st_value - tls_tpnt->l_tls_offset + rpnt->r_addend; break; #endif default: diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c index fce2ec7be..15d773388 100644 --- a/ldso/ldso/x86_64/elfinterp.c +++ b/ldso/ldso/x86_64/elfinterp.c @@ -158,7 +158,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, int symtab_index; char *symname; struct elf_resolve *tls_tpnt = 0; - ElfW(Sym) *sym; + struct symbol_ref sym_ref; ElfW(Addr) *reloc_addr; ElfW(Addr) symbol_addr; #if defined (__SUPPORT_LD_DEBUG__) @@ -168,28 +168,30 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); reloc_type = ELF_R_TYPE(rpnt->r_info); symtab_index = ELF_R_SYM(rpnt->r_info); - sym = &symtab[symtab_index]; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symbol_addr = 0; - symname = strtab + sym->st_name; + symname = strtab + sym_ref.sym->st_name; if (symtab_index) { symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, - elf_machine_type_class(reloc_type), &tls_tpnt); + elf_machine_type_class(reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this * might have been intentional. We should not be linking local * symbols here, so all bases should be covered. */ - if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym->st_info) != STT_TLS) - && (ELF_ST_BIND(sym->st_info) != STB_WEAK))) { + if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS) + && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) { /* This may be non-fatal if called from dlopen. */ return 1; } + tls_tpnt = sym_ref.tpnt; } else { /* Relocs against STN_UNDEF are usually treated as using a * symbol value of zero, and using the module containing the * reloc itself. */ - symbol_addr = sym->st_value; + symbol_addr = sym_ref.sym->st_value; tls_tpnt = tpnt; } @@ -249,13 +251,13 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, if (_dl_debug_move) _dl_dprintf(_dl_debug_file, "\t%s move %d bytes from %x to %x\n", - symname, sym->st_size, + symname, sym_ref.sym->st_size, symbol_addr, reloc_addr); #endif _dl_memcpy((char *)reloc_addr, (char *)symbol_addr, - sym->st_size); + sym_ref.sym->st_size); } else _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); break; diff --git a/ldso/ldso/xtensa/elfinterp.c b/ldso/ldso/xtensa/elfinterp.c index 48281913d..8eb600916 100644 --- a/ldso/ldso/xtensa/elfinterp.c +++ b/ldso/ldso/xtensa/elfinterp.c @@ -146,7 +146,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, int reloc_type; int symtab_index; char *symname; - Elf32_Sym *sym; + struct symbol_ref sym_ref; Elf32_Addr *reloc_addr; Elf32_Addr symbol_addr; #if defined (__SUPPORT_LD_DEBUG__) @@ -156,14 +156,15 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset); reloc_type = ELF32_R_TYPE (rpnt->r_info); symtab_index = ELF32_R_SYM (rpnt->r_info); - sym = &symtab[symtab_index]; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; symbol_addr = 0; - symname = strtab + sym->st_name; + symname = strtab + sym_ref.sym->st_name; if (symtab_index) { symbol_addr = (Elf32_Addr) _dl_find_hash (symname, scope, tpnt, - elf_machine_type_class (reloc_type), NULL); + elf_machine_type_class (reloc_type), &sym_ref); /* * We want to allow undefined references to weak symbols - this might @@ -171,7 +172,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, * here, so all bases should be covered. */ if (unlikely (!symbol_addr && - ELF32_ST_BIND (sym->st_info) != STB_WEAK)) { + ELF32_ST_BIND (sym_ref.sym->st_info) != STB_WEAK)) { _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); _dl_exit (1); diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 3957e846f..b88bc4819 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -613,6 +613,7 @@ void *dlsym(void *vhandle, const char *name) struct dyn_elf *rpnt; void *ret; struct elf_resolve *tls_tpnt = NULL; + struct symbol_ref sym_ref = { NULL, NULL }; /* Nastiness to support underscore prefixes. */ #ifdef __UCLIBC_UNDERSCORES__ char tmp_buf[80]; @@ -667,13 +668,13 @@ void *dlsym(void *vhandle, const char *name) tpnt = NULL; if (handle == _dl_symbol_tables) tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */ - ret = _dl_find_hash(name2, handle, NULL, 0, &tls_tpnt); + ret = _dl_find_hash(name2, handle, tpnt, 0, &sym_ref); #if defined(USE_TLS) && USE_TLS && defined SHARED - if (tls_tpnt) { + if (sym_ref.tpnt) { /* The found symbol is a thread-local storage variable. Return the address for to the current thread. */ - ret = _dl_tls_symaddr ((struct link_map *)tls_tpnt, (Elf32_Addr)ret); + ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret); } #endif |