Implement e_machine-based section type decoding
authorEli Bendersky <eliben@gmail.com>
Mon, 15 Jan 2018 22:14:11 +0000 (14:14 -0800)
committerEli Bendersky <eliben@gmail.com>
Mon, 15 Jan 2018 22:14:11 +0000 (14:14 -0800)
elftools/common/py3compat.py
elftools/elf/descriptions.py
elftools/elf/elffile.py
elftools/elf/enums.py
elftools/elf/structs.py
test/test_mips_support.py

index 9285d66b279aa9326adece25e3e38416699002a0..b901e078881fad0ae30926258c1743c617e77326 100644 (file)
@@ -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)):
index 8dc641407b92616fc4800d23a67619c5e0478bbf..d197c1400468438f25c5294847e295387f1d8dc4 100644 (file)
@@ -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
 
index 354088b8854319d7017faf045f0d088e087d48cc..a1509eeff5a944aa9787cdb31d2b6bfdf9f6dcce 100644 (file)
@@ -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)
 
index 380cd2c2a266aa05ad37ade76c8d1a3fea7a242a..d8b6e1d775cff698b6d80a7076fc97e0ed7910b5 100644 (file)
@@ -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,
index 4fb665ed60fa38a5e2c698dd063120657a7bb333..62c27f00638efd8ecb96335f8fbe7c4140e1b4ab 100644 (file)
@@ -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)),
         )
 
index 0cd37208ff416593018809bd778415a473b984d7..780e2dc0252e0993c713cd0fb3460125b945ffff 100644 (file)
@@ -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()