# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
-from ..construct import Subconstruct, ConstructError, ArrayError
+from ..construct import (
+ Subconstruct, ConstructError, ArrayError, Adapter, Field, RepeatUntil,
+ Rename
+ )
class RepeatUntilExcluding(Subconstruct):
raise NotImplementedError('no building')
def _sizeof(self, context):
raise SizeofError("can't calculate size")
+
+
+def _LEB128_reader():
+ """ Read LEB128 variable-length data from the stream. The data is terminated
+ by a byte with 0 in its highest bit.
+ """
+ return RepeatUntil(
+ lambda obj, ctx: ord(obj) < 0x80,
+ Field(None, 1))
+
+
+class _ULEB128Adapter(Adapter):
+ """ An adapter for ULEB128, given a sequence of bytes in a sub-construct.
+ """
+ def _decode(self, obj, context):
+ value = 0
+ for b in reversed(obj):
+ value = (value << 7) + (ord(b) & 0x7F)
+ return value
+
+
+class _SLEB128Adapter(Adapter):
+ """ An adapter for SLEB128, given a sequence of bytes in a sub-construct.
+ """
+ def _decode(self, obj, context):
+ value = 0
+ for b in reversed(obj):
+ value = (value << 7) + (ord(b) & 0x7F)
+ if ord(obj[-1]) & 0x40:
+ # negative -> sign extend
+ value |= - (1 << (7 * len(obj)))
+ return value
+
+
+def ULEB128(name):
+ """ A construct creator for ULEB128 encoding.
+ """
+ return Rename(name, _ULEB128Adapter(_LEB128_reader()))
+
+
+def SLEB128(name):
+ """ A construct creator for SLEB128 encoding.
+ """
+ return Rename(name, _SLEB128Adapter(_LEB128_reader()))
from ..construct import (
UBInt8, UBInt16, UBInt32, UBInt64, ULInt8, ULInt16, ULInt32, ULInt64,
SBInt8, SBInt16, SBInt32, SBInt64, SLInt8, SLInt16, SLInt32, SLInt64,
- Adapter, Struct, ConstructError, If, RepeatUntil, Field, Rename, Enum,
- Array, PrefixedArray, CString, Embed, StaticField
+ Adapter, Struct, ConstructError, If, Enum, Array, PrefixedArray,
+ CString, Embed, StaticField
)
-from ..common.construct_utils import RepeatUntilExcluding
-
+from ..common.construct_utils import RepeatUntilExcluding, ULEB128, SLEB128
from .enums import *
self.Dwarf_initial_length = _InitialLength
def _create_leb128(self):
- self.Dwarf_uleb128 = _ULEB128
- self.Dwarf_sleb128 = _SLEB128
+ self.Dwarf_uleb128 = ULEB128
+ self.Dwarf_sleb128 = SLEB128
def _create_cu_header(self):
self.Dwarf_CU_header = Struct('Dwarf_CU_header',
else:
raise ConstructError("Failed decoding initial length for %X" % (
obj.first))
-
-
-def _LEB128_reader():
- """ Read LEB128 variable-length data from the stream. The data is terminated
- by a byte with 0 in its highest bit.
- """
- return RepeatUntil(
- lambda obj, ctx: ord(obj) < 0x80,
- Field(None, 1))
-
-
-class _ULEB128Adapter(Adapter):
- """ An adapter for ULEB128, given a sequence of bytes in a sub-construct.
- """
- def _decode(self, obj, context):
- value = 0
- for b in reversed(obj):
- value = (value << 7) + (ord(b) & 0x7F)
- return value
-
-
-class _SLEB128Adapter(Adapter):
- """ An adapter for SLEB128, given a sequence of bytes in a sub-construct.
- """
- def _decode(self, obj, context):
- value = 0
- for b in reversed(obj):
- value = (value << 7) + (ord(b) & 0x7F)
- if ord(obj[-1]) & 0x40:
- # negative -> sign extend
- value |= - (1 << (7 * len(obj)))
- return value
-
-
-def _ULEB128(name):
- """ A construct creator for ULEB128 encoding.
- """
- return Rename(name, _ULEB128Adapter(_LEB128_reader()))
-
-
-def _SLEB128(name):
- """ A construct creator for SLEB128 encoding.
- """
- return Rename(name, _SLEB128Adapter(_LEB128_reader()))
from .enums import (
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)
+ ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64, ENUM_RELOC_TYPE_MIPS,
+ ENUM_ATTR_TAG_ARM)
from .constants import P_FLAGS, SH_FLAGS, SUNW_SYMINFO_FLAGS, VER_FLAGS
from ..common.py3compat import iteritems
def describe_ei_class(x):
return _DESCR_EI_CLASS.get(x, _unknown)
+
def describe_ei_data(x):
return _DESCR_EI_DATA.get(x, _unknown)
+
def describe_ei_version(x):
s = '%d' % ENUM_E_VERSION[x]
if x == 'EV_CURRENT':
s += ' (current)'
return s
+
def describe_ei_osabi(x):
return _DESCR_EI_OSABI.get(x, _unknown)
+
def describe_e_type(x):
return _DESCR_E_TYPE.get(x, _unknown)
+
def describe_e_machine(x):
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):
if x in _DESCR_P_TYPE:
return _DESCR_P_TYPE.get(x)
else:
return _unknown
+
def describe_p_flags(x):
s = ''
for flag in (P_FLAGS.PF_R, P_FLAGS.PF_W, P_FLAGS.PF_X):
s += _DESCR_P_FLAGS[flag] if (x & flag) else ' '
return s
+
def describe_sh_type(x):
if x in _DESCR_SH_TYPE:
return _DESCR_SH_TYPE.get(x)
else:
return _unknown
+
def describe_sh_flags(x):
s = ''
for flag in (
s += _DESCR_SH_FLAGS[flag] if (x & flag) else ''
return s
+
def describe_symbol_type(x):
return _DESCR_ST_INFO_TYPE.get(x, _unknown)
+
def describe_symbol_bind(x):
return _DESCR_ST_INFO_BIND.get(x, _unknown)
+
def describe_symbol_visibility(x):
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, elffile):
arch = elffile.get_machine_arch()
if arch == 'x86':
else:
return 'unrecognized: %-7x' % (x & 0xFFFFFFFF)
+
def describe_dyn_tag(x):
return _DESCR_D_TAG.get(x, _unknown)
SUNW_SYMINFO_FLAGS.SYMINFO_FLG_INTERPOSE,
SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DEFERRED) if x & flag)
+
def describe_symbol_boundto(x):
return _DESCR_SYMINFO_BOUNDTO.get(x, '%3s' % x)
+
def describe_ver_flags(x):
return ' | '.join(_DESCR_VER_FLAGS[flag] for flag in (
VER_FLAGS.VER_FLG_WEAK,
VER_FLAGS.VER_FLG_BASE,
VER_FLAGS.VER_FLG_INFO) if x & flag)
+
def describe_note(x):
n_desc = x['n_desc']
desc = ''
_DESCR_NOTE_N_TYPE.get(x['n_type'], _unknown))
return '%s (%s)%s' % (note_type, note_type_desc, desc)
+
+def describe_attr_tag_arm(tag, val, extra):
+ idx = ENUM_ATTR_TAG_ARM[tag] - 1
+ d_entry = _DESCR_ATTR_VAL_ARM[idx]
+
+ if d_entry is None:
+ if tag == 'TAG_COMPATIBILITY':
+ return (_DESCR_ATTR_TAG_ARM[tag]
+ + 'flag = %d, vendor = %s' % (val, extra))
+
+ elif tag == 'TAG_ALSO_COMPATIBLE_WITH':
+ if val.tag == 'TAG_CPU_ARCH':
+ return _DESCR_ATTR_TAG_ARM[tag] + d_entry[val]
+
+ else:
+ return _DESCR_ATTR_TAG_ARM[tag] + '??? (%d)' % val.tag
+
+ elif tag == 'TAG_NODEFAULTS':
+ return _DESCR_ATTR_TAG_ARM[tag] + 'True'
+
+ s = _DESCR_ATTR_TAG_ARM[tag]
+ s += '"%s"' % val if val else ''
+ return s
+
+ else:
+ return _DESCR_ATTR_TAG_ARM[tag] + d_entry[val]
+
+
#-------------------------------------------------------------------------------
_unknown = '<unknown>'
ELFCLASS64='ELF64',
)
+
_DESCR_EI_DATA = dict(
ELFDATANONE='none',
ELFDATA2LSB="2's complement, little endian",
ELFDATA2MSB="2's complement, big endian",
)
+
_DESCR_EI_OSABI = dict(
ELFOSABI_SYSV='UNIX - System V',
ELFOSABI_HPUX='UNIX - HP-UX',
ELFOSABI_STANDALONE='Standalone App',
)
+
_DESCR_E_TYPE = dict(
ET_NONE='NONE (None)',
ET_REL='REL (Relocatable file)',
PROC_SPECIFIC='Processor Specific',
)
+
_DESCR_E_MACHINE = dict(
EM_NONE='None',
EM_M32='WE32100',
RESERVED='RESERVED',
)
+
_DESCR_P_TYPE = dict(
PT_NULL='NULL',
PT_LOAD='LOAD',
PT_AARCH64_UNWIND='AARCH64_UNWIND',
)
+
_DESCR_P_FLAGS = {
P_FLAGS.PF_X: 'E',
P_FLAGS.PF_R: 'R',
P_FLAGS.PF_W: 'W',
}
+
_DESCR_SH_TYPE = dict(
SHT_NULL='NULL',
SHT_PROGBITS='PROGBITS',
SHT_MIPS_PDR_EXCEPTION='MIPS_PDR_EXCEPTION',
)
+
_DESCR_SH_FLAGS = {
SH_FLAGS.SHF_WRITE: 'W',
SH_FLAGS.SHF_ALLOC: 'A',
SH_FLAGS.SHF_EXCLUDE: 'E',
}
+
_DESCR_ST_INFO_TYPE = dict(
STT_NOTYPE='NOTYPE',
STT_OBJECT='OBJECT',
STT_SRELC='SRELC',
)
+
_DESCR_ST_INFO_BIND = dict(
STB_LOCAL='LOCAL',
STB_GLOBAL='GLOBAL',
STB_WEAK='WEAK',
)
+
_DESCR_ST_VISIBILITY = dict(
STV_DEFAULT='DEFAULT',
STV_INTERNAL='INTERNAL',
STV_ELIMINATE='ELIMINATE',
)
+
_DESCR_ST_SHNDX = dict(
SHN_UNDEF='UND',
SHN_ABS='ABS',
SHN_COMMON='COM',
)
+
_DESCR_SYMINFO_FLAGS = {
SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECT: 'D',
SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DIRECTBIND: 'B',
SUNW_SYMINFO_FLAGS.SYMINFO_FLG_DEFERRED: 'P',
}
+
_DESCR_SYMINFO_BOUNDTO = dict(
SYMINFO_BT_SELF='<self>',
SYMINFO_BT_PARENT='<parent>',
SYMINFO_BT_EXTERN='<extern>',
)
+
_DESCR_VER_FLAGS = {
0: '',
VER_FLAGS.VER_FLG_BASE: 'BASE',
VER_FLAGS.VER_FLG_INFO: 'INFO',
}
+
# PT_NOTE section types
_DESCR_NOTE_N_TYPE = dict(
NT_GNU_ABI_TAG='ABI version tag',
NT_GNU_GOLD_VERSION='gold version',
)
+
# Values in GNU .note.ABI-tag notes (n_type=='NT_GNU_ABI_TAG')
_DESCR_NOTE_ABI_TAG_OS = dict(
ELF_NOTE_OS_LINUX='Linux',
ELF_NOTE_OS_SYLLABLE='Syllable',
)
+
_DESCR_RELOC_TYPE_i386 = dict(
(v, k) for k, v in iteritems(ENUM_RELOC_TYPE_i386))
+
_DESCR_RELOC_TYPE_x64 = dict(
(v, k) for k, v in iteritems(ENUM_RELOC_TYPE_x64))
+
_DESCR_RELOC_TYPE_ARM = dict(
(v, k) for k, v in iteritems(ENUM_RELOC_TYPE_ARM))
+
_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))
+
+
+_DESCR_ATTR_TAG_ARM = dict(
+ TAG_FILE='File Attributes',
+ TAG_SECTION='Section Attributes:',
+ TAG_SYMBOL='Symbol Attributes:',
+ TAG_CPU_RAW_NAME='Tag_CPU_raw_name: ',
+ TAG_CPU_NAME='Tag_CPU_name: ',
+ TAG_CPU_ARCH='Tag_CPU_arch: ',
+ TAG_CPU_ARCH_PROFILE='Tag_CPU_arch_profile: ',
+ TAG_ARM_ISA_USE='Tag_ARM_ISA_use: ',
+ TAG_THUMB_ISA_USE='Tag_Thumb_ISA_use: ',
+ TAG_FP_ARCH='Tag_FP_arch: ',
+ TAG_WMMX_ARCH='Tag_WMMX_arch: ',
+ TAG_ADVANCED_SIMD_ARCH='Tag_Advanced_SIMD_arch: ',
+ TAG_PCS_CONFIG='Tag_PCS_config: ',
+ TAG_ABI_PCS_R9_USE='Tag_ABI_PCS_R9_use: ',
+ TAG_ABI_PCS_RW_DATA='Tag_ABI_PCS_RW_use: ',
+ TAG_ABI_PCS_RO_DATA='Tag_ABI_PCS_RO_use: ',
+ TAG_ABI_PCS_GOT_USE='Tag_ABI_PCS_GOT_use: ',
+ TAG_ABI_PCS_WCHAR_T='Tag_ABI_PCS_wchar_t: ',
+ TAG_ABI_FP_ROUNDING='Tag_ABI_FP_rounding: ',
+ TAG_ABI_FP_DENORMAL='Tag_ABI_FP_denormal: ',
+ TAG_ABI_FP_EXCEPTIONS='Tag_ABI_FP_exceptions: ',
+ TAG_ABI_FP_USER_EXCEPTIONS='Tag_ABI_FP_user_exceptions: ',
+ TAG_ABI_FP_NUMBER_MODEL='Tag_ABI_FP_number_model: ',
+ TAG_ABI_ALIGN_NEEDED='Tag_ABI_align_needed: ',
+ TAG_ABI_ALIGN_PRESERVED='Tag_ABI_align_preserved: ',
+ TAG_ABI_ENUM_SIZE='Tag_ABI_enum_size: ',
+ TAG_ABI_HARDFP_USE='Tag_ABI_HardFP_use: ',
+ TAG_ABI_VFP_ARGS='Tag_ABI_VFP_args: ',
+ TAG_ABI_WMMX_ARGS='Tag_ABI_WMMX_args: ',
+ TAG_ABI_OPTIMIZATION_GOALS='Tag_ABI_optimization_goals: ',
+ TAG_ABI_FP_OPTIMIZATION_GOALS='Tag_ABI_FP_optimization_goals: ',
+ TAG_COMPATIBILITY='Tag_compatibility: ',
+ TAG_CPU_UNALIGNED_ACCESS='Tag_CPU_unaligned_access: ',
+ TAG_FP_HP_EXTENSION='Tag_FP_HP_extension: ',
+ TAG_ABI_FP_16BIT_FORMAT='Tag_ABI_FP_16bit_format: ',
+ TAG_MPEXTENSION_USE='Tag_MPextension_use: ',
+ TAG_DIV_USE='Tag_DIV_use: ',
+ TAG_NODEFAULTS='Tag_nodefaults: ',
+ TAG_ALSO_COMPATIBLE_WITH='Tag_also_compatible_with: ',
+ TAG_T2EE_USE='Tag_T2EE_use: ',
+ TAG_CONFORMANCE='Tag_conformance: ',
+ TAG_VIRTUALIZATION_USE='Tag_Virtualization_use: ',
+ TAG_MPEXTENSION_USE_OLD='Tag_MPextension_use_old: ',
+)
+
+
+_DESCR_ATTR_VAL_ARM = [
+ None, #1
+ None, #2
+ None, #3
+ None, #4
+ None, #5
+ { #6 TAG_CPU_ARCH
+ 0 : 'Pre-v4',
+ 1 : 'v4',
+ 2 : 'v4T',
+ 3 : 'v5T',
+ 4 : 'v5TE',
+ 5 : 'v5TEJ',
+ 6 : 'v6',
+ 7 : 'v6KZ',
+ 8 : 'v6T2',
+ 9 : 'v6K',
+ 10: 'v7',
+ 11: 'v6-M',
+ 12: 'v6S-M',
+ 13: 'v7E-M',
+ 14: 'v8',
+ 15: 'v8-R',
+ 16: 'v8-M.baseline',
+ 17: 'v8-M.mainline',
+ },
+ { #7 TAG_CPU_ARCH_PROFILE
+ 0x00: 'None',
+ 0x41: 'Application',
+ 0x52: 'Realtime',
+ 0x4D: 'Microcontroller',
+ 0x53: 'Application or Realtime',
+ },
+ { #8 TAG_ARM_ISA
+ 0: 'No',
+ 1: 'Yes',
+ },
+ { #9 TAG_THUMB_ISA
+ 0: 'No',
+ 1: 'Thumb-1',
+ 2: 'Thumb-2',
+ 3: 'Yes',
+ },
+ { #10 TAG_FP_ARCH
+ 0: 'No',
+ 1: 'VFPv1',
+ 2: 'VFPv2 ',
+ 3: 'VFPv3',
+ 4: 'VFPv3-D16',
+ 5: 'VFPv4',
+ 6: 'VFPv4-D16',
+ 7: 'FP ARM v8',
+ 8: 'FPv5/FP-D16 for ARMv8',
+ },
+ { #11 TAG_WMMX_ARCH
+ 0: 'No',
+ 1: 'WMMXv1',
+ 2: 'WMMXv2',
+ },
+ { #12 TAG_ADVANCED_SIMD_ARCH
+ 0: 'No',
+ 1: 'NEONv1',
+ 2: 'NEONv1 with Fused-MAC',
+ 3: 'NEON for ARMv8',
+ 4: 'NEON for ARMv8.1',
+ },
+ { #13 TAG_PCS_CONFIG
+ 0: 'None',
+ 1: 'Bare platform',
+ 2: 'Linux application',
+ 3: 'Linux DSO',
+ 4: 'PalmOS 2004',
+ 5: 'PalmOS (reserved)',
+ 6: 'SymbianOS 2004',
+ 7: 'SymbianOS (reserved)',
+ },
+ { #14 TAG_ABI_PCS_R9_USE
+ 0: 'v6',
+ 1: 'SB',
+ 2: 'TLS',
+ 3: 'Unused',
+ },
+ { #15 TAG_ABI_PCS_RW_DATA
+ 0: 'Absolute',
+ 1: 'PC-relative',
+ 2: 'SB-relative',
+ 3: 'None',
+ },
+ { #16 TAG_ABI_PCS_RO_DATA
+ 0: 'Absolute',
+ 1: 'PC-relative',
+ 2: 'None',
+ },
+ { #17 TAG_ABI_PCS_GOT_USE
+ 0: 'None',
+ 1: 'direct',
+ 2: 'GOT-indirect',
+ },
+ { #18 TAG_ABI_PCS_WCHAR_T
+ 0: 'None',
+ 1: '??? 1',
+ 2: '2',
+ 3: '??? 3',
+ 4: '4',
+ },
+ { #19 TAG_ABI_FP_ROUNDING
+ 0: 'Unused',
+ 1: 'Needed',
+ },
+ { #20 TAG_ABI_FP_DENORMAL
+ 0: 'Unused',
+ 1: 'Needed',
+ 2: 'Sign only',
+ },
+ { #21 TAG_ABI_FP_EXCEPTIONS
+ 0: 'Unused',
+ 1: 'Needed',
+ },
+ { #22 TAG_ABI_FP_USER_EXCEPTIONS
+ 0: 'Unused',
+ 1: 'Needed',
+ },
+ { #23 TAG_ABI_FP_NUMBER_MODEL
+ 0: 'Unused',
+ 1: 'Finite',
+ 2: 'RTABI',
+ 3: 'IEEE 754',
+ },
+ { #24 TAG_ABI_ALIGN_NEEDED
+ 0: 'None',
+ 1: '8-byte',
+ 2: '4-byte',
+ 3: '??? 3',
+ },
+ { #25 TAG_ABI_ALIGN_PRESERVED
+ 0: 'None',
+ 1: '8-byte, except leaf SP',
+ 2: '8-byte',
+ 3: '??? 3',
+ },
+ { #26 TAG_ABI_ENUM_SIZE
+ 0: 'Unused',
+ 1: 'small',
+ 2: 'int',
+ 3: 'forced to int',
+ },
+ { #27 TAG_ABI_HARDFP_USE
+ 0: 'As Tag_FP_arch',
+ 1: 'SP only',
+ 2: 'Reserved',
+ 3: 'Deprecated',
+ },
+ { #28 TAG_ABI_VFP_ARGS
+ 0: 'AAPCS',
+ 1: 'VFP registers',
+ 2: 'custom',
+ 3: 'compatible',
+ },
+ { #29 TAG_ABI_WMMX_ARGS
+ 0: 'AAPCS',
+ 1: 'WMMX registers',
+ 2: 'custom',
+ },
+ { #30 TAG_ABI_OPTIMIZATION_GOALS
+ 0: 'None',
+ 1: 'Prefer Speed',
+ 2: 'Aggressive Speed',
+ 3: 'Prefer Size',
+ 4: 'Aggressive Size',
+ 5: 'Prefer Debug',
+ 6: 'Aggressive Debug',
+ },
+ { #31 TAG_ABI_FP_OPTIMIZATION_GOALS
+ 0: 'None',
+ 1: 'Prefer Speed',
+ 2: 'Aggressive Speed',
+ 3: 'Prefer Size',
+ 4: 'Aggressive Size',
+ 5: 'Prefer Accuracy',
+ 6: 'Aggressive Accuracy',
+ },
+ { #32 TAG_COMPATIBILITY
+ 0: 'No',
+ 1: 'Yes',
+ },
+ None, #33
+ { #34 TAG_CPU_UNALIGNED_ACCESS
+ 0: 'None',
+ 1: 'v6',
+ },
+ None, #35
+ { #36 TAG_FP_HP_EXTENSION
+ 0: 'Not Allowed',
+ 1: 'Allowed',
+ },
+ None, #37
+ { #38 TAG_ABI_FP_16BIT_FORMAT
+ 0: 'None',
+ 1: 'IEEE 754',
+ 2: 'Alternative Format',
+ },
+ None, #39
+ None, #40
+ None, #41
+ { #42 TAG_MPEXTENSION_USE
+ 0: 'Not Allowed',
+ 1: 'Allowed',
+ },
+ None, #43
+ { #44 TAG_DIV_USE
+ 0: 'Allowed in Thumb-ISA, v7-R or v7-M',
+ 1: 'Not allowed',
+ 2: 'Allowed in v7-A with integer division extension',
+ },
+ None, #45
+ None, #46
+ None, #47
+ None, #48
+ None, #49
+ None, #50
+ None, #51
+ None, #52
+ None, #53
+ None, #54
+ None, #55
+ None, #56
+ None, #57
+ None, #58
+ None, #59
+ None, #60
+ None, #61
+ None, #62
+ None, #63
+ None, #64
+ None, #65
+ { #66 TAG_FP_HP_EXTENSION
+ 0: 'Not Allowed',
+ 1: 'Allowed',
+ },
+ None, #67
+ { #68 TAG_VIRTUALIZATION_USE
+ 0: 'Not Allowed',
+ 1: 'TrustZone',
+ 2: 'Virtualization Extensions',
+ 3: 'TrustZone and Virtualization Extensions',
+ },
+ None, #69
+ { #70 TAG_MPEXTENSION_USE_OLD
+ 0: 'Not Allowed',
+ 1: 'Allowed',
+ },
+]
from .sections import (
Section, StringTableSection, SymbolTableSection,
SUNWSyminfoTableSection, NullSection, NoteSection,
- StabSection)
+ StabSection, ARMAttributesSection)
from .dynamic import DynamicSection, DynamicSegment
from .relocation import RelocationSection, RelocationHandler
from .gnuversions import (
return NoteSection(section_header, name, self)
elif sectype == 'SHT_PROGBITS' and name == '.stab':
return StabSection(section_header, name, self)
+ elif sectype == 'SHT_ARM_ATTRIBUTES':
+ return ARMAttributesSection(section_header, name, self)
else:
return Section(section_header, name, self)
VER_NDX_ELIMINATE=0xff01,
_default_=Pass,
)
+
# Sunw Syminfo Bound To special values
ENUM_SUNW_SYMINFO_BOUNDTO = dict(
SYMINFO_BT_SELF=0xffff,
R_AARCH64_TLS_DTPMOD32=1032,
R_AARCH64_TLS_TPREL32=1033,
)
+
+ENUM_ATTR_TAG_ARM = dict(
+ TAG_FILE=1,
+ TAG_SECTION=2,
+ TAG_SYMBOL=3,
+ TAG_CPU_RAW_NAME=4,
+ TAG_CPU_NAME=5,
+ TAG_CPU_ARCH=6,
+ TAG_CPU_ARCH_PROFILE=7,
+ TAG_ARM_ISA_USE=8,
+ TAG_THUMB_ISA_USE=9,
+ TAG_FP_ARCH=10,
+ TAG_WMMX_ARCH=11,
+ TAG_ADVANCED_SIMD_ARCH=12,
+ TAG_PCS_CONFIG=13,
+ TAG_ABI_PCS_R9_USE=14,
+ TAG_ABI_PCS_RW_DATA=15,
+ TAG_ABI_PCS_RO_DATA=16,
+ TAG_ABI_PCS_GOT_USE=17,
+ TAG_ABI_PCS_WCHAR_T=18,
+ TAG_ABI_FP_ROUNDING=19,
+ TAG_ABI_FP_DENORMAL=20,
+ TAG_ABI_FP_EXCEPTIONS=21,
+ TAG_ABI_FP_USER_EXCEPTIONS=22,
+ TAG_ABI_FP_NUMBER_MODEL=23,
+ TAG_ABI_ALIGN_NEEDED=24,
+ TAG_ABI_ALIGN_PRESERVED=25,
+ TAG_ABI_ENUM_SIZE=26,
+ TAG_ABI_HARDFP_USE=27,
+ TAG_ABI_VFP_ARGS=28,
+ TAG_ABI_WMMX_ARGS=29,
+ TAG_ABI_OPTIMIZATION_GOALS=30,
+ TAG_ABI_FP_OPTIMIZATION_GOALS=31,
+ TAG_COMPATIBILITY=32,
+ TAG_CPU_UNALIGNED_ACCESS=34,
+ TAG_FP_HP_EXTENSION=36,
+ TAG_ABI_FP_16BIT_FORMAT=38,
+ TAG_MPEXTENSION_USE=42,
+ TAG_DIV_USE=44,
+ TAG_NODEFAULTS=64,
+ TAG_ALSO_COMPATIBLE_WITH=65,
+ TAG_T2EE_USE=66,
+ TAG_CONFORMANCE=67,
+ TAG_VIRTUALIZATION_USE=68,
+ TAG_MPEXTENSION_USE_OLD=70,
+)
from collections import defaultdict
from .constants import SH_FLAGS
from .notes import iter_notes
+
import zlib
"""
return iter_notes(self.elffile, self['sh_offset'], self['sh_size'])
+
class StabSection(Section):
""" ELF stab section.
"""
self.stream.seek(offset)
yield stabs
+
+class ARMAttribute(object):
+ """ ARM attribute object - representing a build attribute of ARM ELF files.
+ """
+ def __init__(self, structs, stream):
+ self._tag = struct_parse(structs.Elf_Attribute_Tag, stream)
+ self.extra = None
+
+ if self.tag in ('TAG_FILE', 'TAG_SECTION', 'TAG_SYMBOL'):
+ self.value = struct_parse(structs.Elf_word('value'), stream)
+
+ if self.tag != 'TAG_FILE':
+ self.extra = []
+ s_number = struct_parse(self.structs.Elf_uleb128('s_number'),
+ self.stream
+ )
+
+ while s_number != 0:
+ self.extra.append(s_number)
+ s_number = struct_parse(self.structs.Elf_uleb128('s_number'),
+ self.stream
+ )
+
+ elif self.tag in ('TAG_CPU_RAW_NAME', 'TAG_CPU_NAME', 'TAG_CONFORMANCE'):
+ self.value = struct_parse(structs.Elf_ntbs('value',
+ encoding='ascii'),
+ stream)
+
+ elif self.tag == 'TAG_COMPATIBILITY':
+ self.value = struct_parse(structs.Elf_uleb128('value'), stream)
+ self.extra = struct_parse(structs.Elf_ntbs('vendor_name',
+ encoding='ascii'),
+ stream)
+
+ elif self.tag == 'TAG_ALSO_COMPATIBLE_WITH':
+ self.value = ARMAttribute(structs, stream)
+
+ if type(self.value.value) is not str:
+ nul = struct_parse(structs.Elf_byte('nul'), stream)
+ elf_assert(null_byte == 0,
+ "Invalid terminating byte %r, expecting NUL." % nul)
+
+ else:
+ self.value = struct_parse(structs.Elf_uleb128('value'), stream)
+
+ @property
+ def tag(self):
+ return self._tag['tag']
+
+ def __repr__(self):
+ s = '<ARMAttribute (%s): %r>' % (self.tag, self.value)
+ s += ' %s' % self.extra if self.extra is not None else ''
+ return s
+
+
+class ARMAttributesSubsubsection(object):
+ """ Subsubsection of an ELF .ARM.attributes section's subsection.
+ """
+ def __init__(self, stream, structs, offset):
+ self.stream = stream
+ self.offset = offset
+ self.structs = structs
+
+ self.header = ARMAttribute(self.structs, self.stream)
+
+ self.attr_start = self.stream.tell()
+
+ def iter_attributes(self, tag=None):
+ """ Yield all attributes (limit to |tag| if specified).
+ """
+ for attribute in self._make_attributes():
+ if tag is None or attribute.tag == tag:
+ yield attribute
+
+ @property
+ def num_attributes(self):
+ """ Number of attributes in the subsubsection.
+ """
+ return sum(1 for _ in self.iter_attributes()) + 1
+
+ @property
+ def attributes(self):
+ """ List of all attributes in the subsubsection.
+ """
+ return [self.header] + list(self.iter_attributes())
+
+ def _make_attributes(self):
+ """ Create all attributes for this subsubsection except the first one
+ which is the header.
+ """
+ end = self.offset + self.header.value
+
+ self.stream.seek(self.attr_start)
+
+ while self.stream.tell() != end:
+ yield ARMAttribute(self.structs, self.stream)
+
+ def __repr__(self):
+ s = "<ARMAttributesSubsubsection (%s): %d bytes>"
+ return s % (self.header.tag[4:], self.header.value)
+
+
+class ARMAttributesSubsection(object):
+ """ Subsection of an ELF .ARM.attributes section.
+ """
+ def __init__(self, stream, structs, offset):
+ self.stream = stream
+ self.offset = offset
+ self.structs = structs
+
+ self.header = struct_parse(self.structs.Elf_Attr_Subsection_Header,
+ self.stream,
+ self.offset
+ )
+
+ self.subsubsec_start = self.stream.tell()
+
+ def iter_subsubsections(self, scope=None):
+ """ Yield all subsubsections (limit to |scope| if specified).
+ """
+ for subsubsec in self._make_subsubsections():
+ if scope is None or subsubsec.header.tag == scope:
+ yield subsubsec
+
+ @property
+ def num_subsubsections(self):
+ """ Number of subsubsections in the subsection.
+ """
+ return sum(1 for _ in self.iter_subsubsections())
+
+ @property
+ def subsubsections(self):
+ """ List of all subsubsections in the subsection.
+ """
+ return list(self.iter_subsubsections())
+
+ def _make_subsubsections(self):
+ """ Create all subsubsections for this subsection.
+ """
+ end = self.offset + self['length']
+
+ self.stream.seek(self.subsubsec_start)
+
+ while self.stream.tell() != end:
+ subsubsec = ARMAttributesSubsubsection(self.stream,
+ self.structs,
+ self.stream.tell())
+ self.stream.seek(self.subsubsec_start + subsubsec.header.value)
+ yield subsubsec
+
+ def __getitem__(self, name):
+ """ Implement dict-like access to header entries.
+ """
+ return self.header[name]
+
+ def __repr__(self):
+ s = "<ARMAttributesSubsection (%s): %d bytes>"
+ return s % (self.header['vendor_name'], self.header['length'])
+
+
+class ARMAttributesSection(Section):
+ """ ELF .ARM.attributes section.
+ """
+ def __init__(self, header, name, elffile):
+ super(ARMAttributesSection, self).__init__(header, name, elffile)
+
+ fv = struct_parse(self.structs.Elf_byte('format_version'),
+ self.stream,
+ self['sh_offset']
+ )
+
+ elf_assert(chr(fv) == 'A',
+ "Unknown attributes version %s, expecting 'A'." % chr(fv)
+ )
+
+ self.subsec_start = self.stream.tell()
+
+ def iter_subsections(self, vendor_name=None):
+ """ Yield all subsections (limit to |vendor_name| if specified).
+ """
+ for subsec in self._make_subsections():
+ if vendor_name is None or subsec['vendor_name'] == vendor_name:
+ yield subsec
+
+ @property
+ def num_subsections(self):
+ """ Number of subsections in the section.
+ """
+ return sum(1 for _ in self.iter_subsections())
+
+ @property
+ def subsections(self):
+ """ List of all subsections in the section.
+ """
+ return list(self.iter_subsections())
+
+ def _make_subsections(self):
+ """ Create all subsections for this section.
+ """
+ end = self['sh_offset'] + self.data_size
+
+ self.stream.seek(self.subsec_start)
+
+ while self.stream.tell() != end:
+ subsec = ARMAttributesSubsection(self.stream,
+ self.structs,
+ self.stream.tell())
+ self.stream.seek(self.subsec_start + subsec['length'])
+ yield subsec
UBInt8, UBInt16, UBInt32, UBInt64,
ULInt8, ULInt16, ULInt32, ULInt64,
SBInt32, SLInt32, SBInt64, SLInt64,
- Struct, Array, Enum, Padding, BitStruct, BitField, Value, String, CString,
+ Struct, Array, Enum, Padding, BitStruct, BitField, Value, String, CString
)
-
+from ..common.construct_utils import ULEB128
from .enums import *
self.Elf_xword = UBInt32 if self.elfclass == 32 else UBInt64
self.Elf_sxword = SBInt32 if self.elfclass == 32 else SBInt64
self._create_ehdr()
+ self._create_leb128()
+ self._create_ntbs()
def create_advanced_structs(self, elftype=None):
""" Create all ELF structs except the ehdr. They may possibly depend
self._create_gnu_abi()
self._create_note(elftype)
self._create_stabs()
+ self._create_arm_attributes()
#-------------------------------- PRIVATE --------------------------------#
self.Elf_half('e_shstrndx'),
)
+ def _create_leb128(self):
+ self.Elf_uleb128 = ULEB128
+
+ def _create_ntbs(self):
+ self.Elf_ntbs = CString
+
def _create_phdr(self):
if self.elfclass == 32:
self.Elf_Phdr = Struct('Elf_Phdr',
self.Elf_half('n_desc'),
self.Elf_word('n_value'),
)
+
+ def _create_arm_attributes(self):
+ # Structure of a build attributes subsection header. A subsection is
+ # either public to all tools that process the ELF file or private to
+ # the vendor's tools.
+ self.Elf_Attr_Subsection_Header = Struct('Elf_Attr_Subsection',
+ self.Elf_word('length'),
+ self.Elf_ntbs('vendor_name',
+ encoding='ascii')
+ )
+
+ # Structure of a build attribute tag.
+ self.Elf_Attribute_Tag = Struct('Elf_Attribute_Tag',
+ Enum(self.Elf_uleb128('tag'),
+ **ENUM_ATTR_TAG_ARM)
+ )
describe_sh_type, describe_sh_flags,
describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,
- describe_ver_flags, describe_note
+ describe_ver_flags, describe_note, describe_attr_tag_arm
)
from elftools.elf.constants import E_FLAGS
from elftools.dwarf.dwarfinfo import DWARFInfo
offset += verneed['vn_next']
+ def display_arch_specific(self):
+ """ Display the architecture-specific info contained in the file.
+ """
+ if self.elffile['e_machine'] == 'EM_ARM':
+ self._display_arch_specific_arm()
+
def display_hex_dump(self, section_spec):
""" Display a hex dump of a section. section_spec is either a section
number or a name.
self._dwarfinfo.debug_frame_sec,
self._dwarfinfo.CFI_entries())
+ def _display_arch_specific_arm(self):
+ """ Display the ARM architecture-specific info contained in the file.
+ """
+ attr_sec = self.elffile.get_section_by_name('.ARM.attributes')
+
+ for s in attr_sec.iter_subsections():
+ self._emitline("Attribute Section: %s" % s.header['vendor_name'])
+ for ss in s.iter_subsubsections():
+ h_val = "" if ss.header.extra is None else " ".join("%d" % x for x in ss.header.extra)
+ self._emitline(describe_attr_tag_arm(ss.header.tag, h_val, None))
+
+ for attr in ss.iter_attributes():
+ self._emit(' ')
+ self._emitline(describe_attr_tag_arm(attr.tag,
+ attr.value,
+ attr.extra))
+
def _emit(self, s=''):
""" Emit an object to output
"""
optparser.add_option('-V', '--version-info',
action='store_true', dest='show_version_info',
help='Display the version sections (if present)')
+ optparser.add_option('-A', '--arch-specific',
+ action='store_true', dest='show_arch_specific',
+ help='Display the architecture-specific information (if present)')
optparser.add_option('--debug-dump',
action='store', dest='debug_dump_what', metavar='<what>',
help=(
readelf.display_relocations()
if options.show_version_info:
readelf.display_version_info()
+ if options.show_arch_specific:
+ readelf.display_arch_specific()
if options.show_hex_dump:
readelf.display_hex_dump(options.show_hex_dump)
if options.show_string_dump:
self.assertEqual(elf.num_sections(), 14)
self.assertEqual(elf.num_segments(), 2)
+ def test_build_attributes(self):
+ with open(os.path.join('test', 'testfiles_for_unittests',
+ 'simple_gcc.elf.arm'), 'rb') as f:
+ elf = ELFFile(f)
+
+ sec = elf.get_section_by_name('.ARM.attributes')
+ self.assertEqual(sec['sh_type'], 'SHT_ARM_ATTRIBUTES')
+ self.assertEqual(sec.num_subsections, 1)
+
+ subsec = sec.subsections[0]
+ self.assertEqual(subsec.header['vendor_name'], 'aeabi')
+ self.assertEqual(subsec.num_subsubsections, 1)
+
+ subsubsec = subsec.subsubsections[0]
+ self.assertEqual(subsubsec.header.tag, 'TAG_FILE')
+
+ for i in subsubsec.iter_attributes('TAG_CPU_NAME'):
+ self.assertEqual(i.value, 'ARM7TDMI-S')
+
+ for i in subsubsec.iter_attributes('TAG_CPU_ARCH'):
+ self.assertEqual(i.value, 2)
+
def test_DWARF_indirect_forms(self):
# This file uses a lot of DW_FORM_indirect, and is also an ARM ELF
# with non-trivial DWARF info.