def _dump_elf(cls, buf): """ Dump the symbol table of an ELF file. Needs pyelftools (https://github.com/eliben/pyelftools) """ from elftools.elf.elffile import ELFFile from elftools.elf import descriptions from io import BytesIO f = ELFFile(BytesIO(buf)) print("ELF file:") for sec in f.iter_sections(): if sec['sh_type'] == 'SHT_SYMTAB': symbols = sorted(sec.iter_symbols(), key=lambda sym: sym.name) print(" symbols:") for sym in symbols: if not sym.name: continue print(" - %r: size=%d, value=0x%x, type=%s, bind=%s" % ( sym.name.decode(), sym['st_size'], sym['st_value'], descriptions.describe_symbol_type( sym['st_info']['type']), descriptions.describe_symbol_bind( sym['st_info']['bind']), )) print()
def display_symbol_tables(self): """ Display the symbol tables contained in the file """ for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % ( bytes2str(section.name))) continue self._emitline("\nSymbol table '%s' contains %s entries:" % ( bytes2str(section.name), section.num_symbols())) if self.elffile.elfclass == 32: self._emitline(' Num: Value Size Type Bind Vis Ndx Name') else: # 64 self._emitline(' Num: Value Size Type Bind Vis Ndx Name') for nsym, symbol in enumerate(section.iter_symbols()): # symbol names are truncated to 25 chars, similarly to readelf self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s' % ( nsym, self._format_hex(symbol['st_value'], fullhex=True, lead0x=False), symbol['st_size'], describe_symbol_type(symbol['st_info']['type']), describe_symbol_bind(symbol['st_info']['bind']), describe_symbol_visibility(symbol['st_other']['visibility']), describe_symbol_shndx(symbol['st_shndx']), bytes2str(symbol.name)))
def _dump_elf(cls, buf): """ Dump the symbol table of an ELF file. Needs pyelftools (https://github.com/eliben/pyelftools) """ from elftools.elf.elffile import ELFFile from elftools.elf import descriptions from io import BytesIO f = ELFFile(BytesIO(buf)) print("ELF file:") for sec in f.iter_sections(): if sec['sh_type'] == 'SHT_SYMTAB': symbols = sorted(sec.iter_symbols(), key=lambda sym: sym.name) print(" symbols:") for sym in symbols: if not sym.name: continue print(" - %r: size=%d, value=0x%x, type=%s, bind=%s" % (sym.name.decode(), sym['st_size'], sym['st_value'], descriptions.describe_symbol_type(sym['st_info']['type']), descriptions.describe_symbol_bind(sym['st_info']['bind']), )) print()
def elf_symbol_tables(self): symbol_tables_list = [] def add_info(dic): symbol_tables_list.append(dic) self._init_versioninfo() symbol_tables = [ s for s in self.elffile.iter_sections() if isinstance(s, SymbolTableSection) ] if not symbol_tables and self.elffile.num_sections() == 0: return None for section in symbol_tables: if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: continue for nsym, symbol in enumerate(section.iter_symbols()): version_info = '' if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != symbol.name and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version symbol_info = {} symbol_info['index'] = nsym symbol_info['Value'] = self._format_hex(symbol['st_value'], fullhex=True, lead0x=False) symbol_info['Size'] = symbol['st_size'] symbol_info['Type'] = describe_symbol_type( symbol['st_info']['type']) symbol_info['Bind'] = describe_symbol_bind( symbol['st_info']['bind']) symbol_info['Vis'] = describe_symbol_visibility( symbol['st_other']['visibility']) symbol_info['Ndx'] = describe_symbol_shndx(symbol['st_shndx']) symbol_info['Name'] = symbol.name symbol_info['version_info'] = version_info add_info(symbol_info) return symbol_tables_list
def display_symbol_tables(self): """ Display the symbol tables contained in the file """ self._init_versioninfo() for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % ( bytes2str(section.name))) continue self._emitline("\nSymbol table '%s' contains %s entries:" % ( bytes2str(section.name), section.num_symbols())) if self.elffile.elfclass == 32: self._emitline(' Num: Value Size Type Bind Vis Ndx Name') else: # 64 self._emitline(' Num: Value Size Type Bind Vis Ndx Name') for nsym, symbol in enumerate(section.iter_symbols()): version_info = '' # readelf doesn't display version info for Solaris versioning if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != bytes2str(symbol.name) and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version # symbol names are truncated to 25 chars, similarly to readelf self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %.25s%s' % ( nsym, self._format_hex( symbol['st_value'], fullhex=True, lead0x=False), symbol['st_size'], describe_symbol_type(symbol['st_info']['type']), describe_symbol_bind(symbol['st_info']['bind']), describe_symbol_visibility(symbol['st_other']['visibility']), describe_symbol_shndx(symbol['st_shndx']), bytes2str(symbol.name), version_info))
def _get_symbol_tables(self): symbol_tables = [] for section in self.elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue for nsym, symbol in enumerate(section.iter_symbols()): symbol_tables.append({ "value": self._print_addr(symbol["st_value"]), "type": describe_symbol_type(symbol["st_info"]["type"]), "bind": describe_symbol_bind(symbol["st_info"]["bind"]), "ndx_name": symbol.name, }) return symbol_tables
def _get_symbol_tables(self) -> List[Dict[str, str]]: symbol_tables = [] for section in self.elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue symbol_tables.extend( { "value": self._print_addr(symbol["st_value"]), "type": describe_symbol_type(symbol["st_info"]["type"]), "bind": describe_symbol_bind(symbol["st_info"]["bind"]), "ndx_name": symbol.name, } for symbol in section.iter_symbols() ) return symbol_tables
def display_symbol_tables(self): """ Display the symbol tables contained in the file """ for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: self._emitline( "\nSymbol table '%s' has a sh_entsize of zero!" % (bytes2str(section.name))) continue self._emitline("\nSymbol table '%s' contains %s entries:" % (bytes2str(section.name), section.num_symbols())) if self.elffile.elfclass == 32: self._emitline( ' Num: Value Size Type Bind Vis Ndx Name') else: # 64 self._emitline( ' Num: Value Size Type Bind Vis Ndx Name' ) for nsym, symbol in enumerate(section.iter_symbols()): # symbol names are truncated to 25 chars, similarly to readelf self._emitline( '%6d: %s %5d %-7s %-6s %-7s %4s %.25s' % (nsym, self._format_hex(symbol['st_value'], fullhex=True, lead0x=False), symbol['st_size'], describe_symbol_type(symbol['st_info']['type']), describe_symbol_bind(symbol['st_info']['bind']), describe_symbol_visibility( symbol['st_other']['visibility']), describe_symbol_shndx( symbol['st_shndx']), bytes2str(symbol.name)))
def get_symbols(self): """Return a set of symbols from the dwarf symbol tables""" symbols = {} # We want .symtab and .dynsym tables = [ (idx, s) for idx, s in enumerate(self.elffile.iter_sections()) if isinstance(s, SymbolTableSection) ] for idx, section in tables: # Symbol table has no entries if this is zero # section.num_symbols() shows count, section.name is name if section["sh_entsize"] == 0: continue # We need the index of the symbol to look up versions for sym_idx, symbol in enumerate(section.iter_symbols()): # Version info is from the versym / verneed / verdef sections. version_info = self._get_symbol_version(section, sym_idx, symbol) # We aren't considering st_value, which could be many things # https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcoblj/index.html#chapter6-35166 symbols[symbol.name] = { "version_info": version_info, "type": describe_symbol_type(symbol["st_info"]["type"]), "binding": describe_symbol_bind(symbol["st_info"]["bind"]), "visibility": describe_symbol_visibility( symbol["st_other"]["visibility"] ), "defined": describe_symbol_shndx( self._get_symbol_shndx(symbol, sym_idx, idx) ).strip(), } return symbols
def scan(self, data, file, options, expire_at): with io.BytesIO(data) as elf_io: try: elf = elffile.ELFFile(elf_io) self.event.setdefault('header', {}) for (key, value) in elf.header.items(): if key == 'e_flags': self.event['header']['flags'] = value elif key == 'e_shnum': self.event['header']['section_headers'] = value elif key == 'e_phnum': self.event['header']['program_headers'] = value elif key == 'e_version': self.event['header'][ 'file_version'] = descriptions.describe_e_version_numeric( value) elif key == 'e_machine': self.event['header'][ 'machine'] = descriptions.describe_e_machine(value) elif key == 'e_type': self.event['header'][ 'file_type'] = descriptions.describe_e_type(value) elif key == 'e_ident': for x, y in value.items(): if x == 'EI_DATA': self.event['header'][ 'data'] = descriptions.describe_ei_data(y) elif x == 'EI_OSABI': self.event['header'][ 'os_abi'] = descriptions.describe_ei_osabi( y) elif x == 'EI_VERSION': self.event['header'][ 'header_version'] = descriptions.describe_ei_version( y) elif x == 'EI_CLASS': self.event['header'][ 'class'] = descriptions.describe_ei_class( y) elif x == 'EI_ABIVERSION': self.event['header']['abi_version'] = y try: self.event.setdefault('shared_libraries', []) self.event.setdefault('imports', []) self.event.setdefault('exports', []) for section in elf.iter_sections(): if not section.is_null(): if isinstance(section, dynamic.DynamicSection): for tag in section.iter_tags(): if tag.entry.d_tag == 'DT_NEEDED': if tag.needed not in self.event[ 'shared_libraries']: self.event[ 'shared_libraries'].append( tag.needed) # Attempt to organize symbols into imports and exports # This is the most comprehensive explanation I've seen for organizing these symbols: http://www.m4b.io/elf/export/binary/analysis/2015/05/25/what-is-an-elf-export.html if isinstance(section, sections.SymbolTableSection): for symbol in section.iter_symbols(): if descriptions.describe_symbol_type( symbol['st_info']['type']) in [ 'FUNC', 'OBJECT' ]: if descriptions.describe_symbol_bind( symbol['st_info']['bind']) in [ 'GLOBAL', 'WEAK' ]: if descriptions.describe_symbol_shndx( symbol['st_shndx'] ) == 'UND': if symbol.name not in self.event[ 'imports']: self.event[ 'imports'].append( symbol.name) else: if symbol.name not in self.event[ 'exports']: self.event[ 'exports'].append( symbol.name) except OverflowError: self.flags.append('overflow_error') self.event.setdefault('segments', []) segment_cache = {} for segment in elf.iter_segments(): for section in elf.iter_sections(): if not section.is_null( ) and segment.section_in_segment(section): key = segment.header['p_type'] if key not in self.event['segments']: self.event['segments'].append(key) segment_cache.setdefault(key, []) segment_cache[key].append(section.name) self.event.setdefault('segment_sections', []) for (key, value) in segment_cache.items(): section_dict = {'segment': key, 'sections': value} if section_dict not in self.event['segment_sections']: self.event['segment_sections'].append(section_dict) except exceptions.ELFParseError: self.flags.append('elf_parse_error')
def get_sections(self): sections = [] for nsec, section in enumerate(self._elf.iter_sections()): result = {} result['nsec'] = nsec result['name'] = section.name result['sh_type'] = describe_sh_type(section['sh_type']) if self._elf.elfclass == 32: result['sh_addr'] = section['sh_addr'] result['shoffset'] = section['sh_offset'] result['sh_size'] = section['sh_size'] result['sh_entsize'] = section['sh_entsize'] result['sh_flags'] = describe_sh_flags(section['sh_flags']) result['sh_link'] = section['sh_link'] result['sh_info'] = section['sh_info'] result['sh_addralign'] = section['sh_addralign'] else: # 64 result['sh_addr'] = section['sh_addr'] result['sh_offset'] = section['sh_offset'] result['sh_size'] = section['sh_size'] result['sh_entsize'] = section['sh_entsize'] result['sh_flags'] = describe_sh_flags(section['sh_flags']) result['sh_link'] = section['sh_link'], section['sh_info'] result['sh_addralign'] = section['sh_addralign'] # Dynamic Section if isinstance(section, DynamicSection): result['special_type'] = 'dynamic' result['dynamic'] = [] has_dynamic_sections = True for tag in section.iter_tags(): dynamic = {} if tag.entry.d_tag == 'DT_NEEDED': parsed = 'Shared library: [%s]' % tag.needed elif tag.entry.d_tag == 'DT_RPATH': parsed = 'Library rpath: [%s]' % tag.rpath elif tag.entry.d_tag == 'DT_RUNPATH': parsed = 'Library runpath: [%s]' % tag.runpath elif tag.entry.d_tag == 'DT_SONAME': parsed = 'Library soname: [%s]' % tag.soname elif tag.entry.d_tag.endswith(('SZ', 'ENT')): parsed = '%i (bytes)' % tag['d_val'] elif tag.entry.d_tag.endswith(('NUM', 'COUNT')): parsed = '%i' % tag['d_val'] elif tag.entry.d_tag == 'DT_PLTREL': s = describe_dyn_tag(tag.entry.d_val) if s.startswith('DT_'): s = s[3:] parsed = '%s' % s else: parsed = '%#x' % tag['d_val'] dynamic['tag'] = ENUM_D_TAG.get( tag.entry.d_tag, tag.entry.d_tag) dynamic['tag_type'] = tag.entry.d_tag[3:] dynamic['tag_value'] = parsed result['dynamic'].append(dynamic) #Relocation Section if isinstance(section, RelocationSection): result['special_type'] = 'relocation' result['relocation'] = [] has_relocation_sections = True # The symbol table section pointed to in sh_link symtable = self._elf.get_section(section['sh_link']) for rel in section.iter_relocations(): relocation = {} relocation['r_offset'] = rel['r_offset'] relocation['r_info'] = rel['r_info'] relocation['r_info_type'] = describe_reloc_type( rel['r_info_type'], self._elf) if rel['r_info_sym'] == 0: continue symbol = symtable.get_symbol(rel['r_info_sym']) # Some symbols have zero 'st_name', so instead what's used is # the name of the section they point at if symbol['st_name'] == 0: symsec = self._elf.get_section(symbol['st_shndx']) relocation['symbol_name'] = symbol_name = symsec.name else: symbol_name = symbol.name relocation['st_value'] = symbol['st_value'] relocation['symbol_name'] = symbol_name if section.is_RELA(): relocation['r_addend'] = rel['r_addend'] result['relocation'].append(relocation) #Symbol Section if isinstance(section, SymbolTableSection): self._init_versioninfo() if section['sh_entsize'] == 0: continue result['special_type'] = 'symbol' result['symbol'] = [] for nsym, symbol in enumerate(section.iter_symbols()): sym_dic = {} version_info = '' # readelf doesn't display version info for Solaris versioning if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != symbol.name and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version # symbol names are truncated to 25 chars, similarly to readelf sym_dic['nsym'] = nsym sym_dic['st_value'] = symbol['st_value'] sym_dic['st_size'] = symbol['st_size'] sym_dic['st_type'] = describe_symbol_type( symbol['st_info']['type']) sym_dic['bind'] = describe_symbol_bind( symbol['st_info']['bind']) sym_dic['vis'] = describe_symbol_visibility( symbol['st_other']['visibility']) sym_dic['ndx'] = describe_symbol_shndx( symbol['st_shndx']) sym_dic['name'] = symbol.name sym_dic['version'] = version_info result['symbol'].append(sym_dic) sections.append(result) return sections
def CollectBinaryElfinfo(self): """Returns various informations symbol and versions present in elf header We will analyse 5 sections: - version definitions and version needed: contains version interface defined for this binary and for each required soname, the version interfaces required - symbol table: contains list of symbol name - version symbol table: maps the symbol against version interface - syminfo: contains special linking flags for each symbol The amount of data might be too large for it to fit in memory at one time, therefore the rest_client is passed to facilitate saving data. """ md5_sum = self._compute_md5_sum() if self.rest_client.BlobExists('elfdump', md5_sum): logging.debug('We already have info about %r.', self._binary_path) return md5_sum sections = self._get_sections_of_interest('verneed', 'verdef', 'syminfo', 'symbols') versions_needed = [] if 'verneed' in sections: for verneed, vernaux_iter in sections['verneed'].iter_versions(): versions_needed.extend([{ 'index': vernaux['vna_other'], 'soname': verneed.name, 'version': vernaux.name } for vernaux in vernaux_iter]) versions_needed.sort(key=lambda x: x['index']) for version in versions_needed: del version['index'] version_definitions = [] if 'verdef' in sections: for verdef, verdaux_iter in sections['verdef'].iter_versions(): version_name = verdaux_iter.next().name dependencies = [x.name for x in verdaux_iter] version_definitions.append({ 'index': verdef['vd_ndx'], 'version': version_name, 'dependencies': dependencies }) if version_definitions: version_definitions.sort(key=lambda x: x['index']) # the first "version definition" entry is the base soname # we don't care about this information version_definitions.pop(0) for version in version_definitions: del version['index'] symbols = [] if 'symbols' in sections: versions_info = (version_definitions + versions_needed) symbol_iter = sections['symbols'].iter_symbols() # We skip the first symbol which is always the 'UNDEF' symbol entry symbol_iter.next() for index, sym in enumerate(symbol_iter, start=1): symbol = { 'bind': describe_symbol_bind(sym['st_info']['bind']), 'shndx': self._describe_symbol_shndx(sym['st_shndx']), 'symbol': sym.name, 'flags': None, 'soname': None, 'version': None } if 'versym' in sections: versym = sections['versym'].get_symbol(index) if not versym['ndx'] in [ 'VER_NDX_LOCAL', 'VER_NDX_GLOBAL' ]: # if versym is 2 or more, it's an index on the version # definition and version needed tables version = versions_info[versym['ndx'] - 2] symbol['version'] = version['version'] if 'soname' in version: symbol['soname'] = version['soname'] if 'syminfo' in sections: syminfo = sections['syminfo'].get_symbol(index) # We only use the information from syminfo if: # - there is at least one flag that uses the boundto value, # - boundto is an index and not special value (SYMINFO_BT_SELF...) if (syminfo['si_flags'] & (SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECT | SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECTBIND | SUNW_SYMINFO_FLAGS.SYMINFO_FLG_LAZYLOAD | SUNW_SYMINFO_FLAGS.SYMINFO_FLG_FILTER) and isinstance(syminfo['si_boundto'], int)): symbol['flags'] = describe_syminfo_flags( syminfo['si_flags']) symbol['soname'] = self._describe_symbol_boundto( syminfo) symbols.append(representations.ElfSymInfo(**symbol)) symbols.sort(key=lambda m: m.symbol) binary_info = { 'version definition': version_definitions, 'version needed': versions_needed, 'symbol table': symbols } self.rest_client.SaveBlob('elfdump', md5_sum, binary_info) return md5_sum
def CollectBinaryElfinfo(self): """Returns various informations symbol and versions present in elf header We will analyse 5 sections: - version definitions and version needed: contains version interface defined for this binary and for each required soname, the version interfaces required - symbol table: contains list of symbol name - version symbol table: maps the symbol against version interface - syminfo: contains special linking flags for each symbol The amount of data might be too large for it to fit in memory at one time, therefore the rest_client is passed to facilitate saving data. """ md5_sum = self._compute_md5_sum() if self.rest_client.BlobExists('elfdump', md5_sum): logging.debug('We already have info about %r.', self._binary_path) return md5_sum sections = self._get_sections_of_interest('verneed', 'verdef', 'syminfo', 'symbols') versions_needed = [] if 'verneed' in sections: for verneed, vernaux_iter in sections['verneed'].iter_versions(): versions_needed.extend([{'index': vernaux['vna_other'], 'soname': verneed.name, 'version': vernaux.name} for vernaux in vernaux_iter]) versions_needed.sort(key=lambda x: x['index']) for version in versions_needed: del version['index'] version_definitions = [] if 'verdef' in sections: for verdef, verdaux_iter in sections['verdef'].iter_versions(): version_name = verdaux_iter.next().name dependencies = [x.name for x in verdaux_iter] version_definitions.append({'index': verdef['vd_ndx'], 'version': version_name, 'dependencies': dependencies}) if version_definitions: version_definitions.sort(key=lambda x: x['index']) # the first "version definition" entry is the base soname # we don't care about this information version_definitions.pop(0) for version in version_definitions: del version['index'] symbols = [] if 'symbols' in sections: versions_info = (version_definitions + versions_needed) symbol_iter = sections['symbols'].iter_symbols() # We skip the first symbol which is always the 'UNDEF' symbol entry symbol_iter.next() for index, sym in enumerate(symbol_iter, start=1): symbol = {'bind': describe_symbol_bind(sym['st_info']['bind']), 'shndx': self._describe_symbol_shndx(sym['st_shndx']), 'symbol': sym.name, 'flags': None, 'soname': None, 'version': None} if 'versym' in sections: versym = sections['versym'].get_symbol(index) if not versym['ndx'] in ['VER_NDX_LOCAL', 'VER_NDX_GLOBAL']: # if versym is 2 or more, it's an index on the version # definition and version needed tables version = versions_info[versym['ndx'] - 2] symbol['version'] = version['version'] if 'soname' in version: symbol['soname'] = version['soname'] if 'syminfo' in sections: syminfo = sections['syminfo'].get_symbol(index) # We only use the information from syminfo if: # - there is at least one flag that uses the boundto value, # - boundto is an index and not special value (SYMINFO_BT_SELF...) if (syminfo['si_flags'] & ( SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECT | SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECTBIND | SUNW_SYMINFO_FLAGS.SYMINFO_FLG_LAZYLOAD | SUNW_SYMINFO_FLAGS.SYMINFO_FLG_FILTER) and isinstance(syminfo['si_boundto'], int)): symbol['flags'] = describe_syminfo_flags(syminfo['si_flags']) symbol['soname'] = self._describe_symbol_boundto(syminfo) symbols.append(representations.ElfSymInfo(**symbol)) symbols.sort(key=lambda m: m.symbol) binary_info = {'version definition': version_definitions, 'version needed': versions_needed, 'symbol table': symbols} self.rest_client.SaveBlob('elfdump', md5_sum, binary_info) return md5_sum
def display_symbol_tables(self): """ Display the symbol tables contained in the file """ self._init_versioninfo() listSyms = [] setClasses = set() for section in self.elffile.iter_sections(): if not isinstance(section, SymbolTableSection): continue if section['sh_entsize'] == 0: continue for nsym, symbolobj in enumerate(section.iter_symbols()): version_info = '' # readelf doesn't display version info for Solaris versioning if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != symbolobj.name and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version demang = demangler.demangle(symbolobj.name) nnn = indexStartsWith(demang, "vtable for ") if nnn: setClasses.add(nnn) continue nnn = indexStartsWith(demang, "typeinfo name for ") if nnn: setClasses.add(nnn) continue nnn = indexStartsWith(demang, "typeinfo for ") if nnn: setClasses.add(nnn) continue nnn = indexStartsWith(demang, "non-virtual thunk to ") if nnn: # No need to duplicate the symbol. # demang = nnn continue # Related to virtual inheritance. # http://stackoverflow.com/questions/6258559/what-is-the-vtt-for-a-class nnn = indexStartsWith(demang, "VTT for ") # TODO: Use it to build class hierarchy ??? if nnn: continue sym = ElfSym( demang, symbolobj.name, describe_symbol_type(symbolobj['st_info']['type']), describe_symbol_bind(symbolobj['st_info']['bind']), describe_symbol_visibility( symbolobj['st_other']['visibility']), describe_symbol_shndx(symbolobj['st_shndx']), version_info) listSyms.append(sym) return (listSyms, setClasses)
# vim:ts=4 sw=4 expandtab import sys from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection from elftools.elf.descriptions import ( describe_symbol_type, describe_symbol_bind, describe_symbol_visibility, describe_symbol_shndx, describe_reloc_type, describe_dyn_tag, ) IGNORE_TYPES=('STT_NOTYPE', 'STT_SECTION', 'STT_FILE') f = ELFFile(open(sys.argv[1], 'r')) for sect in f.iter_sections(): if not isinstance(sect, SymbolTableSection): continue for sym in sect.iter_symbols(): if sym['st_info']['type'] in IGNORE_TYPES: continue """ print '{} rawtype {} rawbind {} rawvis {}'.format( sym.name, sym['st_info']['type'], sym['st_info']['bind'], sym['st_other']['visibility'], ) """ print '{} {}'.format( sym.name, describe_symbol_bind(sym['st_info']['bind']), )