|
|
| |
#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag)) | #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag)) |
| |
|
#ifndef SUSEIDX |
|
# define SUSEIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + \ |
|
DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM + DT_SUSE_TAGIDX (sym)) |
|
#endif |
|
|
/* We need this string more than once. */ | /* We need this string more than once. */ |
static const char undefined_msg[] = "undefined symbol: "; | static const char undefined_msg[] = "undefined symbol: "; |
| |
|
|
unsigned long int hash; | unsigned long int hash; |
struct sym_val current_value = { NULL, NULL }; | struct sym_val current_value = { NULL, NULL }; |
struct r_scope_elem **scope = symbol_scope; | struct r_scope_elem **scope = symbol_scope; |
|
size_t i = 0; |
| |
/* This sucks mostly - but people sadly don't pass a symtab index, or hashvals ptr in */ | /* This sucks mostly - but people sadly don't pass a symtab index, or hashvals ptr in */ |
const Elf_Symndx *hashvals; | const Elf_Symndx *hashvals; |
|
|
up a versioned symbol. */ | up a versioned symbol. */ |
assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY); | assert (version == NULL || flags == 0 || flags == DL_LOOKUP_ADD_DEPENDENCY); |
| |
size_t i = 0; |
if (__builtin_expect (undef_map != NULL, 1) && |
|
__builtin_expect (undef_map->l_dtneeded.r_nlist != NULL, 0) && |
|
__builtin_expect (*ref != NULL, 1)) |
|
{ |
|
unsigned int idx, noffset; |
|
const ElfW(Sym) *symtab; |
|
ElfW(Addr) direct; |
|
|
|
/* We need a dynsym index ... */ |
|
symtab = (const void *) D_PTR (undef_map, l_info[DT_SYMTAB]); |
|
direct = D_PTR (undef_map, l_info[SUSEIDX(DT_SUSE_DIRECT)]); |
|
|
|
idx = *ref - symtab; |
|
if (__builtin_expect ((GLRO(dl_debug_mask) & DL_DEBUG_DIRECT) != 0, 0)) |
|
_dl_debug_printf ("dynamic symbol index %u from '%s' for %s base direct 0x%x start 0x%x\n", idx, |
|
undef_map->l_name ? undef_map->l_name : "<noname>", |
|
undef_name ? undef_name : "<undef>", |
|
(int) direct, (int) undef_map->l_map_start); |
|
direct += idx * 2; |
|
if (direct >= undef_map->l_map_end || direct <= undef_map->l_map_start) |
|
_dl_debug_printf ("broken: off end of map 0x%x\n", (int) direct); |
|
else |
|
{ |
|
noffset = *(uint16_t *)direct; |
|
if (__builtin_expect ((GLRO(dl_debug_mask) & DL_DEBUG_DIRECT) != 0, 0)) |
|
_dl_debug_printf ("dynamic symbol offset %u from 0x%x\n", noffset, (int) direct); |
|
if (noffset & DT_SUSE_DIRECT_VAGUE) |
|
{ |
|
if (__builtin_expect ((GLRO(dl_debug_mask) & DL_DEBUG_DIRECT) != 0, 0)) |
|
_dl_debug_printf ("vague symbol\n"); |
|
goto normal_lookup; |
|
} |
|
|
|
noffset &= DT_SUSE_DIRECT_MASK; |
|
|
|
if (__builtin_expect (noffset < undef_map->l_dtneeded.r_nlist, 1)) |
|
{ |
|
int res; |
|
struct r_scope_elem direct_elem; |
|
|
|
/* FIXME - requires LD_PRELOAD support ... */ |
|
direct_elem.r_list = undef_map->l_dtneeded.r_list + noffset; |
|
direct_elem.r_nlist = 1; |
|
|
|
if (direct_elem.r_list[0] == skip_map) |
|
goto normal_lookup; /* FIXME - correct ? */ |
|
|
|
res = do_lookup_x (undef_name, hash, *ref, ¤t_value, &direct_elem, |
|
0, version, flags, skip_map, type_class); |
|
if (res > 0) |
|
{ |
|
if (__builtin_expect ((GLRO(dl_debug_mask) & DL_DEBUG_DIRECT) != 0, 0)) |
|
_dl_debug_printf ("direct lookup ...\n"); |
|
goto match; |
|
} |
|
else |
|
_dl_debug_printf ("Error in lookup %u - missing (?) - fallback " |
|
"to deps & then global ? ...\n", res); |
|
} |
|
else if (noffset == DT_SUSE_DIRECT_UNKNOWN) |
|
{ |
|
if (__builtin_expect ((GLRO(dl_debug_mask) & DL_DEBUG_DIRECT) != 0, 0)) |
|
_dl_debug_printf ("unknown/undefined symbol '%s'\n", |
|
undef_name ? undef_name : "<undef>"); |
|
} |
|
else |
|
{ |
|
_dl_debug_printf ("Error: foo symbol '%s' 0 < %u < %u\n", |
|
undef_name ? undef_name : "<undef>", |
|
noffset, undef_map->l_dtneeded.r_nlist); |
|
} |
|
} |
|
} |
|
normal_lookup: |
|
|
if (__builtin_expect (skip_map != NULL, 0)) | if (__builtin_expect (skip_map != NULL, 0)) |
{ | { |
/* Search the relevant loaded objects for a definition. */ | /* Search the relevant loaded objects for a definition. */ |
|
|
return 0; | return 0; |
} | } |
} | } |
|
match: |
if (__builtin_expect (current_value.s == NULL, 0)) | if (__builtin_expect (current_value.s == NULL, 0)) |
{ | { |
if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) | if ((*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) |