struct dyn_elf * prev;
};
- struct sym_val {
- const ElfW(Sym) *s;
- struct elf_resolve *m;
+ struct symbol_ref {
+ const ElfW(Sym) *sym;
+ struct elf_resolve *tpnt;
};
+/* Structure to describe a single list of scope elements. The lookup
+ functions get passed an array of pointers to such structures. */
+struct r_scope_elem {
+ struct elf_resolve **r_list; /* Array of maps for the scope. */
+ unsigned int r_nlist; /* Number of entries in the scope. */
+ struct r_scope_elem *next;
+};
+
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. */
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, s, c, tpnt) _dl_lookup_hash(n, r, m, s, c)
- # define _dl_find_hash(n, r, m, s, t, tpntp) _dl_find_hash(n, r, m, s, t)
- #endif
- extern char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope,
- struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class,
- struct elf_resolve **tpntp);
- static __always_inline char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
- struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class,
- struct elf_resolve **tpntp)
- {
- return _dl_lookup_hash(name, scope, mytpnt, symbol, type_class, tpntp);
- }
-extern char *_dl_find_hash(const char *name, struct dyn_elf *rpnt,
++extern char *_dl_find_hash(const char *name, struct r_scope_elem *scope,
+ struct elf_resolve *mytpnt, int type_class,
+ struct symbol_ref *symbol);
extern int _dl_linux_dynamic_link(void);
got_addr = (char **) instr_addr;
/* Get the address of the GOT entry */
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope,
+ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope,
- tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+ tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
_dl_progname, symname);
return 1;
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
+ def_mod = sym_ref.tpnt;
} else {
/*
* Relocs against STN_UNDEF are usually treated as using a
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,
+ new_addr = (unsigned long) _dl_find_hash(symname,
- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
+ &_dl_loaded_modules->symbol_scope, tpnt,
- NULL, 0, resolver);
++ ELF_RTYPE_CLASS_PLT, NULL);
entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
*entry = new_addr;
_dl_progname, symname);
return 0;
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
}
#if defined(__SUPPORT_LD_DEBUG__)
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, &_dl_loaded_modules->symbol_scope, NULL, NULL, 0, &new_tpnt);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, NULL, 0, &sym_ref);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, 0, &sym_ref);
if (!new_addr) {
- new_addr = _dl_lookup_hash(symname, NULL, NULL, NULL, 0, &new_tpnt);
+ new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref);
if (!new_addr) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
_dl_progname, symname);
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);
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
+ symbol_tpnt = sym_ref.tpnt;
}
#if defined (__SUPPORT_LD_DEBUG__)
got_addr = (char **)instr_addr;
/* Get the address of the GOT entry. */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
_dl_exit(1);
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
_dl_exit(1);
}
+
symbol_addr += rpnt->r_addend;
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
}
#if defined (__SUPPORT_LD_DEBUG__)
#define debug_reloc(symtab, strtab, rpnt)
#endif /* __SUPPORT_LD_DEBUG__ */
- const ElfW(Sym) *ref, struct sym_val *value, int type_class)
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+static void
+internal_function
+_dl_debug_lookup (const char *undef_name, struct elf_resolve *undef_map,
- struct elf_resolve *tls_tpnt = NULL;
- struct sym_val val = { NULL, NULL };
++ const ElfW(Sym) *ref, struct symbol_ref *value, int type_class)
+{
+#ifdef SHARED
+ unsigned long symbol_addr;
+
+ if (_dl_trace_prelink)
+ {
+ int conflict = 0;
- undef_map, &val, type_class, &tls_tpnt);
++ struct symbol_ref val = { NULL, NULL };
+
+ if ((_dl_trace_prelink_map == NULL
+ || _dl_trace_prelink_map == _dl_loaded_modules)
+ && undef_map != _dl_loaded_modules)
+ {
+ symbol_addr = (unsigned long)
+ _dl_find_hash(undef_name, &undef_map->symbol_scope,
- if (val.s != value->s || val.m != value->m)
++ undef_map, type_class, &val);
+
- if (value->s
- && (__builtin_expect (ELF_ST_TYPE(value->s->st_info)
++ if (val.sym != value->sym || val.tpnt != value->tpnt)
+ conflict = 1;
+ }
+
- (size_t) (value->m ? value->m->mapaddr : 0),
- (size_t) (value->s ? value->s->st_value : 0));
++ if (value->sym
++ && (__builtin_expect (ELF_ST_TYPE(value->sym->st_info)
+ == STT_TLS, 0)))
+ type_class = 4;
+
+ if (conflict
+ || _dl_trace_prelink_map == undef_map
+ || _dl_trace_prelink_map == NULL
+ || type_class == 4)
+ {
+ _dl_dprintf (1, "%s %x %x -> %x %x ",
+ conflict ? "conflict" : "lookup",
+ (size_t) undef_map->mapaddr,
+ (size_t) (((ElfW(Addr)) ref) - undef_map->mapaddr),
- (size_t) (val.m ? val.m->mapaddr : 0),
- (size_t) (val.s ? val.s->st_value : 0));
++ (size_t) (value->tpnt ? value->tpnt->mapaddr : 0),
++ (size_t) (value->sym ? value->sym->st_value : 0));
+ if (conflict)
+ _dl_dprintf (1, "x %x %x ",
++ (size_t) (val.tpnt ? val.tpnt->mapaddr : 0),
++ (size_t) (val.sym ? val.sym->st_value : 0));
+ _dl_dprintf (1, "/%x %s\n", type_class, undef_name);
+ }
+}
+#endif
+}
+
+#else
+#define _dl_debug_lookup(undef_name, undef_map, ref, value, type_class)
+#endif
* 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_lookup_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,
- struct sym_val *symbol, int type_class, struct elf_resolve **tpntp)
-char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt,
++char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,
+ int type_class, struct symbol_ref *sym_ref)
{
struct elf_resolve *tpnt = NULL;
ElfW(Sym) *symtab;
unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name);
#endif
- for (; rpnt; rpnt = rpnt->next) {
- tpnt = rpnt->dyn;
-
- 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 ((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 (loop_scope = scope; loop_scope && !sym; loop_scope = loop_scope->next) {
+ for (i = 0; i < loop_scope->r_nlist; i++) {
+ tpnt = loop_scope->r_list[i];
+
+ 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;
}
- 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;
+ /* Don't search the executable when resolving a copy reloc. */
+ if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
+ continue;
- /* If the hash table is empty there is nothing to do here. */
- if (tpnt->nbucket == 0)
- continue;
+ /* If the hash table is empty there is nothing to do here. */
+ if (tpnt->nbucket == 0)
+ continue;
- symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
+ symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
#ifdef __LDSO_GNU_HASH_SUPPORT__
- /* Prefer GNU hash style, if any */
- if (tpnt->l_gnu_bitmask) {
- sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
- if (sym != NULL)
- /* If sym has been found, do not search further */
- break;
- } else {
+ /* Prefer GNU hash style, if any */
+ if (tpnt->l_gnu_bitmask) {
+ sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class);
+ if (sym != NULL)
+ /* If sym has been found, do not search further */
+ break;
+ } else {
#endif
- /* Use the old SysV-style hash table */
+ /* Use the old SysV-style hash table */
- /* Calculate the old sysv hash number only once */
- if (elf_hash_number == 0xffffffff)
- elf_hash_number = _dl_elf_hash((const unsigned char *)name);
+ /* Calculate the old sysv hash number only once */
+ if (elf_hash_number == 0xffffffff)
+ elf_hash_number = _dl_elf_hash((const unsigned char *)name);
- sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
- if (sym != NULL)
- break;
+ sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class);
+ if (sym != NULL)
+ /* If sym has been found, do not search further */
+ break;
#ifdef __LDSO_GNU_HASH_SUPPORT__
- }
+ }
#endif
- } /* end of for (; rpnt; rpnt = rpnt->next) { */
+ } /* End of inner for */
+ }
if (sym) {
- if (symbol) {
- symbol->s = sym;
- symbol->m = tpnt;
++ if (sym_ref) {
++ sym_ref->sym = sym;
++ sym_ref->tpnt = tpnt;
+ }
/* 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) {
got_addr = (char **)instr_addr;
/* Get the address of the GOT entry. */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
_dl_exit(1);
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;
-
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
- ¤t_value, elf_machine_type_class(reloc_type));
++ &sym_ref, elf_machine_type_class(reloc_type));
+ tls_tpnt = sym_ref.tpnt;
} else {
- if (symtab_index)
- symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type),
- &symtab[symtab_index]);
- else
- symbol_addr = symtab[symtab_index].st_value;
+ symbol_addr = symtab[symtab_index].st_value;
tls_tpnt = tpnt;
}
ElfW(Phdr) *ppnt;
ElfW(Dyn) *dpnt;
char *lpntstr;
- unsigned int i, cnt, k, nscope_elem;
- unsigned int i;
++ unsigned int i, cnt, nscope_elem;
int unlazy = 0, trace_loaded_objects = 0;
struct dyn_elf *rpnt;
struct elf_resolve *tcurr;
tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
#endif
tpnt = NULL;
+
+ /*
+ * Allocate the global scope array.
+ */
+ scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
+
+ for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next)
+ scope_elem_list[i++] = tcurr;
+
+ _dl_loaded_modules->symbol_scope.r_list = scope_elem_list;
+ _dl_loaded_modules->symbol_scope.r_nlist = nscope_elem;
+ /*
+ * The symbol scope of the application, that is the first entry of the
+ * _dl_loaded_modules list, is just the global scope to be used for the
+ * symbol lookup.
+ */
+ global_scope = &_dl_loaded_modules->symbol_scope;
+
+ /* Build the local scope for each loaded modules. */
+ local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
+ i = 1;
+ for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
++ unsigned int k;
+ cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
+ tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
+ tcurr->symbol_scope.r_nlist = cnt;
+ _dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *));
+ /* Restoring the init_flag.*/
+ for (k = 1; k < nscope_elem; k++)
+ scope_elem_list[k]->init_flag &= ~DL_RESERVED;
}
+ _dl_free(local_scope);
+
#ifdef __LDSO_LDD_SUPPORT__
- /* End of the line for ldd.... */
- if (trace_loaded_objects) {
- _dl_dprintf(1, "\t%s => %s (%x)\n",
- rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1,
- rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr));
+ /* Exit if LD_TRACE_LOADED_OBJECTS is on. */
+ if (trace_loaded_objects && !_dl_trace_prelink)
_dl_exit(0);
- }
#endif
#if defined(USE_TLS) && USE_TLS
* ld.so.1, so we have to look up each symbol individually.
*/
- _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, NULL, 0, NULL);
- _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", _dl_symbol_tables, NULL, 0, NULL);
++ _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
if (_dl_envp)
*_dl_envp = (unsigned long) envp;
/* 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(__C_SYMBOL_PREFIX__ "malloc",
- global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++ global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
#if defined(USE_TLS) && USE_TLS
/* Find the real functions and make ldso functions use them from now on */
_dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++ _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
_dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++ _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
_dl_free_function = (void (*)(void *)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- _dl_find_hash(__C_SYMBOL_PREFIX__ "free", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++ _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
_dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL);
++ _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
#endif
got_addr = (char **)instr_addr;
/* Get the address of the GOT entry. */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
_dl_exit(1);
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
_dl_exit(1);
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
}
#if defined (__SUPPORT_LD_DEBUG__)
symname = strtab + sym->st_name;
new_addr = (unsigned long) _dl_find_hash(symname,
- &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
_dl_progname, symname);
got_addr = (char **)instr_addr;
/* Get the address of the GOT entry. */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
_dl_exit(1);
unsigned long old_val=0;
#endif
- struct sym_val current_value = { NULL, NULL };
-
++ struct symbol_ref sym_ref = { NULL, NULL };
/* Now parse the relocation information */
rel_size = rel_size / sizeof(ElfW(Rel));
rpnt = (ELF_RELOC *) rel_addr;
strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT];
++
for (i = 0; i < rel_size; i++, rpnt++) {
reloc_addr = (unsigned long *) (tpnt->loadaddr +
(unsigned long) rpnt->r_offset);
if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {
symbol_addr = (unsigned long)_dl_find_hash(symname,
- tpnt->symbol_scope,
+ scope,
- tpnt, ¤t_value,
- elf_machine_type_class(reloc_type), NULL);
+ 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))
return 1;
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
}
if (!symtab_index) {
/* Relocs against STN_UNDEF are usually treated as using a
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,
+ symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
- tpnt, ¤t_value, 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:
}
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
}
}
else if (sym->st_shndx == SHN_COMMON) {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
}
else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
*got_entry != sym->st_value && tmp_lazy) {
}
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
}
got_entry++;
/* Get the address of the GOT entry */
finaladdr = (Elf32_Addr) _dl_find_hash(symname,
- &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!finaladdr)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);
_dl_exit(1);
* 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;
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
+ 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__)
old_val = *reloc_addr;
#endif
got_addr = (char **) instr_addr;
/* Get the address of the GOT entry */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
if (symtab_index) {
symname = strtab + symtab[symtab_index].st_name;
- if (ELF32_ST_VISIBILITY(symtab[symtab_index].st_other)
- != STV_PROTECTED) {
- symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, ¤t_value,
- elf_machine_type_class(reloc_type), &tls_tpnt);
- /*
- * 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 (!symbol_addr
- && (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);
-
- /* Let the caller to handle the error: it may be non fatal if called from dlopen */
- return 1;
- }
- } else
- /* Resolve protected symbols locally */
- symbol_addr = DL_FIND_HASH_VALUE(tpnt, elf_machine_type_class(reloc_type),
- &symtab[symtab_index]);
-
+ symbol_addr = (unsigned long) _dl_find_hash(symname, scope, 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 (!symbol_addr
+ && (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, symname);
+
+ /* Let the caller to handle the error: it may be non fatal if called from dlopen */
+ return 1;
+ }
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
- ¤t_value, elf_machine_type_class(reloc_type));
++ &sym_ref, elf_machine_type_class(reloc_type));
+ tls_tpnt = sym_ref.tpnt;
}
#if defined (__SUPPORT_LD_DEBUG__)
/* Get the address of the GOT entry */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
_dl_progname, symname);
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);
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
}
#ifdef __SUPPORT_LD_DEBUG__
got_addr = (char **)instr_addr;
/* Get the address of the GOT entry */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
_dl_exit(1);
return 1;
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
+ 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
got_addr = (char **)instr_addr;
/* Get the address of the GOT entry. */
- new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, NULL, ELF_RTYPE_CLASS_PLT, NULL);
- new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
++ new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);
_dl_exit(1);
/* This may be non-fatal if called from dlopen. */
return 1;
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
+ 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
_dl_progname, symname);
_dl_exit (1);
}
- ¤t_value, elf_machine_type_class(reloc_type));
+ if (_dl_trace_prelink)
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
++ &sym_ref, elf_machine_type_class(reloc_type));
}
#if defined (__SUPPORT_LD_DEBUG__)
tpnt = NULL;
if (handle == _dl_symbol_tables)
tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */
- ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, NULL, NULL, 0, &tls_tpnt);
- ret = _dl_find_hash(name2, handle, tpnt, 0, &sym_ref);
++ ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, 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