cie = self.cie
cie_decoded_table = cie.get_decoded()
last_line_in_CIE = copy.copy(cie_decoded_table.table[-1])
- cur_line = last_line_in_CIE
+ cur_line = copy.copy(last_line_in_CIE)
cur_line['pc'] = self['initial_location']
reg_order = copy.copy(cie_decoded_table.reg_order)
dwarf_assert(
isinstance(self, FDE),
'%s instruction must be in a FDE' % name)
- dwarf_assert(
- instr.args[0] in last_line_in_CIE,
- '%s: can not find register in CIE')
- cur_line[instr.args[0]] = last_line_in_CIE[instr.args[0]]
+ if instr.args[0] in last_line_in_CIE:
+ cur_line[instr.args[0]] = last_line_in_CIE[instr.args[0]]
+ else:
+ cur_line.pop(instr.args[0], None)
elif name == 'DW_CFA_remember_state':
line_stack.append(cur_line)
elif name == 'DW_CFA_restore_state':
'Unexpected instruction "%s" for a CIE' % instr)
def _full_reg_name(regnum):
- return 'r%s (%s)' % (regnum, describe_reg_name(regnum))
+ regname = describe_reg_name(regnum, _MACHINE_ARCH, False)
+ if regname:
+ return 'r%s (%s)' % (regnum, regname)
+ else:
+ return 'r%s' % regnum
if isinstance(entry, CIE):
cie = entry
return '(' + dwarf_expr_dumper.get_str() + ')'
-def describe_reg_name(regnum, machine_arch=None):
+def describe_reg_name(regnum, machine_arch=None, default=True):
""" Provide a textual description for a register name, given its serial
number. The number is expected to be valid.
"""
return _REG_NAMES_x86[regnum]
elif machine_arch == 'x64':
return _REG_NAMES_x64[regnum]
+ elif default:
+ return 'r%s' % regnum
else:
- return '<none>'
+ return None
#-------------------------------------------------------------------------------
EF_ARM_ABI_FLOAT_SOFT=0x00000200
EF_ARM_ABI_FLOAT_HARD=0x00000400
+ EF_MIPS_NOREORDER=1
+ EF_MIPS_PIC=2
+ EF_MIPS_CPIC=4
+ EF_MIPS_XGOT=8
+ EF_MIPS_64BIT_WHIRL=16
+ EF_MIPS_ABI2=32
+ EF_MIPS_ABI_ON32=64
+ EF_MIPS_NAN2008=1024
+ EF_MIPS_ARCH=0xf0000000
+ EF_MIPS_ARCH_1=0x00000000
+ EF_MIPS_ARCH_2=0x10000000
+ EF_MIPS_ARCH_3=0x20000000
+ EF_MIPS_ARCH_4=0x30000000
+ EF_MIPS_ARCH_5=0x40000000
+ EF_MIPS_ARCH_32=0x50000000
+ EF_MIPS_ARCH_64=0x60000000
+ EF_MIPS_ARCH_32R2=0x70000000
+ EF_MIPS_ARCH_64R2=0x80000000
+
class SHN_INDICES(object):
""" Special section indices
"""
# This code is in the public domain
#-------------------------------------------------------------------------------
from .enums import (
- ENUM_D_TAG, ENUM_E_VERSION, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64,
- ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64)
+ ENUM_D_TAG, ENUM_E_VERSION, ENUM_P_TYPE, ENUM_SH_TYPE,
+ ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64,
+ ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_MIPS)
from .constants import P_FLAGS, SH_FLAGS, SUNW_SYMINFO_FLAGS, VER_FLAGS
from ..common.py3compat import iteritems
return '0x%x' % ENUM_E_VERSION[x]
def describe_p_type(x):
- return _DESCR_P_TYPE.get(x, _unknown)
+ if x in _DESCR_P_TYPE:
+ return _DESCR_P_TYPE.get(x)
+ elif x >= ENUM_P_TYPE['PT_LOOS'] and x <= ENUM_P_TYPE['PT_HIOS']:
+ return 'LOOS+%lx' % (x - ENUM_P_TYPE['PT_LOOS'])
+ else:
+ return _unknown
def describe_p_flags(x):
s = ''
return s
def describe_sh_type(x):
- return _DESCR_SH_TYPE.get(x, _unknown)
+ 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'])
+ else:
+ return _unknown
def describe_sh_flags(x):
s = ''
return _DESCR_RELOC_TYPE_ARM.get(x, _unknown)
elif arch == 'AArch64':
return _DESCR_RELOC_TYPE_AARCH64.get(x, _unknown)
+ elif arch == 'MIPS':
+ return _DESCR_RELOC_TYPE_MIPS.get(x, _unknown)
else:
return 'unrecognized: %-7x' % (x & 0xFFFFFFFF)
SHT_ARM_PREEMPTMAP='ARM_PREEMPTMAP',
SHT_ARM_ATTRIBUTES='ARM_ATTRIBUTES',
SHT_ARM_DEBUGOVERLAY='ARM_DEBUGOVERLAY',
+ SHT_MIPS_LIBLIST='MIPS_LIBLIST',
+ SHT_MIPS_DEBUG='MIPS_DEBUG',
+ SHT_MIPS_REGINFO='MIPS_REGINFO',
+ SHT_MIPS_PACKAGE='MIPS_PACKAGE',
+ SHT_MIPS_PACKSYM='MIPS_PACKSYM',
+ SHT_MIPS_RELD='MIPS_RELD',
+ SHT_MIPS_IFACE='MIPS_IFACE',
+ SHT_MIPS_CONTENT='MIPS_CONTENT',
+ SHT_MIPS_OPTIONS='MIPS_OPTIONS',
+ SHT_MIPS_SHDR='MIPS_SHDR',
+ SHT_MIPS_FDESC='MIPS_FDESC',
+ SHT_MIPS_EXTSYM='MIPS_EXTSYM',
+ SHT_MIPS_DENSE='MIPS_DENSE',
+ SHT_MIPS_PDESC='MIPS_PDESC',
+ SHT_MIPS_LOCSYM='MIPS_LOCSYM',
+ SHT_MIPS_AUXSYM='MIPS_AUXSYM',
+ SHT_MIPS_OPTSYM='MIPS_OPTSYM',
+ SHT_MIPS_LOCSTR='MIPS_LOCSTR',
+ SHT_MIPS_LINE='MIPS_LINE',
+ SHT_MIPS_RFDESC='MIPS_RFDESC',
+ SHT_MIPS_DELTASYM='MIPS_DELTASYM',
+ SHT_MIPS_DELTAINST='MIPS_DELTAINST',
+ SHT_MIPS_DELTACLASS='MIPS_DELTACLASS',
+ SHT_MIPS_DWARF='MIPS_DWARF',
+ SHT_MIPS_DELTADECL='MIPS_DELTADECL',
+ SHT_MIPS_SYMBOL_LIB='MIPS_SYMBOL_LIB',
+ SHT_MIPS_EVENTS='MIPS_EVENTS',
+ SHT_MIPS_TRANSLATE='MIPS_TRANSLATE',
+ SHT_MIPS_PIXIE='MIPS_PIXIE',
+ SHT_MIPS_XLATE='MIPS_XLATE',
+ SHT_MIPS_XLATE_DEBUG='MIPS_XLATE_DEBUG',
+ SHT_MIPS_WHIRL='MIPS_WHIRL',
+ SHT_MIPS_EH_REGION='MIPS_EH_REGION',
+ SHT_MIPS_XLATE_OLD='MIPS_XLATE_OLD',
+ SHT_MIPS_PDR_EXCEPTION='MIPS_PDR_EXCEPTION',
)
_DESCR_SH_FLAGS = {
_DESCR_RELOC_TYPE_AARCH64 = dict(
(v, k) for k, v in iteritems(ENUM_RELOC_TYPE_AARCH64))
+_DESCR_RELOC_TYPE_MIPS = dict(
+ (v, k) for k, v in iteritems(ENUM_RELOC_TYPE_MIPS))
+
_DESCR_D_TAG = dict(
(v, k) for k, v in iteritems(ENUM_D_TAG))
return 'ARM'
elif self['e_machine'] == 'EM_AARCH64':
return 'AArch64'
+ elif self['e_machine'] == 'EM_MIPS':
+ return 'MIPS'
else:
return '<unknown>'
SHT_GNU_HASH=0x6ffffff6,
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_GNU_versym=0x6fffffff, # also SHT_SUNW_versym, SHT_HIOS
SHT_LOPROC=0x70000000,
SHT_HIPROC=0x7fffffff,
SHT_LOUSER=0x80000000,
SHT_AMD64_UNWIND=0x70000001,
SHT_SUNW_LDYNSYM=0x6ffffff3,
SHT_SUNW_syminfo=0x6ffffffc,
- SHT_ARM_EXIDX=0x70000001,
- SHT_ARM_PREEMPTMAP=0x70000002,
- SHT_ARM_ATTRIBUTES=0x70000003,
- SHT_ARM_DEBUGOVERLAY=0x70000004,
+ 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,
)
PT_SHLIB=5,
PT_PHDR=6,
PT_TLS=7,
+ PT_LOOS=0x60000000,
+ PT_HIOS=0x6fffffff,
PT_LOPROC=0x70000000,
PT_HIPROC=0x7fffffff,
PT_GNU_EH_FRAME=0x6474e550,
_default_=Pass,
)
+ENUM_RELOC_TYPE_MIPS = dict(
+ R_MIPS_NONE=0,
+ R_MIPS_16=1,
+ R_MIPS_32=2,
+ R_MIPS_REL32=3,
+ R_MIPS_26=4,
+ R_MIPS_HI16=5,
+ R_MIPS_LO16=6,
+ R_MIPS_GPREL16=7,
+ R_MIPS_LITERAL=8,
+ R_MIPS_GOT16=9,
+ R_MIPS_PC16=10,
+ R_MIPS_CALL16=11,
+ R_MIPS_GPREL32=12,
+ R_MIPS_SHIFT5=16,
+ R_MIPS_SHIFT6=17,
+ R_MIPS_64=18,
+ R_MIPS_GOT_DISP=19,
+ R_MIPS_GOT_PAGE=20,
+ R_MIPS_GOT_OFST=21,
+ R_MIPS_GOT_HI16=22,
+ R_MIPS_GOT_LO16=23,
+ R_MIPS_SUB=24,
+ R_MIPS_INSERT_A=25,
+ R_MIPS_INSERT_B=26,
+ R_MIPS_DELETE=27,
+ R_MIPS_HIGHER=28,
+ R_MIPS_HIGHEST=29,
+ R_MIPS_CALL_HI16=30,
+ R_MIPS_CALL_LO16=31,
+ R_MIPS_SCN_DISP=32,
+ R_MIPS_REL16=33,
+ R_MIPS_ADD_IMMEDIATE=34,
+ R_MIPS_PJUMP=35,
+ R_MIPS_RELGOT=36,
+ R_MIPS_JALR=37,
+ R_MIPS_TLS_DTPMOD32=38,
+ R_MIPS_TLS_DTPREL32=39,
+ R_MIPS_TLS_DTPMOD64=40,
+ R_MIPS_TLS_DTPREL64=41,
+ R_MIPS_TLS_GD=42,
+ R_MIPS_TLS_LDM=43,
+ R_MIPS_TLS_DTPREL_HI16=44,
+ R_MIPS_TLS_DTPREL_LO16=45,
+ R_MIPS_TLS_GOTTPREL=46,
+ R_MIPS_TLS_TPREL32=47,
+ R_MIPS_TLS_TPREL64=48,
+ R_MIPS_TLS_TPREL_HI16=49,
+ R_MIPS_TLS_TPREL_LO16=50,
+ R_MIPS_GLOB_DAT=51,
+ R_MIPS_COPY=126,
+ R_MIPS_JUMP_SLOT=127,
+ _default_=Pass,
+)
+
ENUM_RELOC_TYPE_i386 = dict(
R_386_NONE=0,
R_386_32=1,
from ..common.exceptions import ELFRelocationError
from ..common.utils import elf_assert, struct_parse
from .sections import Section
-from .enums import ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
+from .enums import ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64, ENUM_RELOC_TYPE_MIPS
class Relocation(object):
raise ELFRelocationError(
'Unexpected REL relocation for x64: %s' % reloc)
recipe = self._RELOCATION_RECIPES_X64.get(reloc_type, None)
+ elif self.elffile.get_machine_arch() == 'MIPS':
+ if reloc.is_RELA():
+ raise ELFRelocationError(
+ 'Unexpected RELA relocation for MIPS: %s' % reloc)
+ recipe = self._RELOCATION_RECIPES_MIPS.get(reloc_type, None)
if recipe is None:
raise ELFRelocationError(
def _reloc_calc_sym_plus_addend_pcrel(value, sym_value, offset, addend=0):
return sym_value + addend - offset
+ # https://dmz-portal.mips.com/wiki/MIPS_relocation_types
+ _RELOCATION_RECIPES_MIPS = {
+ ENUM_RELOC_TYPE_MIPS['R_MIPS_NONE']: _RELOCATION_RECIPE_TYPE(
+ bytesize=4, has_addend=False, calc_func=_reloc_calc_identity),
+ ENUM_RELOC_TYPE_MIPS['R_MIPS_32']: _RELOCATION_RECIPE_TYPE(
+ bytesize=4, has_addend=False,
+ calc_func=_reloc_calc_sym_plus_value),
+ }
+
_RELOCATION_RECIPES_X86 = {
ENUM_RELOC_TYPE_i386['R_386_NONE']: _RELOCATION_RECIPE_TYPE(
bytesize=4, has_addend=False, calc_func=_reloc_calc_identity),
version = flags & E_FLAGS.EF_ARM_EABIMASK
if version == E_FLAGS.EF_ARM_EABI_VER5:
description += ", Version5 EABI"
+ elif self.elffile['e_machine'] == "EM_MIPS":
+ if flags & E_FLAGS.EF_MIPS_NOREORDER:
+ description += ", noreorder"
+ if flags & E_FLAGS.EF_MIPS_CPIC:
+ description += ", cpic"
+ if not (flags & E_FLAGS.EF_MIPS_ABI2) and not (flags & E_FLAGS.EF_MIPS_ABI_ON32):
+ description += ", o32"
+ if (flags & E_FLAGS.EF_MIPS_ARCH) == E_FLAGS.EF_MIPS_ARCH_1:
+ description += ", mips1"
+
return description
def display_program_headers(self, show_heading=True):
reg_order = sorted(ifilter(
lambda r: r != ra_regnum,
decoded_table.reg_order))
+ if len(decoded_table.reg_order):
+
+ # Headings for the registers
+ for regnum in reg_order:
+ self._emit('%-6s' % describe_reg_name(regnum))
+ self._emitline('ra ')
- # Headings for the registers
- for regnum in reg_order:
- self._emit('%-6s' % describe_reg_name(regnum))
- self._emitline('ra ')
+ # Now include ra_regnum in reg_order to print its values similarly
+ # to the other registers.
+ reg_order.append(ra_regnum)
+ else:
+ self._emitline()
- # Now include ra_regnum in reg_order to print its values similarly
- # to the other registers.
- reg_order.append(ra_regnum)
for line in decoded_table.table:
self._emit(self._format_hex(
line['pc'], fullhex=True, lead0x=False))
--- /dev/null
+#-------------------------------------------------------------------------------
+# elftools tests
+#
+# Karl Vogel (karl.vogel@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+import os
+
+from utils import setup_syspath; setup_syspath()
+from elftools.elf.elffile import ELFFile
+
+class TestMIPSSupport(unittest.TestCase):
+ def test_hello(self):
+ with open(os.path.join('test', 'testfiles_for_unittests',
+ 'simple_gcc.elf.mips'), 'rb') as f:
+ elf = ELFFile(f)
+ self.assertEqual(elf.get_machine_arch(), 'MIPS')
+
+ # Check some other properties of this ELF file derived from readelf
+ self.assertEqual(elf['e_entry'], 0x0)
+ self.assertEqual(elf.num_sections(), 25)
+ self.assertEqual(elf.num_segments(), 0)
+
+if __name__ == '__main__':
+ unittest.main()
+