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):
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,
+)
""" 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]
+
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 *
)
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'),
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)