summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'ldso')
-rw-r--r--ldso/include/dl-hash.h16
-rw-r--r--ldso/ldso/arm/elfinterp.c6
-rw-r--r--ldso/ldso/avr32/elfinterp.c13
-rw-r--r--ldso/ldso/bfin/elfinterp.c18
-rw-r--r--ldso/ldso/cris/elfinterp.c5
-rw-r--r--ldso/ldso/dl-hash.c20
-rw-r--r--ldso/ldso/i386/elfinterp.c6
-rw-r--r--ldso/ldso/m68k/elfinterp.c15
-rw-r--r--ldso/ldso/mips/elfinterp.c22
-rw-r--r--ldso/ldso/powerpc/elfinterp.c20
-rw-r--r--ldso/ldso/sh/elfinterp.c10
-rw-r--r--ldso/ldso/sh64/elfinterp.c7
-rw-r--r--ldso/ldso/sparc/elfinterp.c24
-rw-r--r--ldso/ldso/x86_64/elfinterp.c20
-rw-r--r--ldso/ldso/xtensa/elfinterp.c11
-rw-r--r--ldso/libdl/libdl.c7
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