some code restructuring + initial version of dwarfrelocationmanager
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 @@
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 @@
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 '<Relocation (%s): %s>' % (
+ '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 @@
""" 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 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 @@
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 @@
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 '<Relocation (%s): %s>' % (
- '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 @@
#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)