From 89a824fd227b7e006dbbc18cf09006bdaeb350e4 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 23 Sep 2011 10:59:59 +0300 Subject: [PATCH] relocation output working in readelf comparison --- elftools/elf/descriptions.py | 39 ++++++++++------ elftools/elf/enums.py | 91 ++++++++++++++++++++++++++++++++++++ elftools/elf/sections.py | 10 ++++ scripts/readelf.py | 35 ++++++++++++-- tests/run_tests.py | 2 +- 5 files changed, 158 insertions(+), 19 deletions(-) diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py index 35232b9..f404898 100644 --- a/elftools/elf/descriptions.py +++ b/elftools/elf/descriptions.py @@ -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 = '' _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()) + diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index c13d15f..78302ae 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -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, +) + diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py index 59c85b7..10b99f9 100644 --- a/elftools/elf/sections.py +++ b/elftools/elf/sections.py @@ -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 """ diff --git a/scripts/readelf.py b/scripts/readelf.py index 264f25c..69293cc 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -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.') diff --git a/tests/run_tests.py b/tests/run_tests.py index 24f4015..a369b5e 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -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 -- 2.30.2