#------------------------------------------------------------------------------- # elftools: elf/sections.py # # ELF sections # # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- from ..construct import CString from ..common.utils import struct_parse, elf_assert, parse_cstring_from_stream class Section(object): """ Base class for ELF sections. Also used for all sections types that have no special functionality. Allows dictionary-like access to the section header. For example: > sec = Section(...) > sec['sh_type'] # section type """ def __init__(self, header, name, stream): self.header = header self.name = name self.stream = stream def data(self): """ The section data from the file. """ self.stream.seek(self['sh_offset']) return self.stream.read(self['sh_size']) def is_null(self): """ Is this a null section? """ return False def __getitem__(self, name): """ Implement dict-like access to header entries """ return self.header[name] def __eq__(self, other): return self.header == other.header class NullSection(Section): """ ELF NULL section """ def __init__(self, header, name, stream): super(NullSection, self).__init__(header, name, stream) def is_null(self): return True class StringTableSection(Section): """ ELF string table section. """ def __init__(self, header, name, stream): super(StringTableSection, self).__init__(header, name, stream) def get_string(self, offset): """ Get the string stored at the given offset in this string table. """ table_offset = self['sh_offset'] s = parse_cstring_from_stream(self.stream, table_offset + offset) return s class SymbolTableSection(Section): """ ELF symbol table section. Has an associated StringTableSection that's passed in the constructor. """ def __init__(self, header, name, stream, elffile, stringtable): super(SymbolTableSection, self).__init__(header, name, stream) self.elffile = elffile self.elfstructs = self.elffile.structs 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. Similarly to Section objects, allows dictionary-like access to the symbol entry. """ 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]