From a42f82d9f08a4194002d97f066548ebf1fc0058e Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 9 Sep 2011 06:02:47 +0300 Subject: [PATCH] added Symbol decoding from a symbol table section --- elftools/elf/elffile.py | 1 + elftools/elf/enums.py | 27 +++++++++++++++++++++++ elftools/elf/sections.py | 46 +++++++++++++++++++++++++++++++++++++++- elftools/elf/structs.py | 9 +++++--- z.py | 6 ++++++ 5 files changed, 85 insertions(+), 4 deletions(-) diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index dc1b246..b0e2b67 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -150,6 +150,7 @@ class ELFFile(object): strtab_section = self.get_section(linked_strtab_index) return SymbolTableSection( section_header, name, self.stream, + elfstructs=self.structs, stringtable=strtab_section) def _get_segment_header(self, n): diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index 31647ac..1cd5a9b 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -105,3 +105,30 @@ ENUM_P_TYPE = dict( PT_GNU_RELRO=0x6474e552, ) +# st_info bindings in the symbol header +ENUM_ST_INFO_BIND = dict( + STB_LOCAL=0, + STB_GLOBAL=1, + STB_WEAK=2, + STB_NUM=3, + STB_LOOS=10, + STB_HIOS=12, + STB_LOPROC=13, + STB_HIPROC=15, +) + +# st_info type in the symbol header +ENUM_ST_INFO_TYPE = dict( + STT_NOTYPE=0, + STT_OBJECT=1, + STT_FUNC=2, + STT_SECTION=3, + STT_FILE=4, + STT_COMMON=5, + STT_TLS=6, + STT_NUM=7, + STT_LOOS=10, + STT_HIOS=12, + STT_LOPROC=13, + STT_HIPROC=15, +) diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py index 04410f3..fd11875 100644 --- a/elftools/elf/sections.py +++ b/elftools/elf/sections.py @@ -55,6 +55,50 @@ class SymbolTableSection(Section): """ ELF symbol table section. Has an associated StringTableSection that's passed in the constructor. """ - def __init__(self, header, name, stream, stringtable): + def __init__(self, header, name, stream, elfstructs, stringtable): super(SymbolTableSection, self).__init__(header, name, stream) + self.elfstructs = elfstructs self.stringtable = stringtable + elf_assert(self['sh_entsize'] > 0, + 'Expected entry size of section %s to be > 0' % name) + elf_assert(self['sh_size'] % self['sh_entsize'] == 0, + 'Expected section size to be a multiple of entry size in section %s' % name) + + def num_symbols(self): + """ Number of symbols in the table + """ + return self['sh_size'] // self['sh_entsize'] + + def get_symbol(self, n): + """ Get the symbol at index #n from the table (Symbol object) + """ + # Grab the symbol's entry from the stream + entry_offset = self['sh_offset'] + n * self['sh_entsize'] + entry = struct_parse( + self.elfstructs.Elf_Sym, + self.stream, + stream_pos=entry_offset) + # Find the symbol name in the associated string table + name = self.stringtable.get_string(entry['st_name']) + return Symbol(entry, name) + + def iter_symbols(self): + """ Yield all the symbols in the table + """ + for i in range(self.num_symbols()): + yield self.get_symbol(i) + + +class Symbol(object): + """ Symbol object - representing a single symbol entry from a symbol table + section. + """ + def __init__(self, entry, name): + self.entry = entry + self.name = name + + def __getitem__(self, name): + """ Implement dict-like access to entries + """ + return self.entry[name] + diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index c628c93..21ea2b7 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -11,7 +11,7 @@ from ..construct import ( UBInt8, UBInt16, UBInt32, UBInt64, ULInt8, ULInt16, ULInt32, ULInt64, SBInt32, SLInt32, SBInt64, SLInt64, - Struct, Array, Enum, Padding, + Struct, Array, Enum, Padding, BitStruct, BitField, ) from .enums import * @@ -130,19 +130,22 @@ class ELFStructs(object): ) def _create_sym(self): + st_info_struct = BitStruct('st_info', + Enum(BitField('bind', 4), **ENUM_ST_INFO_BIND), + Enum(BitField('type', 4), **ENUM_ST_INFO_TYPE)) 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'), - self.Elf_byte('st_info'), + st_info_struct, self.Elf_byte('st_other'), self.Elf_half('st_shndx'), ) else: self.Elf_Sym = Struct('Elf_Sym', self.Elf_word('st_name'), - self.Elf_byte('st_info'), + st_info_struct, self.Elf_byte('st_other'), self.Elf_half('st_shndx'), self.Elf_addr('st_value'), diff --git a/z.py b/z.py index fc295e7..dd2ab54 100644 --- a/z.py +++ b/z.py @@ -22,6 +22,12 @@ for sec in efile.iter_sections(): for seg in efile.iter_segments(): print seg['p_type'], seg['p_offset'] +for sec in efile.iter_sections(): + if isinstance(sec, SymbolTableSection): + print 'symbol table "%s ~~~"' % sec.name + for sym in sec.iter_symbols(): + print '%-26s %s %s' % (sym.name, sym['st_info']['type'], sym['st_info']['bind']) + #~ print 'num', efile.num_sections() #~ sec = efile.get_section(39) -- 2.30.2