From 5fc2c25d3f3567020eaf17faf09ad074090ab6b3 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Mon, 15 Jan 2018 14:14:11 -0800 Subject: [PATCH] Implement e_machine-based section type decoding --- elftools/common/py3compat.py | 2 +- elftools/elf/descriptions.py | 7 +-- elftools/elf/elffile.py | 3 +- elftools/elf/enums.py | 102 ++++++++++++++++++++--------------- elftools/elf/structs.py | 28 +++++++--- test/test_mips_support.py | 10 +++- 6 files changed, 94 insertions(+), 58 deletions(-) diff --git a/elftools/common/py3compat.py b/elftools/common/py3compat.py index 9285d66..b901e07 100644 --- a/elftools/common/py3compat.py +++ b/elftools/common/py3compat.py @@ -28,7 +28,7 @@ if PY3: def iterbytes(b): """Return an iterator over the elements of a bytes object. - + For example, for b'abc' yields b'a', b'b' and then b'c'. """ for i in range(len(b)): diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py index 8dc6414..d197c14 100644 --- a/elftools/elf/descriptions.py +++ b/elftools/elf/descriptions.py @@ -7,7 +7,7 @@ # This code is in the public domain #------------------------------------------------------------------------------- from .enums import ( - ENUM_D_TAG, ENUM_E_VERSION, ENUM_P_TYPE, ENUM_SH_TYPE, + ENUM_D_TAG, ENUM_E_VERSION, ENUM_P_TYPE, ENUM_SH_TYPE_BASE, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_MIPS, ENUM_ATTR_TAG_ARM) @@ -65,8 +65,9 @@ def describe_p_flags(x): def describe_sh_type(x): if x in _DESCR_SH_TYPE: return _DESCR_SH_TYPE.get(x) - elif x >= ENUM_SH_TYPE['SHT_LOOS'] and x < ENUM_SH_TYPE['SHT_GNU_versym']: - return 'loos+%lx' % (x - ENUM_SH_TYPE['SHT_LOOS']) + elif (x >= ENUM_SH_TYPE_BASE['SHT_LOOS'] and + x < ENUM_SH_TYPE_BASE['SHT_GNU_versym']): + return 'loos+%lx' % (x - ENUM_SH_TYPE_BASE['SHT_LOOS']) else: return _unknown diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index 354088b..a1509ee 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -71,8 +71,7 @@ class ELFFile(object): self.structs.create_basic_structs() self.header = self._parse_elf_header() - self.elftype = self['e_type'] - self.structs.create_advanced_structs(self.elftype) + self.structs.create_advanced_structs(self['e_type'], self['e_machine']) self.stream.seek(0) self.e_ident_raw = self.stream.read(16) diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index 380cd2c..d8b6e1d 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -6,6 +6,7 @@ # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- +from ..common.utils import merge_dicts from ..construct import Pass @@ -267,7 +268,7 @@ ENUM_E_MACHINE = dict( ) # sh_type in the section header -ENUM_SH_TYPE = dict( +ENUM_SH_TYPE_BASE = dict( SHT_NULL=0, SHT_PROGBITS=1, SHT_SYMTAB=2, @@ -293,55 +294,70 @@ ENUM_SH_TYPE = dict( SHT_GNU_verdef=0x6ffffffd, # also SHT_SUNW_verdef SHT_GNU_verneed=0x6ffffffe, # also SHT_SUNW_verneed SHT_GNU_versym=0x6fffffff, # also SHT_SUNW_versym, SHT_HIOS - SHT_LOPROC=0x70000000, - SHT_HIPROC=0x7fffffff, + + # These are commented out because they carry no semantic meaning in themselves and + # may be overridden by target-specific enums. + #SHT_LOPROC=0x70000000, + #SHT_HIPROC=0x7fffffff, + SHT_LOUSER=0x80000000, SHT_HIUSER=0xffffffff, - SHT_AMD64_UNWIND=0x70000001, SHT_SUNW_LDYNSYM=0x6ffffff3, SHT_SUNW_syminfo=0x6ffffffc, - SHT_ARM_EXIDX=0x70000001, # also SHT_MIPS_MSYM - SHT_ARM_PREEMPTMAP=0x70000002, # also SHT_MIPS_CONFLICT - SHT_ARM_ATTRIBUTES=0x70000003, # also SHT_MIPS_GPTAB - SHT_ARM_DEBUGOVERLAY=0x70000004, # also SHT_MIPS_UCODE - SHT_MIPS_LIBLIST=0x70000000, - SHT_MIPS_DEBUG=0x70000005, - SHT_MIPS_REGINFO=0x70000006, - SHT_MIPS_PACKAGE=0x70000007, - SHT_MIPS_PACKSYM=0x70000008, - SHT_MIPS_RELD=0x70000009, - SHT_MIPS_IFACE=0x7000000b, - SHT_MIPS_CONTENT=0x7000000c, - SHT_MIPS_OPTIONS=0x7000000d, - SHT_MIPS_SHDR=0x70000010, - SHT_MIPS_FDESC=0x70000011, - SHT_MIPS_EXTSYM=0x70000012, - SHT_MIPS_DENSE=0x70000013, - SHT_MIPS_PDESC=0x70000014, - SHT_MIPS_LOCSYM=0x70000015, - SHT_MIPS_AUXSYM=0x70000016, - SHT_MIPS_OPTSYM=0x70000017, - SHT_MIPS_LOCSTR=0x70000018, - SHT_MIPS_LINE=0x70000019, - SHT_MIPS_RFDESC=0x7000001a, - SHT_MIPS_DELTASYM=0x7000001b, - SHT_MIPS_DELTAINST=0x7000001c, - SHT_MIPS_DELTACLASS=0x7000001d, - SHT_MIPS_DWARF=0x7000001e, - SHT_MIPS_DELTADECL=0x7000001f, - SHT_MIPS_SYMBOL_LIB=0x70000020, - SHT_MIPS_EVENTS=0x70000021, - SHT_MIPS_TRANSLATE=0x70000022, - SHT_MIPS_PIXIE=0x70000023, - SHT_MIPS_XLATE=0x70000024, - SHT_MIPS_XLATE_DEBUG=0x70000025, - SHT_MIPS_WHIRL=0x70000026, - SHT_MIPS_EH_REGION=0x70000027, - SHT_MIPS_XLATE_OLD=0x70000028, - SHT_MIPS_PDR_EXCEPTION=0x70000029, _default_=Pass, ) +ENUM_SH_TYPE_AMD64 = merge_dicts( + ENUM_SH_TYPE_BASE, + dict(SHT_AMD64_UNWIND=0x70000001)) + +ENUM_SH_TYPE_ARM = merge_dicts( + ENUM_SH_TYPE_BASE, + dict( + SHT_ARM_EXIDX=0x70000001, + SHT_ARM_PREEMPTMAP=0x70000002, + SHT_ARM_ATTRIBUTES=0x70000003, + SHT_ARM_DEBUGOVERLAY=0x70000004)) + +ENUM_SH_TYPE_MIPS = merge_dicts( + ENUM_SH_TYPE_BASE, + dict( + SHT_MIPS_LIBLIST=0x70000000, + SHT_MIPS_DEBUG=0x70000005, + SHT_MIPS_REGINFO=0x70000006, + SHT_MIPS_PACKAGE=0x70000007, + SHT_MIPS_PACKSYM=0x70000008, + SHT_MIPS_RELD=0x70000009, + SHT_MIPS_IFACE=0x7000000b, + SHT_MIPS_CONTENT=0x7000000c, + SHT_MIPS_OPTIONS=0x7000000d, + SHT_MIPS_SHDR=0x70000010, + SHT_MIPS_FDESC=0x70000011, + SHT_MIPS_EXTSYM=0x70000012, + SHT_MIPS_DENSE=0x70000013, + SHT_MIPS_PDESC=0x70000014, + SHT_MIPS_LOCSYM=0x70000015, + SHT_MIPS_AUXSYM=0x70000016, + SHT_MIPS_OPTSYM=0x70000017, + SHT_MIPS_LOCSTR=0x70000018, + SHT_MIPS_LINE=0x70000019, + SHT_MIPS_RFDESC=0x7000001a, + SHT_MIPS_DELTASYM=0x7000001b, + SHT_MIPS_DELTAINST=0x7000001c, + SHT_MIPS_DELTACLASS=0x7000001d, + SHT_MIPS_DWARF=0x7000001e, + SHT_MIPS_DELTADECL=0x7000001f, + SHT_MIPS_SYMBOL_LIB=0x70000020, + SHT_MIPS_EVENTS=0x70000021, + SHT_MIPS_TRANSLATE=0x70000022, + SHT_MIPS_PIXIE=0x70000023, + SHT_MIPS_XLATE=0x70000024, + SHT_MIPS_XLATE_DEBUG=0x70000025, + SHT_MIPS_WHIRL=0x70000026, + SHT_MIPS_EH_REGION=0x70000027, + SHT_MIPS_XLATE_OLD=0x70000028, + SHT_MIPS_PDR_EXCEPTION=0x70000029)) + ENUM_ELFCOMPRESS_TYPE = dict( ELFCOMPRESS_ZLIB=1, ELFCOMPRESS_LOOS=0x60000000, diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index 4fb665e..62c27f0 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -72,12 +72,12 @@ class ELFStructs(object): self._create_leb128() self._create_ntbs() - def create_advanced_structs(self, elftype=None): + def create_advanced_structs(self, e_type=None, e_machine=None): """ Create all ELF structs except the ehdr. They may possibly depend - on provided #elftype previously parsed from ehdr. + on provided e_type and/or e_machine parsed from ehdr. """ self._create_phdr() - self._create_shdr() + self._create_shdr(e_machine) self._create_chdr() self._create_sym() self._create_rel() @@ -87,7 +87,7 @@ class ELFStructs(object): self._create_gnu_verdef() self._create_gnu_versym() self._create_gnu_abi() - self._create_note(elftype) + self._create_note(e_type) self._create_stabs() self._create_arm_attributes() @@ -149,10 +149,22 @@ class ELFStructs(object): self.Elf_xword('p_align'), ) - def _create_shdr(self): + def _create_shdr(self, e_machine=None): + """Section header parsing. + + Depends on e_machine because of machine-specific values in sh_type. + """ + sh_type_dict = ENUM_SH_TYPE_BASE + if e_machine == 'EM_ARM': + sh_type_dict = ENUM_SH_TYPE_ARM + elif e_machine == 'EM_X86_64': + sh_type_dict = ENUM_SH_TYPE_AMD64 + elif e_machine == 'EM_MIPS': + sh_type_dict = ENUM_SH_TYPE_MIPS + self.Elf_Shdr = Struct('Elf_Shdr', self.Elf_word('sh_name'), - Enum(self.Elf_word('sh_type'), **ENUM_SH_TYPE), + Enum(self.Elf_word('sh_type'), **sh_type_dict), self.Elf_xword('sh_flags'), self.Elf_addr('sh_addr'), self.Elf_offset('sh_offset'), @@ -300,13 +312,13 @@ class ELFStructs(object): self.Elf_word('abi_tiny'), ) - def _create_note(self, elftype=None): + def _create_note(self, e_type=None): # Structure of "PT_NOTE" section self.Elf_Nhdr = Struct('Elf_Nhdr', self.Elf_word('n_namesz'), self.Elf_word('n_descsz'), Enum(self.Elf_word('n_type'), - **(ENUM_NOTE_N_TYPE if elftype != "ET_CORE" + **(ENUM_NOTE_N_TYPE if e_type != "ET_CORE" else ENUM_CORE_NOTE_N_TYPE)), ) diff --git a/test/test_mips_support.py b/test/test_mips_support.py index 0cd3720..780e2dc 100644 --- a/test/test_mips_support.py +++ b/test/test_mips_support.py @@ -2,6 +2,8 @@ # elftools tests # # Karl Vogel (karl.vogel@gmail.com) +# Eli Bendersky (eliben@gmail.com) +# # This code is in the public domain #------------------------------------------------------------------------------- import unittest @@ -11,7 +13,7 @@ from elftools.elf.elffile import ELFFile class TestMIPSSupport(unittest.TestCase): - def test_hello(self): + def test_basic(self): with open(os.path.join('test', 'testfiles_for_unittests', 'simple_gcc.elf.mips'), 'rb') as f: elf = ELFFile(f) @@ -22,6 +24,12 @@ class TestMIPSSupport(unittest.TestCase): self.assertEqual(elf.num_sections(), 25) self.assertEqual(elf.num_segments(), 0) + # Test that Mips-specific section types work; these types are + # available only when the file is identified as MIPS in the + # e_machine header field. + sec9 = elf.get_section(9) + self.assertEqual(sec9['sh_type'], 'SHT_MIPS_DWARF') + if __name__ == '__main__': unittest.main() -- 2.30.2