From d8d644973d39285e51b52755b51633163667e742 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 18 Nov 2011 07:07:37 +0200 Subject: [PATCH] some code restructuring + initial version of dwarfrelocationmanager --- elftools/dwarf/dwarfrelocationmanager.py | 59 ++++++++++++++++++++++++ elftools/elf/elffile.py | 4 +- elftools/elf/relocation.py | 37 +++++++++++++++ elftools/elf/sections.py | 40 ++++------------ z.py | 2 +- 5 files changed, 107 insertions(+), 35 deletions(-) create mode 100644 elftools/dwarf/dwarfrelocationmanager.py create mode 100644 elftools/elf/relocation.py diff --git a/elftools/dwarf/dwarfrelocationmanager.py b/elftools/dwarf/dwarfrelocationmanager.py new file mode 100644 index 0000000..d8f7831 --- /dev/null +++ b/elftools/dwarf/dwarfrelocationmanager.py @@ -0,0 +1,59 @@ +#------------------------------------------------------------------------------- +# elftools: dwarf/dwarfrelocationmanager.py +# +# DWARFRelocationManager - handles relocations of DWARF data +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- + +from ..elf.sections import RelocationSection + + +class DWARFRelocationManager(object): + """ Manages relocations for some DWARF section + """ + def __init__(self, elffile, section_name): + """ + """ + self.elffile = elffile + self.section_name = section_name + self._section = self.elffile.get_section_by_name(section_name) + + # _relocs maps an offset in the section to a Relocation object + # _reloc_section is the relocation section object + # ... both are loaded by _load_relocations + self._relocs = {} + self._reloc_section = None + self._load_relocations() + + # _symtable: symbol table section attached to the relocation section + self._symtable = self.elffile.get_section( + self._reloc_section['sh_link']) + + def has_relocation(self, offset): + """ Does the given offset have a relocation registered for it? + The offset is relative to its section. + """ + return offset in self._relocs + + def apply_relocation(self, offset): + """ Apply the relocation registered for the given offset. Return the + relocated value. + """ + reloc = self._relocs[offset] + + def _load_relocations(self): + # Currently assume that only a single relocation section will exist + # for our section, and that it's either a .rel or a .rela + reloc_section_names = ( + '.rel' + self.section_name, + '.rela' + self.section_name) + for section in self.elffile.iter_sections(): + if ( isinstance(section, RelocationSection) and + section.name in reloc_section_names): + self._reloc_section = section + for reloc in self._reloc_section.iter_relocations(): + self._relocs[reloc['r_offset']] = reloc + break + diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index 872d2d5..ebd04dd 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -212,7 +212,7 @@ class ELFFile(object): return self._make_symbol_table_section(section_header, name) elif sectype in ('SHT_REL', 'SHT_RELA'): return RelocationSection( - section_header, name, self.stream, self.structs) + section_header, name, self.stream, self) else: return Section(section_header, name, self.stream) @@ -223,7 +223,7 @@ class ELFFile(object): strtab_section = self.get_section(linked_strtab_index) return SymbolTableSection( section_header, name, self.stream, - elfstructs=self.structs, + elffile=self, stringtable=strtab_section) def _get_segment_header(self, n): diff --git a/elftools/elf/relocation.py b/elftools/elf/relocation.py new file mode 100644 index 0000000..ab53927 --- /dev/null +++ b/elftools/elf/relocation.py @@ -0,0 +1,37 @@ +#------------------------------------------------------------------------------- +# elftools: elf/relocation.py +# +# ELF relocations +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- + +class Relocation(object): + """ Relocation object - representing a single relocation entry. Allows + dictionary-like access to the entry's fields. + + Can be either a REL or RELA relocation. + """ + def __init__(self, entry, elffile): + self.entry = entry + self.elffile = elffile + + def is_RELA(self): + """ Is this a RELA relocation? If not, it's REL. + """ + return 'r_addend' in self.entry + + def __getitem__(self, name): + """ Dict-like access to entries + """ + return self.entry[name] + + def __repr__(self): + return '' % ( + 'RELA' if self.is_RELA() else 'REL', + self.entry) + + def __str__(self): + return self.__repr__() + diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py index b30bd63..1f4bf3d 100644 --- a/elftools/elf/sections.py +++ b/elftools/elf/sections.py @@ -8,6 +8,7 @@ #------------------------------------------------------------------------------- from ..construct import CString from ..common.utils import struct_parse, elf_assert +from .relocation import Relocation class Section(object): @@ -73,9 +74,10 @@ class SymbolTableSection(Section): """ ELF symbol table section. Has an associated StringTableSection that's passed in the constructor. """ - def __init__(self, header, name, stream, elfstructs, stringtable): + def __init__(self, header, name, stream, elffile, stringtable): super(SymbolTableSection, self).__init__(header, name, stream) - self.elfstructs = elfstructs + 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) @@ -108,9 +110,10 @@ class SymbolTableSection(Section): class RelocationSection(Section): - def __init__(self, header, name, stream, elfstructs): + def __init__(self, header, name, stream, elffile): super(RelocationSection, self).__init__(header, name, stream) - self.elfstructs = elfstructs + self.elffile = elffile + self.elfstructs = self.elffile.structs if self.header['sh_type'] == 'SHT_REL': expected_size = self.elfstructs.Elf_Rel.sizeof() self.entry_struct = self.elfstructs.Elf_Rel @@ -142,7 +145,7 @@ class RelocationSection(Section): self.entry_struct, self.stream, stream_pos=entry_offset) - return Relocation(entry) + return Relocation(entry, self.elffile) def iter_relocations(self): """ Yield all the relocations in the section @@ -168,30 +171,3 @@ class Symbol(object): return self.entry[name] -class Relocation(object): - """ Relocation object - representing a single relocation entry. Allows - dictionary-like access to the entry's fields. - - Can be either a REL or RELA relocation. - """ - def __init__(self, entry): - self.entry = entry - - def is_RELA(self): - """ Is this a RELA relocation? If not, it's REL. - """ - return 'r_addend' in self.entry - - def __getitem__(self, name): - """ Dict-like access to entries - """ - return self.entry[name] - - def __repr__(self): - return '' % ( - 'RELA' if self.is_RELA() else 'REL', - self.entry) - - def __str__(self): - return self.__repr__() - diff --git a/z.py b/z.py index 9495185..7c09211 100644 --- a/z.py +++ b/z.py @@ -31,7 +31,7 @@ topdie = cu.get_top_DIE() #print topdie dinfo_sec = efile.get_section_by_name('.debug_info') -relman = DWARFRelocationManager(efile, dinfo_sec.name, dinfo_sec['sh_offset']) +relman = DWARFRelocationManager(efile, dinfo_sec.name) print relman._reloc_section.name, relman._reloc_section['sh_offset'] pprint.pprint(relman._relocs) -- 2.30.2