@ -31,9 +31,8 @@
# include <assert.h>
/* Return nonzero if do_lookup_x:check_match should consider SYM to
fail to match a symbol reference for some machine - specific
reason . */
/* Return nonzero if check_match should consider SYM to fail to match a
symbol reference for some machine - specific reason . */
# ifndef ELF_MACHINE_SYM_NO_MATCH
# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
# endif
@ -75,67 +74,25 @@ struct sym_val
# define bump_num_relocations() ((void) 0)
# endif
/* Inner part of the lookup functions. We return a value > 0 if we
found the symbol , the value 0 if nothing is found and < 0 if
something bad happened . */
static int
__attribute_noinline__
do_lookup_x ( const char * undef_name , uint_fast32_t new_hash ,
unsigned long int * old_hash , const ElfW ( Sym ) * ref ,
struct sym_val * result , struct r_scope_elem * scope , size_t i ,
const struct r_found_version * const version , int flags ,
struct link_map * skip , int type_class , struct link_map * undef_map )
/* Utility function for do_lookup_x. The caller is called with undef_name,
ref , version , flags and type_class , and those are passed as the first
five arguments . The caller then computes sym , symidx , strtab , and map
and passes them as the next four arguments . Lastly the caller passes in
versioned_sym and num_versions which are modified by check_match during
the checking process . */
static const ElfW ( Sym ) *
check_match ( const char * const undef_name ,
const ElfW ( Sym ) * const ref ,
const struct r_found_version * const version ,
const int flags ,
const int type_class ,
const ElfW ( Sym ) * const sym ,
const Elf_Symndx symidx ,
const char * const strtab ,
const struct link_map * const map ,
const ElfW ( Sym ) * * const versioned_sym ,
int * const num_versions )
{
size_t n = scope - > r_nlist ;
/* Make sure we read the value before proceeding. Otherwise we
might use r_list pointing to the initial scope and r_nlist being
the value after a resize . That is the only path in dl - open . c not
protected by GSCOPE . A read barrier here might be to expensive . */
__asm volatile ( " " : " +r " ( n ) , " +m " ( scope - > r_list ) ) ;
struct link_map * * list = scope - > r_list ;
do
{
/* These variables are used in the nested function. */
Elf_Symndx symidx ;
int num_versions = 0 ;
const ElfW ( Sym ) * versioned_sym = NULL ;
const struct link_map * map = list [ i ] - > l_real ;
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
if ( map = = skip )
continue ;
/* Don't search the executable when resolving a copy reloc. */
if ( ( type_class & ELF_RTYPE_CLASS_COPY ) & & map - > l_type = = lt_executable )
continue ;
/* Do not look into objects which are going to be removed. */
if ( map - > l_removed )
continue ;
/* Print some debugging info if wanted. */
if ( __glibc_unlikely ( GLRO ( dl_debug_mask ) & DL_DEBUG_SYMBOLS ) )
_dl_debug_printf ( " symbol=%s; lookup in file=%s [%lu] \n " ,
undef_name , DSO_FILENAME ( map - > l_name ) ,
map - > l_ns ) ;
/* If the hash table is empty there is nothing to do here. */
if ( map - > l_nbuckets = = 0 )
continue ;
/* The tables for this map. */
const ElfW ( Sym ) * symtab = ( const void * ) D_PTR ( map , l_info [ DT_SYMTAB ] ) ;
const char * strtab = ( const void * ) D_PTR ( map , l_info [ DT_STRTAB ] ) ;
/* Nested routine to check whether the symbol matches. */
const ElfW ( Sym ) *
__attribute_noinline__
check_match ( const ElfW ( Sym ) * sym )
{
unsigned int stt = ELFW ( ST_TYPE ) ( sym - > st_info ) ;
assert ( ELF_RTYPE_CLASS_PLT = = 1 ) ;
if ( __builtin_expect ( ( sym - > st_value = = 0 /* No value. */
@ -216,9 +173,9 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
{
/* Don't accept hidden symbols. */
if ( ( verstab [ symidx ] & 0x8000 ) = = 0
& & num_versions + + = = 0 )
& & ( * num_versions ) + + = = 0 )
/* No version so far. */
versioned_sym = sym ;
* versioned_sym = sym ;
return NULL ;
}
@ -227,7 +184,62 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
/* There cannot be another entry for this symbol so stop here. */
return sym ;
}
}
/* Inner part of the lookup functions. We return a value > 0 if we
found the symbol , the value 0 if nothing is found and < 0 if
something bad happened . */
static int
__attribute_noinline__
do_lookup_x ( const char * undef_name , uint_fast32_t new_hash ,
unsigned long int * old_hash , const ElfW ( Sym ) * ref ,
struct sym_val * result , struct r_scope_elem * scope , size_t i ,
const struct r_found_version * const version , int flags ,
struct link_map * skip , int type_class , struct link_map * undef_map )
{
size_t n = scope - > r_nlist ;
/* Make sure we read the value before proceeding. Otherwise we
might use r_list pointing to the initial scope and r_nlist being
the value after a resize . That is the only path in dl - open . c not
protected by GSCOPE . A read barrier here might be to expensive . */
__asm volatile ( " " : " +r " ( n ) , " +m " ( scope - > r_list ) ) ;
struct link_map * * list = scope - > r_list ;
do
{
/* These variables are used in the nested function. */
Elf_Symndx symidx ;
int num_versions = 0 ;
const ElfW ( Sym ) * versioned_sym = NULL ;
const struct link_map * map = list [ i ] - > l_real ;
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
if ( map = = skip )
continue ;
/* Don't search the executable when resolving a copy reloc. */
if ( ( type_class & ELF_RTYPE_CLASS_COPY ) & & map - > l_type = = lt_executable )
continue ;
/* Do not look into objects which are going to be removed. */
if ( map - > l_removed )
continue ;
/* Print some debugging info if wanted. */
if ( __glibc_unlikely ( GLRO ( dl_debug_mask ) & DL_DEBUG_SYMBOLS ) )
_dl_debug_printf ( " symbol=%s; lookup in file=%s [%lu] \n " ,
undef_name , DSO_FILENAME ( map - > l_name ) ,
map - > l_ns ) ;
/* If the hash table is empty there is nothing to do here. */
if ( map - > l_nbuckets = = 0 )
continue ;
/* The tables for this map. */
const ElfW ( Sym ) * symtab = ( const void * ) D_PTR ( map , l_info [ DT_SYMTAB ] ) ;
const char * strtab = ( const void * ) D_PTR ( map , l_info [ DT_STRTAB ] ) ;
const ElfW ( Sym ) * sym ;
const ElfW ( Addr ) * bitmask = map - > l_gnu_bitmask ;
@ -254,7 +266,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
if ( ( ( * hasharr ^ new_hash ) > > 1 ) = = 0 )
{
symidx = hasharr - map - > l_gnu_chain_zero ;
sym = check_match ( & symtab [ symidx ] ) ;
sym = check_match ( undef_name , ref , version , flags ,
type_class , & symtab [ symidx ] , symidx ,
strtab , map , & versioned_sym ,
& num_versions ) ;
if ( sym ! = NULL )
goto found_it ;
}
@ -276,7 +291,10 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
symidx ! = STN_UNDEF ;
symidx = map - > l_chain [ symidx ] )
{
sym = check_match ( & symtab [ symidx ] ) ;
sym = check_match ( undef_name , ref , version , flags ,
type_class , & symtab [ symidx ] , symidx ,
strtab , map , & versioned_sym ,
& num_versions ) ;
if ( sym ! = NULL )
goto found_it ;
}