Commit 8987e6f6 authored by Simon McVittie's avatar Simon McVittie
Browse files

Don't stop reading symbol tables at an unknown ELFW_ST_TYPE, ELFW_ST_BIND



~/.local/share/Steam/ubuntu12_32/steam has a symbol with a weird
binding type part way through its symbol table:

46 [OBJECT   LOOS/GNU_UNIQUE] size: 0 (0)_ZNSs4_Rep20_S_empty_rep_storageE 0000 (nil)

but we can't just stop there, because there are symbols after it that
need relocating.

I blame C++.

Signed-off-by: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
parent aae8d6b3
......@@ -472,7 +472,9 @@ symbol_version ( const ElfW(Sym) *symbol,
static void
dump_symtab (const char *indent,
const ElfW(Sym) *start,
size_t symsz,
const char *strtab,
size_t strsz,
const ElfW(Versym) *versym,
const void *verdef,
const int verdefnum)
......@@ -481,8 +483,7 @@ dump_symtab (const char *indent,
const ElfW(Sym) *entry;
for( entry = start;
( (ELFW_ST_TYPE(entry->st_info) < STT_NUM) &&
(ELFW_ST_BIND(entry->st_info) < STB_NUM) );
(entry - start + 1) * sizeof(*entry) <= symsz;
entry++ )
{
int defversym = 0;
......@@ -653,7 +654,7 @@ dump_rel (const char *indent,
exit( 22 );
#endif
symbol = find_symbol( sym, symtab, strtab, &name );
symbol = find_symbol( sym, symtab, symsz, strtab, strsz, &name );
if( symbol )
fprintf( stderr, "%s // [%03d] %16s off: %"FMT_XADDR"; %s;\n",
indent,
......@@ -707,7 +708,7 @@ dump_rela (const char *indent,
exit( 22 );
#endif
symbol = find_symbol( sym, symtab, strtab, &name );
symbol = find_symbol( sym, symtab, symsz, strtab, strsz, &name );
if( symbol )
fprintf( stderr, "%s // [%03d] %16s off: %"FMT_XADDR"; %s; add: 0x%"FMT_XADDR"\n",
indent,
......@@ -924,7 +925,7 @@ dump_dynamic (const char *indent, void *start, size_t size, ElfW(Addr) base)
if( verdefnum == -1 )
verdefnum = find_value( base, start, DT_VERDEFNUM );
symtab = fix_addr( (void *) base, entry->d_un.d_ptr );
dump_symtab( indent, symtab, strtab, versym, verdef, verdefnum );
dump_symtab( indent, symtab, symsz, strtab, strsiz, versym, verdef, verdefnum );
break;
case DT_RELA:
......
......@@ -327,7 +327,7 @@ process_dt_rela (const ElfW(Rela) *start,
DEBUG( DEBUG_ELF, "RELA entry at %p", entry );
symbol = find_symbol( sym, symtab, strtab, &name );
symbol = find_symbol( sym, symtab, symsz, strtab, strsz, &name );
DEBUG( DEBUG_ELF,
"symbol %p; name: %p:%s", symbol, name, name ? name : "-" );
......@@ -412,7 +412,7 @@ process_dt_rel (const ElfW(Rel) *start,
#error Unsupported CPU architecture
#endif
symbol = find_symbol( sym, symtab, strtab, &name );
symbol = find_symbol( sym, symtab, symsz, strtab, strsz, &name );
DEBUG( DEBUG_ELF,
"symbol %p; name: %p:%s", symbol, name, name ? name : "-" );
......
......@@ -134,16 +134,17 @@ dynamic_section_find_strtab (const ElfW(Dyn) *entries, const void *base, size_t
* find_symbol:
* @idx: The symbol index
* @stab: (array element-type=ElfW(Sym)): The symbol table
* @symsz: The length of the symbol table in bytes
* @str: The string table
* @strsz: The length of the string table in bytes
* @name: (out) (optional): Used to return the name, a pointer into @str
*
* If @idx is in-bounds for @stab, return a pointer to the @idx'th
* entry in @stab. Otherwise return %NULL.
*/
const ElfW(Sym) *
find_symbol (int idx, const ElfW(Sym) *stab, const char *str, const char **name)
find_symbol (int idx, const ElfW(Sym) *stab, size_t symsz, const char *str, size_t strsz, const char **name)
{
const ElfW(Sym) *entry;
const ElfW(Sym) *target = stab + idx;
if( idx < 0 )
......@@ -152,20 +153,13 @@ find_symbol (int idx, const ElfW(Sym) *stab, const char *str, const char **name)
// we could just accept the index as legitimate but then we'd
// run the risk of popping off into an unknown hyperspace coordinate
// this way we stop if the target is past the known end of the table:
for( entry = stab;
( (ELFW_ST_TYPE(entry->st_info) < STT_NUM) &&
(ELFW_ST_BIND(entry->st_info) < STB_NUM) );
entry++ )
{
if( entry == target )
{
if( name )
*name = str + entry->st_name;
return target;
}
}
if( (idx + 1) * sizeof(*target) > symsz )
return NULL;
return NULL;
if( name )
*name = str + target->st_name;
return target;
}
// ==========================================================================
......
......@@ -86,7 +86,9 @@ ElfW(Addr) find_ptr (ElfW(Addr) base, void *start, int what);
const char * dynamic_section_find_strtab (const ElfW(Dyn) *entries, const void *base, size_t *siz);
const ElfW(Sym) * find_symbol (int idx,
const ElfW(Sym) *stab,
size_t symsz,
const char *str,
size_t strsz,
const char **name);
void oom( void ) __attribute__((noreturn));
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment