relocation output working in readelf comparison
authorEli Bendersky <eliben@gmail.com>
Fri, 23 Sep 2011 07:59:59 +0000 (10:59 +0300)
committerEli Bendersky <eliben@gmail.com>
Fri, 23 Sep 2011 07:59:59 +0000 (10:59 +0300)
elftools/elf/descriptions.py
elftools/elf/enums.py
elftools/elf/sections.py
scripts/readelf.py
tests/run_tests.py

index 35232b98c33e1c6030680eff1d68de6ae27df46c..f404898841d02351b5b73730b905d6179ba3fa16 100644 (file)
@@ -6,15 +6,15 @@
 # Eli Bendersky (eliben@gmail.com)
 # This code is in the public domain
 #-------------------------------------------------------------------------------
-from .enums import ENUM_E_VERSION
+from .enums import ENUM_E_VERSION, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
 from .constants import P_FLAGS, SH_FLAGS
 
 
 def describe_ei_class(x):
-    return _DESCR_EI_CLASS.get(x, _unknown())
+    return _DESCR_EI_CLASS.get(x, _unknown)
 
 def describe_ei_data(x):
-    return _DESCR_EI_DATA.get(x, _unknown())
+    return _DESCR_EI_DATA.get(x, _unknown)
 
 def describe_ei_version(x):
     s = '%d' % ENUM_E_VERSION[x]
@@ -23,19 +23,19 @@ def describe_ei_version(x):
     return s
     
 def describe_ei_osabi(x):
-    return _DESCR_EI_OSABI.get(x, _unknown())
+    return _DESCR_EI_OSABI.get(x, _unknown)
 
 def describe_e_type(x):
-    return _DESCR_E_TYPE.get(x, _unknown())
+    return _DESCR_E_TYPE.get(x, _unknown)
 
 def describe_e_machine(x):
-    return _DESCR_E_MACHINE.get(x, _unknown())
+    return _DESCR_E_MACHINE.get(x, _unknown)
 
 def describe_e_version_numeric(x):
     return '0x%x' % ENUM_E_VERSION[x]
 
 def describe_p_type(x):
-    return _DESCR_P_TYPE.get(x, _unknown())
+    return _DESCR_P_TYPE.get(x, _unknown)
 
 def describe_p_flags(x):
     s = ''
@@ -44,7 +44,7 @@ def describe_p_flags(x):
     return s
 
 def describe_sh_type(x):
-    return _DESCR_SH_TYPE.get(x, _unknown())
+    return _DESCR_SH_TYPE.get(x, _unknown)
 
 def describe_sh_flags(x):
     s = ''
@@ -57,21 +57,28 @@ def describe_sh_flags(x):
     return s
 
 def describe_symbol_type(x):
-    return _DESCR_ST_INFO_TYPE.get(x, _unknown())
+    return _DESCR_ST_INFO_TYPE.get(x, _unknown)
 
 def describe_symbol_bind(x):
-    return _DESCR_ST_INFO_BIND.get(x, _unknown())
+    return _DESCR_ST_INFO_BIND.get(x, _unknown)
 
 def describe_symbol_visibility(x):
-    return _DESCR_ST_VISIBILITY.get(x, _unknown())
+    return _DESCR_ST_VISIBILITY.get(x, _unknown)
 
 def describe_symbol_shndx(x):
     return _DESCR_ST_SHNDX.get(x, '%3s' % x)
 
+def describe_reloc_type(x, e_machine):
+    if e_machine in ('EM_386', 'EM_486'):
+        return _DESCR_RELOC_TYPE_i386.get(x, _unknown)
+    elif e_machine in ('EM_X86_64', 'EM_L10M'):
+        return _DESCR_RELOC_TYPE_x64.get(x, _unknown)
+    else:
+        return 'unrecognized: %-7x' % (x & 0xFFFFFFFF)
+
 
 #-------------------------------------------------------------------------------
-def _unknown():
-    return '<unknown>'
+_unknown = '<unknown>'
 
     
 _DESCR_EI_CLASS = dict(
@@ -222,4 +229,10 @@ _DESCR_ST_SHNDX = dict(
     SHN_COMMON='COM',
 )
 
+_DESCR_RELOC_TYPE_i386 = dict(
+        (v, k) for k, v in ENUM_RELOC_TYPE_i386.iteritems())
+
+_DESCR_RELOC_TYPE_x64 = dict(
+        (v, k) for k, v in ENUM_RELOC_TYPE_x64.iteritems())
+
 
index c13d15f0a2178508e322792fdf410f92e5d412d2..78302ae745079b75f8b848436470503952ea091c 100644 (file)
@@ -73,6 +73,7 @@ ENUM_E_MACHINE = dict(
     EM_386=3,
     EM_68K=4,
     EM_88K=5,
+    EM_486=6,
     EM_860=7,
     EM_MIPS=8,
     EM_S370=9,
@@ -80,6 +81,7 @@ ENUM_E_MACHINE = dict(
     EM_IA_64=50,
     EM_X86_64=62,
     EM_AVR=83,
+    EM_L10M=180,
     _default_=Pass,
 )
 
@@ -184,3 +186,92 @@ ENUM_ST_SHNDX = dict(
     _default_=Pass,
 )
 
+ENUM_RELOC_TYPE_i386 = dict(
+    R_386_NONE=0,
+    R_386_32=1,
+    R_386_PC32=2,
+    R_386_GOT32=3,
+    R_386_PLT32=4,
+    R_386_COPY=5,
+    R_386_GLOB_DAT=6,
+    R_386_JUMP_SLOT=7,
+    R_386_RELATIVE=8,
+    R_386_GOTOFF=9,
+    R_386_GOTPC=10,
+    R_386_32PLT=11,
+    R_386_TLS_TPOFF=14,
+    R_386_TLS_IE=15,
+    R_386_TLS_GOTIE=16,
+    R_386_TLS_LE=17,
+    R_386_TLS_GD=18,
+    R_386_TLS_LDM=19,
+    R_386_16=20,
+    R_386_PC16=21,
+    R_386_8=22,
+    R_386_PC8=23,
+    R_386_TLS_GD_32=24,
+    R_386_TLS_GD_PUSH=25,
+    R_386_TLS_GD_CALL=26,
+    R_386_TLS_GD_POP=27,
+    R_386_TLS_LDM_32=28,
+    R_386_TLS_LDM_PUSH=29,
+    R_386_TLS_LDM_CALL=30,
+    R_386_TLS_LDM_POP=31,
+    R_386_TLS_LDO_32=32,
+    R_386_TLS_IE_32=33,
+    R_386_TLS_LE_32=34,
+    R_386_TLS_DTPMOD32=35,
+    R_386_TLS_DTPOFF32=36,
+    R_386_TLS_TPOFF32=37,
+    R_386_TLS_GOTDESC=39,
+    R_386_TLS_DESC_CALL=40,
+    R_386_TLS_DESC=41,
+    R_386_IRELATIVE=42,
+    R_386_USED_BY_INTEL_200=200,
+    R_386_GNU_VTINHERIT=250,
+    R_386_GNU_VTENTRY=251,
+    _default_=Pass,
+)
+
+ENUM_RELOC_TYPE_x64 = dict(
+    R_X86_64_NONE=0,
+    R_X86_64_64=1,
+    R_X86_64_PC32=2,
+    R_X86_64_GOT32=3,
+    R_X86_64_PLT32=4,
+    R_X86_64_COPY=5,
+    R_X86_64_GLOB_DAT=6,
+    R_X86_64_JUMP_SLOT=7,
+    R_X86_64_RELATIVE=8,
+    R_X86_64_GOTPCREL=9,
+    R_X86_64_32=10,
+    R_X86_64_32S=11,
+    R_X86_64_16=12,
+    R_X86_64_PC16=13,
+    R_X86_64_8=14,
+    R_X86_64_PC8=15,
+    R_X86_64_DTPMOD64=16,
+    R_X86_64_DTPOFF64=17,
+    R_X86_64_TPOFF64=18,
+    R_X86_64_TLSGD=19,
+    R_X86_64_TLSLD=20,
+    R_X86_64_DTPOFF32=21,
+    R_X86_64_GOTTPOFF=22,
+    R_X86_64_TPOFF32=23,
+    R_X86_64_PC64=24,
+    R_X86_64_GOTOFF64=25,
+    R_X86_64_GOTPC32=26,
+    R_X86_64_GOT64=27,
+    R_X86_64_GOTPCREL64=28,
+    R_X86_64_GOTPC64=29,
+    R_X86_64_GOTPLT64=30,
+    R_X86_64_PLTOFF64=31,
+    R_X86_64_GOTPC32_TLSDESC=34,
+    R_X86_64_TLSDESC_CALL=35,
+    R_X86_64_TLSDESC=36,
+    R_X86_64_IRELATIVE=37,
+    R_X86_64_GNU_VTINHERIT=250,
+    R_X86_64_GNU_VTENTRY=251,
+    _default_=Pass,
+)
+
index 59c85b79b363a16b17861a623046af2dc27a88a7..10b99f9cfe248d85bcad3c107e895b6afeeff3c1 100644 (file)
@@ -121,6 +121,11 @@ class RelocationSection(Section):
             self.header['sh_entsize'] == expected_size,
             'Expected sh_entsize of SHT_REL section to be %s' % expected_size)
 
+    def is_RELA(self):
+        """ Is this a RELA relocation section? If not, it's REL.
+        """
+        return self.header['sh_type'] == 'SHT_RELA'
+
     def num_relocations(self):
         """ Number of relocations in the section
         """
@@ -169,6 +174,11 @@ class Relocation(object):
     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
         """
index 264f25c131b7acede429ca8c894f0446246b26ed..69293cc6cf9ff8e2de46008a116860862bcc772c 100755 (executable)
@@ -31,7 +31,7 @@ from elftools.elf.descriptions import (
     describe_e_version_numeric, describe_p_type, describe_p_flags,
     describe_sh_type, describe_sh_flags,
     describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
-    describe_symbol_shndx,
+    describe_symbol_shndx, describe_reloc_type,
     )
 
 
@@ -279,11 +279,36 @@ class ReadElf(object):
                 section.name,
                 self._format_hex(section['sh_offset']),
                 section.num_relocations()))
+            if section.is_RELA():
+                self._emitline("  Offset          Info           Type           Sym. Value    Sym. Name + Addend")
+            else:
+                self._emitline(" Offset     Info    Type            Sym.Value  Sym. Name")
+
+            # The symbol table section pointed to in sh_link
+            symtable = self.elffile.get_section(section['sh_link'])
+
             for rel in section.iter_relocations():
-                self._emitline('%s %s' % (
-                    self._format_hex(rel['r_offset'], fullhex=True, lead0x=False),
-                    self._format_hex(rel['r_info'], fullhex=True, lead0x=False)))
-                #print rel, rel.entry
+                hexwidth = 8 if self.elffile.elfclass == 32 else 12
+                symbol = symtable.get_symbol(rel['r_info_sym'])
+                self._emit('%s  %s %-17.17s %s %s%s' % (
+                    self._format_hex(rel['r_offset'], 
+                        fieldsize=hexwidth, lead0x=False),
+                    self._format_hex(rel['r_info'], 
+                        fieldsize=hexwidth, lead0x=False),
+                    describe_reloc_type(
+                        rel['r_info_type'], self.elffile['e_machine']),
+                    self._format_hex(
+                        symbol['st_value'],
+                        fullhex=True, lead0x=False),
+                    '  ' if self.elffile.elfclass == 32 else '',
+                    symbol.name,
+                    ))
+
+                if section.is_RELA():
+                    self._emit(' %s %x' % (
+                        '+' if rel['r_addend'] >= 0 else '-',
+                        abs(rel['r_addend'])))
+                self._emitline()
 
         if not has_relocation_sections:
             self._emitline('\nThere are no relocations in this file.')
index 24f40152814d6fede53bc75e9e6fd7736b18b8c0..a369b5ee0f4b50d4f82f1c3e5936eafa8b903abb 100755 (executable)
@@ -49,7 +49,7 @@ def run_test_on_file(filename):
     """
     success = True
     testlog.info("Running test on file '%s'" % filename)
-    for option in ['-e', '-s', '-x.text', '-p.shstrtab']:
+    for option in ['-e', '-s', '-r', '-x.text', '-p.shstrtab']:
         testlog.info("..option='%s'" % option)
         # stdouts will be a 2-element list: output of readelf and output 
         # of scripts/readelf.py