some code restructuring + initial version of dwarfrelocationmanager
authorEli Bendersky <eliben@gmail.com>
Fri, 18 Nov 2011 05:07:37 +0000 (07:07 +0200)
committerEli Bendersky <eliben@gmail.com>
Fri, 18 Nov 2011 05:07:37 +0000 (07:07 +0200)
elftools/dwarf/dwarfrelocationmanager.py [new file with mode: 0644]
elftools/elf/elffile.py
elftools/elf/relocation.py [new file with mode: 0644]
elftools/elf/sections.py
z.py

diff --git a/elftools/dwarf/dwarfrelocationmanager.py b/elftools/dwarf/dwarfrelocationmanager.py
new file mode 100644 (file)
index 0000000..d8f7831
--- /dev/null
@@ -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
+
index 872d2d516409ad79eed9801463ffb8f4c7fe65b4..ebd04dd72ee3d7d8db18d7ab74407774095facca 100644 (file)
@@ -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 (file)
index 0000000..ab53927
--- /dev/null
@@ -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__()
+
index b30bd63efb2db7026c28859d117c7487351d7a17..1f4bf3d0c82a1382e360b7ac73b7031cf47fb1ee 100644 (file)
@@ -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 '<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 94951852fbd906e35379320271abd28e42a2f3fc..7c09211ede4723a3d49a04669e02a6f6d0dc4e1c 100644 (file)
--- 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)