From 3edefab85d0b58bd3ec43514b9b442cb5a9170e3 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 16 Sep 2011 14:52:54 +0300 Subject: [PATCH] displaying symtables kinda works --- elftools/elf/descriptions.py | 45 ++++++++++++++++++++++++++++++++++++ elftools/elf/enums.py | 21 +++++++++++++++++ elftools/elf/structs.py | 15 ++++++++---- scripts/readelf.py | 41 +++++++++++++++++++++++++++++--- 4 files changed, 114 insertions(+), 8 deletions(-) mode change 100644 => 100755 scripts/readelf.py diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py index 688ee61..23e789d 100644 --- a/elftools/elf/descriptions.py +++ b/elftools/elf/descriptions.py @@ -56,6 +56,18 @@ def describe_sh_flags(x): s += _DESCR_SH_FLAGS[flag] if (x & flag) else '' return s +def describe_symbol_type(x): + return _DESCR_ST_INFO_TYPE.get(x, _unknown()) + +def describe_symbol_bind(x): + return _DESCR_ST_INFO_BIND.get(x, _unknown()) + +def describe_symbol_visibility(x): + return _DESCR_ST_VISIBILITY.get(x, _unknown()) + +def describe_symbol_shndx(x): + return _DESCR_ST_SHNDX.get(x, '%3s' % x) + #------------------------------------------------------------------------------- def _unknown(): @@ -178,3 +190,36 @@ _DESCR_SH_FLAGS = { SH_FLAGS.SHF_EXCLUDE: 'E', } +_DESCR_ST_INFO_TYPE = dict( + STT_NOTYPE='NOTYPE', + STT_OBJECT='OBJECT', + STT_FUNC='FUNC', + STT_SECTION='SECTION', + STT_FILE='FILE', + STT_COMMON='COMMON', + STT_TLS='TLS', + STT_NUM='NUM', + STT_RELC='RELC', + STT_SRELC='SRELC', +) + +_DESCR_ST_INFO_BIND = dict( + STB_LOCAL='LOCAL', + STB_GLOBAL='GLOBAL', + STB_WEAK='WEAK', +) + +_DESCR_ST_VISIBILITY = dict( + STV_DEFAULT='DEFAULT', + STV_INTERNAL='INTERNAL', + STV_HIDDEN='HIDDEN', + STD_PROTECTED='PROTECTED', +) + +_DESCR_ST_SHNDX = dict( + SHN_UNDEF='UND', + SHN_ABS='ABS', + SHN_COMMON='COM', +) + + diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index dadf5d4..49ee9cd 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -6,6 +6,8 @@ # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- +from ..construct import Pass + # e_ident[EI_CLASS] in the ELF header ENUM_EI_CLASS = dict( @@ -152,8 +154,27 @@ ENUM_ST_INFO_TYPE = dict( STT_COMMON=5, STT_TLS=6, STT_NUM=7, + STT_RELC=8, + STT_SRELC=9, STT_LOOS=10, STT_HIOS=12, STT_LOPROC=13, STT_HIPROC=15, ) + +# visibility from st_other +ENUM_ST_VISIBILITY = dict( + STV_DEFAULT=0, + STV_INTERNAL=1, + STV_HIDDEN=2, + STV_PROTECTED=3, +) + +# st_shndx +ENUM_ST_SHNDX = dict( + SHN_UNDEF=0, + SHN_ABS=0xfff1, + SHN_COMMON=0xfff2, + _default_=Pass, +) + diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index 5808820..ae084d2 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -132,26 +132,31 @@ class ELFStructs(object): ) def _create_sym(self): - # Note that st_info is hierarchical. To access the type, use + # st_info is hierarchical. To access the type, use # container['st_info']['type'] st_info_struct = BitStruct('st_info', Enum(BitField('bind', 4), **ENUM_ST_INFO_BIND), Enum(BitField('type', 4), **ENUM_ST_INFO_TYPE)) + # st_other is hierarchical. To access the visibility, + # use container['st_other']['visibility'] + st_other_struct = BitStruct('st_other', + Padding(5), + Enum(BitField('visibility', 3), **ENUM_ST_VISIBILITY)) if self.elfclass == 32: self.Elf_Sym = Struct('Elf_Sym', self.Elf_word('st_name'), self.Elf_addr('st_value'), self.Elf_word('st_size'), st_info_struct, - self.Elf_byte('st_other'), - self.Elf_half('st_shndx'), + st_other_struct, + Enum(self.Elf_half('st_shndx'), **ENUM_ST_SHNDX), ) else: self.Elf_Sym = Struct('Elf_Sym', self.Elf_word('st_name'), st_info_struct, - self.Elf_byte('st_other'), - self.Elf_half('st_shndx'), + st_other_struct, + Enum(self.Elf_half('st_shndx'), **ENUM_ST_SHNDX), self.Elf_addr('st_value'), self.Elf_xword('st_size'), ) diff --git a/scripts/readelf.py b/scripts/readelf.py old mode 100644 new mode 100755 index ede8738..34b4b93 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python #------------------------------------------------------------------------------- # readelf.py # @@ -20,11 +21,14 @@ except ImportError: from elftools.common.exceptions import ELFError from elftools.elf.elffile import ELFFile from elftools.elf.segments import InterpSegment +from elftools.elf.sections import SymbolTableSection from elftools.elf.descriptions import ( describe_ei_class, describe_ei_data, describe_ei_version, describe_ei_osabi, describe_e_type, describe_e_machine, describe_e_version_numeric, describe_p_type, describe_p_flags, describe_sh_type, describe_sh_flags, + describe_symbol_type, describe_symbol_bind, describe_symbol_visibility, + describe_symbol_shndx, ) @@ -218,6 +222,37 @@ class ReadElf(object): self._emitline(' I (info), L (link order), G (group), x (unknown)') self._emitline(' O (extra OS processing required) o (OS specific), p (processor specific)') + 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!" % ( + section.name)) + continue + + self._emitline("\nSymbol table '%s' contains %s entries:" % ( + 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()): + self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %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']), + symbol.name)) + def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True): """ Format an address into a hexadecimal string. @@ -261,10 +296,10 @@ def main(): with open(args[0], 'rb') as file: try: readelf = ReadElf(file, sys.stdout) - readelf.display_file_header() - print '----' + #readelf.display_file_header() #readelf.display_program_headers() - readelf.display_section_headers() + #readelf.display_section_headers() + readelf.display_symbol_tables() except ELFError as ex: sys.stderr.write('ELF read error: %s\n' % ex) sys.exit(1) -- 2.30.2