@ -40,6 +40,24 @@ static int checkver(Verdef *def, int vsym, const char *vername, char *strings)
# define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON)
# define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON)
# define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
# define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
static size_t count_syms_gnu ( uint32_t * gh )
{
size_t nsym , i ;
uint32_t * buckets = gh + 4 + ( gh [ 2 ] * sizeof ( size_t ) / 4 ) ;
uint32_t * hashval ;
for ( i = nsym = 0 ; i < gh [ 0 ] ; i + + ) {
if ( buckets [ i ] > nsym )
nsym = buckets [ i ] ;
}
if ( nsym ) {
hashval = buckets + gh [ 0 ] + ( nsym - gh [ 1 ] ) ;
do nsym + + ;
while ( ! ( * hashval + + & 1 ) ) ;
}
return nsym ;
}
void * __vdsosym ( const char * vername , const char * name )
void * __vdsosym ( const char * vername , const char * name )
{
{
size_t i ;
size_t i ;
@ -60,6 +78,7 @@ void *__vdsosym(const char *vername, const char *name)
char * strings = 0 ;
char * strings = 0 ;
Sym * syms = 0 ;
Sym * syms = 0 ;
Elf_Symndx * hashtab = 0 ;
Elf_Symndx * hashtab = 0 ;
uint32_t * ghashtab = 0 ;
uint16_t * versym = 0 ;
uint16_t * versym = 0 ;
Verdef * verdef = 0 ;
Verdef * verdef = 0 ;
@ -69,15 +88,20 @@ void *__vdsosym(const char *vername, const char *name)
case DT_STRTAB : strings = p ; break ;
case DT_STRTAB : strings = p ; break ;
case DT_SYMTAB : syms = p ; break ;
case DT_SYMTAB : syms = p ; break ;
case DT_HASH : hashtab = p ; break ;
case DT_HASH : hashtab = p ; break ;
case DT_GNU_HASH : ghashtab = p ; break ;
case DT_VERSYM : versym = p ; break ;
case DT_VERSYM : versym = p ; break ;
case DT_VERDEF : verdef = p ; break ;
case DT_VERDEF : verdef = p ; break ;
}
}
}
}
if ( ! strings | | ! syms | | ! hashtab ) return 0 ;
if ( ! strings | | ! syms ) return 0 ;
if ( ! verdef ) versym = 0 ;
if ( ! verdef ) versym = 0 ;
size_t nsym = 0 ;
if ( hashtab ) nsym = hashtab [ 1 ] ;
else if ( ghashtab ) nsym = count_syms_gnu ( ghashtab ) ;
for ( i = 0 ; i < hashtab [ 1 ] ; i + + ) {
for ( i = 0 ; i < nsym ; i + + ) {
if ( ! ( 1 < < ( syms [ i ] . st_info & 0xf ) & OK_TYPES ) ) continue ;
if ( ! ( 1 < < ( syms [ i ] . st_info & 0xf ) & OK_TYPES ) ) continue ;
if ( ! ( 1 < < ( syms [ i ] . st_info > > 4 ) & OK_BINDS ) ) continue ;
if ( ! ( 1 < < ( syms [ i ] . st_info > > 4 ) & OK_BINDS ) ) continue ;
if ( ! syms [ i ] . st_shndx ) continue ;
if ( ! syms [ i ] . st_shndx ) continue ;