Skip to content

Commit

Permalink
Implement e_machine-based section type decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
eliben committed Jan 15, 2018
1 parent 18c99a9 commit 5fc2c25
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 58 deletions.
2 changes: 1 addition & 1 deletion elftools/common/py3compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def byte2int(b): return b

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)):
Expand Down
7 changes: 4 additions & 3 deletions elftools/elf/descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand Down
3 changes: 1 addition & 2 deletions elftools/elf/elffile.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ def __init__(self, stream):

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)

Expand Down
102 changes: 59 additions & 43 deletions elftools/elf/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -267,7 +268,7 @@
)

# sh_type in the section header
ENUM_SH_TYPE = dict(
ENUM_SH_TYPE_BASE = dict(
SHT_NULL=0,
SHT_PROGBITS=1,
SHT_SYMTAB=2,
Expand All @@ -293,55 +294,70 @@
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,
Expand Down
28 changes: 20 additions & 8 deletions elftools/elf/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ def create_basic_structs(self):
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()
Expand All @@ -87,7 +87,7 @@ def create_advanced_structs(self, elftype=None):
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()

Expand Down Expand Up @@ -149,10 +149,22 @@ def _create_phdr(self):
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'),
Expand Down Expand Up @@ -300,13 +312,13 @@ def _create_gnu_abi(self):
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)),
)

Expand Down
10 changes: 9 additions & 1 deletion test/test_mips_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -11,7 +13,7 @@


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)
Expand All @@ -22,6 +24,12 @@ def test_hello(self):
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()

0 comments on commit 5fc2c25

Please sign in to comment.