From ad4d5899b163f64f6d10b6b4ef739ccdd0b69234 Mon Sep 17 00:00:00 2001 From: eliben Date: Thu, 8 Sep 2011 16:57:21 +0300 Subject: [PATCH] Added a SymbolTableSection class and split functionality from ELFFile to create it --- elftools/common/exceptions.py | 1 - elftools/elf/constants.py | 1 - elftools/elf/elffile.py | 30 ++++++++++++++++++++++++++---- elftools/elf/sections.py | 29 ++++++++++++++++++++++++----- elftools/elf/structs.py | 1 - z.py | 6 +++++- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/elftools/common/exceptions.py b/elftools/common/exceptions.py index 05fa602..a4df582 100644 --- a/elftools/common/exceptions.py +++ b/elftools/common/exceptions.py @@ -6,7 +6,6 @@ # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- - class ELFError(Exception): pass diff --git a/elftools/elf/constants.py b/elftools/elf/constants.py index 5af8372..cd21e09 100644 --- a/elftools/elf/constants.py +++ b/elftools/elf/constants.py @@ -6,7 +6,6 @@ # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- - class SHN_INDICES(object): """ Special section indices """ diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index 7d134b9..045e1c4 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -10,7 +10,7 @@ from ..common.exceptions import ELFError from ..common.utils import struct_parse from ..construct import ConstructError from .structs import ELFStructs -from .sections import Section, StringTableSection +from .sections import Section, StringTableSection, SymbolTableSection from .segments import Segment @@ -42,11 +42,11 @@ class ELFFile(object): return self['e_shnum'] def get_section(self, n): - """ Get the section at index #n from the file (Section object) + """ Get the section at index #n from the file (Section object or a + subclass) """ section_header = self._get_section_header(n) - name = self._get_section_name(section_header) - return Section(section_header, name, self.stream) + return self._make_section(section_header) def iter_sections(self): """ Yield all the sections in the file @@ -130,6 +130,28 @@ class ELFFile(object): name_offset = section_header['sh_name'] return self._file_stringtable_section.get_string(name_offset) + def _make_section(self, section_header): + """ Create a section object of the appropriate type + """ + name = self._get_section_name(section_header) + sectype = section_header['sh_type'] + + if sectype == 'SHT_STRTAB': + return StringTableSection(section_header, name, self.stream) + elif sectype in ('SHT_SYMTAB', 'SHT_DYNSYM'): + return self._make_symbol_table_section(section_header, name) + else: + return Section(section_header, name, self.stream) + + def _make_symbol_table_section(self, section_header, name): + """ Create a SymbolTableSection + """ + linked_strtab_index = section_header['sh_link'] + strtab_section = self.get_section(linked_strtab_index) + return SymbolTableSection( + section_header, name, self.stream, + stringtable=strtab_section) + def _get_segment_header(self, n): """ Find the header of segment #n, parse it and return the struct """ diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py index 502b69f..931095f 100644 --- a/elftools/elf/sections.py +++ b/elftools/elf/sections.py @@ -7,9 +7,17 @@ # This code is in the public domain #------------------------------------------------------------------------------- from ..construct import CString +from ..common.utils import struct_parse -class Section(object): +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 @@ -27,7 +35,9 @@ class Section(object): return self.header[name] -class StringTableSection(Section): +class StringTableSection(Section): + """ ELF string table section. + """ def __init__(self, header, name, stream): super(StringTableSection, self).__init__(header, name, stream) @@ -35,9 +45,18 @@ class StringTableSection(Section): """ Get the string stored at the given offset in this string table. """ table_offset = self['sh_offset'] - self.stream.seek(table_offset + offset) - return CString('').parse_stream(self.stream) + return struct_parse( + CString(''), + self.stream, + stream_pos=table_offset + offset) +class SymbolTableSection(Section): + """ ELF symbol table section. Has an associated StringTableSection that's + passed in the constructor. + """ + def __init__(self, header, name, stream, stringtable): + super(SymbolTableSection, self).__init__(header, name, stream) + self.stringtable = stringtable - + diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index 0b9f58f..465a9c8 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -7,7 +7,6 @@ # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- - from ..construct import ( UBInt8, UBInt16, UBInt32, UBInt64, ULInt8, ULInt16, ULInt32, ULInt64, diff --git a/z.py b/z.py index adcfd6c..2a5485c 100644 --- a/z.py +++ b/z.py @@ -1,6 +1,7 @@ import sys from elftools.elf.structs import ELFStructs from elftools.elf.elffile import ELFFile +from elftools.elf.sections import * # read a little-endian, 64-bit file es = ELFStructs(True, 64) @@ -13,11 +14,14 @@ print '===> %s sections!' % efile.num_sections() print '===> %s segments!' % efile.num_segments() for sec in efile.iter_sections(): - print sec.name + print type(sec), sec.name + if isinstance(sec, SymbolTableSection): + print ' linked string table:', sec.stringtable.name for seg in efile.iter_segments(): print seg['p_type'], seg['p_offset'] + #~ print 'num', efile.num_sections() #~ sec = efile.get_section(39) #~ print sec.header -- 2.30.2