建立 MAG160C 逆向工程交接仓库
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
EHABI_INDEX_ENTRY_SIZE: int = 8
|
||||
@@ -0,0 +1,289 @@
|
||||
# -------------------------------------------------------------------------------
|
||||
# elftools: ehabi/decoder.py
|
||||
#
|
||||
# Decode ARM exception handler bytecode.
|
||||
#
|
||||
# LeadroyaL (leadroyal@qq.com)
|
||||
# This code is in the public domain
|
||||
# -------------------------------------------------------------------------------
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable, NamedTuple
|
||||
|
||||
|
||||
class EHABIBytecodeDecoder:
|
||||
""" Decoder of a sequence of ARM exception handler abi bytecode.
|
||||
|
||||
Reference:
|
||||
https://github.com/llvm/llvm-project/blob/master/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
|
||||
https://developer.arm.com/documentation/ihi0038/b/
|
||||
|
||||
Accessible attributes:
|
||||
|
||||
mnemonic_array:
|
||||
MnemonicItem array.
|
||||
|
||||
Parameters:
|
||||
|
||||
bytecode_array:
|
||||
Integer array, raw data of bytecode.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, bytecode_array: list[int]) -> None:
|
||||
self._bytecode_array = bytecode_array
|
||||
self._index: int = 0
|
||||
self.mnemonic_array: list[MnemonicItem] | None = None
|
||||
self._decode()
|
||||
|
||||
def _decode(self) -> None:
|
||||
""" Decode bytecode array, put result into mnemonic_array.
|
||||
"""
|
||||
self._index = 0
|
||||
self.mnemonic_array = []
|
||||
while self._index < len(self._bytecode_array):
|
||||
for mask, value, handler in self.ring:
|
||||
if (self._bytecode_array[self._index] & mask) == value:
|
||||
start_idx = self._index
|
||||
mnemonic = handler(self)
|
||||
end_idx = self._index
|
||||
self.mnemonic_array.append(
|
||||
MnemonicItem(self._bytecode_array[start_idx: end_idx], mnemonic))
|
||||
break
|
||||
|
||||
def _decode_00xxxxxx(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode,
|
||||
# ((Opcode & 0x3f) << 2) + 4);
|
||||
opcode = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
return 'vsp = vsp + %u' % (((opcode & 0x3f) << 2) + 4)
|
||||
|
||||
def _decode_01xxxxxx(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode,
|
||||
# ((Opcode & 0x3f) << 2) + 4);
|
||||
opcode = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
return 'vsp = vsp - %u' % (((opcode & 0x3f) << 2) + 4)
|
||||
|
||||
gpr_register_names = ("r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc")
|
||||
|
||||
def _calculate_range(self, start: int, count: int) -> int:
|
||||
return ((1 << (count + 1)) - 1) << start
|
||||
|
||||
def _printGPR(self, gpr_mask: int) -> str:
|
||||
hits = [self.gpr_register_names[i] for i in range(32) if gpr_mask & (1 << i) != 0]
|
||||
return '{%s}' % ', '.join(hits)
|
||||
|
||||
def _print_registers(self, vfp_mask: int, prefix: str) -> str:
|
||||
hits = [prefix + str(i) for i in range(32) if vfp_mask & (1 << i) != 0]
|
||||
return '{%s}' % ', '.join(hits)
|
||||
|
||||
def _decode_1000iiii_iiiiiiii(self) -> str:
|
||||
op0 = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
op1 = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
# uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);
|
||||
# SW.startLine()
|
||||
# << format("0x%02X 0x%02X ; %s",
|
||||
# Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");
|
||||
# if (GPRMask)
|
||||
# PrintGPR(GPRMask);
|
||||
gpr_mask = (op1 << 4) | ((op0 & 0x0f) << 12)
|
||||
if gpr_mask == 0:
|
||||
return 'refuse to unwind'
|
||||
else:
|
||||
return 'pop %s' % self._printGPR(gpr_mask)
|
||||
|
||||
def _decode_10011101(self) -> str:
|
||||
self._index += 1
|
||||
return 'reserved (ARM MOVrr)'
|
||||
|
||||
def _decode_10011111(self) -> str:
|
||||
self._index += 1
|
||||
return 'reserved (WiMMX MOVrr)'
|
||||
|
||||
def _decode_1001nnnn(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f));
|
||||
opcode = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
return 'vsp = r%u' % (opcode & 0x0f)
|
||||
|
||||
def _decode_10100nnn(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; pop ", Opcode);
|
||||
# PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));
|
||||
opcode = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
return 'pop %s' % self._printGPR(self._calculate_range(4, opcode & 0x07))
|
||||
|
||||
def _decode_10101nnn(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; pop ", Opcode);
|
||||
# PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));
|
||||
opcode = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
return 'pop %s' % self._printGPR(self._calculate_range(4, opcode & 0x07) | (1 << 14))
|
||||
|
||||
def _decode_10110000(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; finish\n", Opcode);
|
||||
self._index += 1
|
||||
return 'finish'
|
||||
|
||||
def _decode_10110001_0000iiii(self) -> str:
|
||||
# SW.startLine()
|
||||
# << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
|
||||
# ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
|
||||
# if (((Opcode1 & 0xf0) == 0x00) && Opcode1)
|
||||
# PrintGPR((Opcode1 & 0x0f));
|
||||
self._index += 1 # skip constant byte
|
||||
op1 = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
if (op1 & 0xf0) != 0 or op1 == 0x00:
|
||||
return 'spare'
|
||||
else:
|
||||
return 'pop %s' % self._printGPR(op1 & 0x0f)
|
||||
|
||||
def _decode_10110010_uleb128(self) -> str:
|
||||
# SmallVector<uint8_t, 4> ULEB;
|
||||
# do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);
|
||||
# uint64_t Value = 0;
|
||||
# for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
|
||||
# Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));
|
||||
# OS << format("; vsp = vsp + %" PRIu64 "\n", 0x204 + (Value << 2));
|
||||
self._index += 1 # skip constant byte
|
||||
uleb_buffer = [self._bytecode_array[self._index]]
|
||||
self._index += 1
|
||||
while self._bytecode_array[self._index] & 0x80 == 0:
|
||||
uleb_buffer.append(self._bytecode_array[self._index])
|
||||
self._index += 1
|
||||
value = 0
|
||||
for b in reversed(uleb_buffer):
|
||||
value = (value << 7) + (b & 0x7F)
|
||||
return 'vsp = vsp + %u' % (0x204 + (value << 2))
|
||||
|
||||
def _decode_10110011_sssscccc(self) -> str:
|
||||
# these two decoders are equal
|
||||
return self._decode_11001001_sssscccc()
|
||||
|
||||
def _decode_101101nn(self) -> str:
|
||||
return self._spare()
|
||||
|
||||
def _decode_10111nnn(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; pop ", Opcode);
|
||||
# PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
|
||||
opcode = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
return 'pop %s' % self._print_registers(self._calculate_range(8, opcode & 0x07), "d")
|
||||
|
||||
def _decode_11000110_sssscccc(self) -> str:
|
||||
# SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
|
||||
# uint8_t Start = ((Opcode1 & 0xf0) >> 4);
|
||||
# uint8_t Count = ((Opcode1 & 0x0f) >> 0);
|
||||
# PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");
|
||||
self._index += 1 # skip constant byte
|
||||
op1 = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
start = ((op1 & 0xf0) >> 4)
|
||||
count = ((op1 & 0x0f) >> 0)
|
||||
return 'pop %s' % self._print_registers(self._calculate_range(start, count), "wR")
|
||||
|
||||
def _decode_11000111_0000iiii(self) -> str:
|
||||
# SW.startLine()
|
||||
# << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
|
||||
# ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
|
||||
# if ((Opcode1 & 0xf0) == 0x00 && Opcode1)
|
||||
# PrintRegisters(Opcode1 & 0x0f, "wCGR");
|
||||
self._index += 1 # skip constant byte
|
||||
op1 = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
if (op1 & 0xf0) != 0 or op1 == 0x00:
|
||||
return 'spare'
|
||||
else:
|
||||
return 'pop %s' % self._print_registers(op1 & 0x0f, "wCGR")
|
||||
|
||||
def _decode_11001000_sssscccc(self) -> str:
|
||||
# SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
|
||||
# uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);
|
||||
# uint8_t Count = ((Opcode1 & 0x0f) >> 0);
|
||||
# PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
|
||||
self._index += 1 # skip constant byte
|
||||
op1 = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
start = 16 + ((op1 & 0xf0) >> 4)
|
||||
count = ((op1 & 0x0f) >> 0)
|
||||
return 'pop %s' % self._print_registers(self._calculate_range(start, count), "d")
|
||||
|
||||
def _decode_11001001_sssscccc(self) -> str:
|
||||
# SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
|
||||
# uint8_t Start = ((Opcode1 & 0xf0) >> 4);
|
||||
# uint8_t Count = ((Opcode1 & 0x0f) >> 0);
|
||||
# PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
|
||||
self._index += 1 # skip constant byte
|
||||
op1 = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
start = ((op1 & 0xf0) >> 4)
|
||||
count = ((op1 & 0x0f) >> 0)
|
||||
return 'pop %s' % self._print_registers(self._calculate_range(start, count), "d")
|
||||
|
||||
def _decode_11001yyy(self) -> str:
|
||||
return self._spare()
|
||||
|
||||
def _decode_11000nnn(self) -> str:
|
||||
# SW.startLine() << format("0x%02X ; pop ", Opcode);
|
||||
# PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");
|
||||
opcode = self._bytecode_array[self._index]
|
||||
self._index += 1
|
||||
return 'pop %s' % self._print_registers(self._calculate_range(10, opcode & 0x07), "wR")
|
||||
|
||||
def _decode_11010nnn(self) -> str:
|
||||
# these two decoders are equal
|
||||
return self._decode_10111nnn()
|
||||
|
||||
def _decode_11xxxyyy(self) -> str:
|
||||
return self._spare()
|
||||
|
||||
def _spare(self) -> str:
|
||||
self._index += 1
|
||||
return 'spare'
|
||||
|
||||
class _DECODE_RECIPE_TYPE(NamedTuple):
|
||||
mask: int
|
||||
value: int
|
||||
handler: Callable[[EHABIBytecodeDecoder], str]
|
||||
|
||||
ring = (
|
||||
_DECODE_RECIPE_TYPE(mask=0xc0, value=0x00, handler=_decode_00xxxxxx),
|
||||
_DECODE_RECIPE_TYPE(mask=0xc0, value=0x40, handler=_decode_01xxxxxx),
|
||||
_DECODE_RECIPE_TYPE(mask=0xf0, value=0x80, handler=_decode_1000iiii_iiiiiiii),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0x9d, handler=_decode_10011101),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0x9f, handler=_decode_10011111),
|
||||
_DECODE_RECIPE_TYPE(mask=0xf0, value=0x90, handler=_decode_1001nnnn),
|
||||
_DECODE_RECIPE_TYPE(mask=0xf8, value=0xa0, handler=_decode_10100nnn),
|
||||
_DECODE_RECIPE_TYPE(mask=0xf8, value=0xa8, handler=_decode_10101nnn),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xb0, handler=_decode_10110000),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xb1, handler=_decode_10110001_0000iiii),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xb2, handler=_decode_10110010_uleb128),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xb3, handler=_decode_10110011_sssscccc),
|
||||
_DECODE_RECIPE_TYPE(mask=0xfc, value=0xb4, handler=_decode_101101nn),
|
||||
_DECODE_RECIPE_TYPE(mask=0xf8, value=0xb8, handler=_decode_10111nnn),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xc6, handler=_decode_11000110_sssscccc),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xc7, handler=_decode_11000111_0000iiii),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xc8, handler=_decode_11001000_sssscccc),
|
||||
_DECODE_RECIPE_TYPE(mask=0xff, value=0xc9, handler=_decode_11001001_sssscccc),
|
||||
_DECODE_RECIPE_TYPE(mask=0xc8, value=0xc8, handler=_decode_11001yyy),
|
||||
_DECODE_RECIPE_TYPE(mask=0xf8, value=0xc0, handler=_decode_11000nnn),
|
||||
_DECODE_RECIPE_TYPE(mask=0xf8, value=0xd0, handler=_decode_11010nnn),
|
||||
_DECODE_RECIPE_TYPE(mask=0xc0, value=0xc0, handler=_decode_11xxxyyy),
|
||||
)
|
||||
|
||||
|
||||
class MnemonicItem:
|
||||
""" Single mnemonic item.
|
||||
"""
|
||||
|
||||
def __init__(self, bytecode: list[int], mnemonic: str) -> None:
|
||||
self.bytecode = bytecode
|
||||
self.mnemonic = mnemonic
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return '%s ; %s' % (' '.join(['0x%02x' % x for x in self.bytecode]), self.mnemonic)
|
||||
@@ -0,0 +1,232 @@
|
||||
# -------------------------------------------------------------------------------
|
||||
# elftools: ehabi/ehabiinfo.py
|
||||
#
|
||||
# Decoder for ARM exception handler bytecode.
|
||||
#
|
||||
# LeadroyaL (leadroyal@qq.com)
|
||||
# This code is in the public domain
|
||||
# -------------------------------------------------------------------------------
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import cached_property
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..common.utils import struct_parse
|
||||
|
||||
from .decoder import EHABIBytecodeDecoder
|
||||
from .constants import EHABI_INDEX_ENTRY_SIZE
|
||||
from .structs import EHABIStructs
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..elf.sections import Section
|
||||
from .decoder import MnemonicItem
|
||||
|
||||
|
||||
class EHABIInfo:
|
||||
""" ARM exception handler abi information class.
|
||||
|
||||
Parameters:
|
||||
|
||||
arm_idx_section:
|
||||
elf.sections.Section object, section which type is SHT_ARM_EXIDX.
|
||||
|
||||
little_endian:
|
||||
bool, endianness of elf file.
|
||||
"""
|
||||
|
||||
def __init__(self, arm_idx_section: Section, little_endian: bool) -> None:
|
||||
self._arm_idx_section = arm_idx_section
|
||||
self._struct = EHABIStructs(little_endian)
|
||||
|
||||
def section_name(self) -> str:
|
||||
return self._arm_idx_section.name
|
||||
|
||||
def section_offset(self) -> int:
|
||||
return self._arm_idx_section['sh_offset']
|
||||
|
||||
def num_entry(self) -> int:
|
||||
""" Number of exception handler entry in the section.
|
||||
"""
|
||||
return self._num_entry
|
||||
|
||||
@cached_property
|
||||
def _num_entry(self) -> int:
|
||||
return self._arm_idx_section['sh_size'] // EHABI_INDEX_ENTRY_SIZE
|
||||
|
||||
def get_entry(self, n: int) -> EHABIEntry:
|
||||
""" Get the exception handler entry at index #n. (EHABIEntry object or a subclass)
|
||||
"""
|
||||
if n >= self.num_entry():
|
||||
raise IndexError('Invalid entry %d/%d' % (n, self.num_entry()))
|
||||
eh_index_entry_offset = self.section_offset() + n * EHABI_INDEX_ENTRY_SIZE
|
||||
eh_index_data = struct_parse(self._struct.EH_index_struct, self._arm_idx_section.stream, eh_index_entry_offset)
|
||||
word0, word1 = eh_index_data['word0'], eh_index_data['word1']
|
||||
|
||||
if word0 & 0x80000000 != 0:
|
||||
return CorruptEHABIEntry('Corrupt ARM exception handler table entry: %x' % n)
|
||||
|
||||
function_offset = arm_expand_prel31(word0, self.section_offset() + n * EHABI_INDEX_ENTRY_SIZE)
|
||||
|
||||
if word1 == 1:
|
||||
# 0x1 means cannot unwind
|
||||
return CannotUnwindEHABIEntry(function_offset)
|
||||
elif word1 & 0x80000000 == 0:
|
||||
# highest bit is zero, point to .ARM.extab data
|
||||
eh_table_offset = arm_expand_prel31(word1, self.section_offset() + n * EHABI_INDEX_ENTRY_SIZE + 4)
|
||||
eh_index_data = struct_parse(self._struct.EH_table_struct, self._arm_idx_section.stream, eh_table_offset)
|
||||
word0 = eh_index_data['word0']
|
||||
if word0 & 0x80000000 == 0:
|
||||
# highest bit is one, generic model
|
||||
return GenericEHABIEntry(function_offset, arm_expand_prel31(word0, eh_table_offset))
|
||||
else:
|
||||
# highest bit is one, arm compact model
|
||||
# highest half must be 0b1000 for compact model
|
||||
if word0 & 0x70000000 != 0:
|
||||
return CorruptEHABIEntry('Corrupt ARM compact model table entry: %x' % n)
|
||||
per_index = (word0 >> 24) & 0x7f
|
||||
if per_index == 0:
|
||||
# arm compact model 0
|
||||
opcode = [(word0 & 0xFF0000) >> 16, (word0 & 0xFF00) >> 8, word0 & 0xFF]
|
||||
return EHABIEntry(function_offset, per_index, opcode)
|
||||
elif per_index == 1 or per_index == 2:
|
||||
# arm compact model 1/2
|
||||
more_word = (word0 >> 16) & 0xff
|
||||
opcode = [(word0 >> 8) & 0xff, (word0 >> 0) & 0xff]
|
||||
self._arm_idx_section.stream.seek(eh_table_offset + 4)
|
||||
for i in range(more_word):
|
||||
r = struct_parse(self._struct.EH_table_struct, self._arm_idx_section.stream)['word0']
|
||||
opcode.append((r >> 24) & 0xFF)
|
||||
opcode.append((r >> 16) & 0xFF)
|
||||
opcode.append((r >> 8) & 0xFF)
|
||||
opcode.append((r >> 0) & 0xFF)
|
||||
return EHABIEntry(function_offset, per_index, opcode, eh_table_offset=eh_table_offset)
|
||||
else:
|
||||
return CorruptEHABIEntry('Unknown ARM compact model %d at table entry: %x' % (per_index, n))
|
||||
else:
|
||||
# highest bit is one, compact model must be 0
|
||||
if word1 & 0x7f000000 != 0:
|
||||
return CorruptEHABIEntry('Corrupt ARM compact model table entry: %x' % n)
|
||||
opcode = [(word1 & 0xFF0000) >> 16, (word1 & 0xFF00) >> 8, word1 & 0xFF]
|
||||
return EHABIEntry(function_offset, 0, opcode)
|
||||
|
||||
|
||||
class EHABIEntry:
|
||||
""" Exception handler abi entry.
|
||||
|
||||
Accessible attributes:
|
||||
|
||||
function_offset:
|
||||
Integer.
|
||||
None if corrupt. (Reference: CorruptEHABIEntry)
|
||||
|
||||
personality:
|
||||
Integer.
|
||||
None if corrupt or unwindable. (Reference: CorruptEHABIEntry, CannotUnwindEHABIEntry)
|
||||
0/1/2 for ARM personality compact format.
|
||||
Others for generic personality.
|
||||
|
||||
bytecode_array:
|
||||
Integer array.
|
||||
None if corrupt or unwindable or generic personality.
|
||||
(Reference: CorruptEHABIEntry, CannotUnwindEHABIEntry, GenericEHABIEntry)
|
||||
|
||||
eh_table_offset:
|
||||
Integer.
|
||||
Only entries who point to .ARM.extab contains this field, otherwise return None.
|
||||
|
||||
unwindable:
|
||||
bool. Whether this function is unwindable.
|
||||
|
||||
corrupt:
|
||||
bool. Whether this entry is corrupt.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
function_offset: int | None,
|
||||
personality: int | None,
|
||||
bytecode_array: list[int] | None,
|
||||
eh_table_offset: int | None = None,
|
||||
unwindable: bool = True,
|
||||
corrupt: bool = False,
|
||||
) -> None:
|
||||
self.function_offset = function_offset
|
||||
self.personality = personality
|
||||
self.bytecode_array = bytecode_array
|
||||
self.eh_table_offset = eh_table_offset
|
||||
self.unwindable = unwindable
|
||||
self.corrupt = corrupt
|
||||
|
||||
def mnmemonic_array(self) -> list[MnemonicItem] | None:
|
||||
if self.bytecode_array:
|
||||
return EHABIBytecodeDecoder(self.bytecode_array).mnemonic_array
|
||||
else:
|
||||
return None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
fo = self.function_offset
|
||||
to = self.eh_table_offset
|
||||
return (
|
||||
"<EHABIEntry"
|
||||
f" function_offset={'' if fo is None else '{fo:#x}'}"
|
||||
f", personaality={self.personality}"
|
||||
f"{', eh_table_offset={to:#x}' if to else ''}"
|
||||
f", bytecode={self.bytecode_array}"
|
||||
">"
|
||||
)
|
||||
|
||||
|
||||
class CorruptEHABIEntry(EHABIEntry):
|
||||
""" This entry is corrupt. Attribute #corrupt will be True.
|
||||
"""
|
||||
|
||||
def __init__(self, reason: str) -> None:
|
||||
super().__init__(function_offset=None, personality=None, bytecode_array=None,
|
||||
corrupt=True)
|
||||
self.reason = reason
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<CorruptEHABIEntry reason=%s>" % self.reason
|
||||
|
||||
|
||||
class CannotUnwindEHABIEntry(EHABIEntry):
|
||||
""" This function cannot be unwind. Attribute #unwindable will be False.
|
||||
"""
|
||||
|
||||
if TYPE_CHECKING:
|
||||
function_offset: int # instead of `int|None` to save `is None` checks everywhere
|
||||
|
||||
def __init__(self, function_offset: int) -> None:
|
||||
super().__init__(function_offset, personality=None, bytecode_array=None,
|
||||
unwindable=False)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<CannotUnwindEHABIEntry function_offset=0x%x>" % self.function_offset
|
||||
|
||||
|
||||
class GenericEHABIEntry(EHABIEntry):
|
||||
""" This entry is generic model rather than ARM compact model.Attribute #bytecode_array will be None.
|
||||
"""
|
||||
|
||||
if TYPE_CHECKING:
|
||||
function_offset: int # instead of `int|None` to save `is None` checks everywhere
|
||||
personality: int
|
||||
|
||||
def __init__(self, function_offset: int, personality: int) -> None:
|
||||
super().__init__(function_offset, personality, bytecode_array=None)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<GenericEHABIEntry function_offset=0x%x, personality=0x%x>" % (self.function_offset, self.personality)
|
||||
|
||||
|
||||
def arm_expand_prel31(address: int, place: int) -> int:
|
||||
"""
|
||||
address: uint32
|
||||
place: uint32
|
||||
return: uint64
|
||||
"""
|
||||
location = address & 0x7fffffff
|
||||
if location & 0x04000000:
|
||||
location |= 0xffffffff80000000
|
||||
return location + place & 0xffffffffffffffff
|
||||
@@ -0,0 +1,47 @@
|
||||
# -------------------------------------------------------------------------------
|
||||
# elftools: ehabi/structs.py
|
||||
#
|
||||
# Encapsulation of Construct structs for parsing an EHABI, adjusted for
|
||||
# correct endianness and word-size.
|
||||
#
|
||||
# LeadroyaL (leadroyal@qq.com)
|
||||
# This code is in the public domain
|
||||
# -------------------------------------------------------------------------------
|
||||
|
||||
from ..construct import UBInt32, ULInt32, Struct
|
||||
|
||||
|
||||
class EHABIStructs:
|
||||
""" Accessible attributes:
|
||||
|
||||
EH_index_struct:
|
||||
Struct of item in section .ARM.exidx.
|
||||
|
||||
EH_table_struct:
|
||||
Struct of item in section .ARM.extab.
|
||||
"""
|
||||
|
||||
def __init__(self, little_endian: bool) -> None:
|
||||
self._little_endian = little_endian
|
||||
self._create_structs()
|
||||
|
||||
def _create_structs(self) -> None:
|
||||
if self._little_endian:
|
||||
self.EHABI_uint32 = ULInt32
|
||||
else:
|
||||
self.EHABI_uint32 = UBInt32
|
||||
self._create_exception_handler_index()
|
||||
self._create_exception_handler_table()
|
||||
|
||||
def _create_exception_handler_index(self) -> None:
|
||||
self.EH_index_struct = Struct(
|
||||
'EH_index',
|
||||
self.EHABI_uint32('word0'),
|
||||
self.EHABI_uint32('word1')
|
||||
)
|
||||
|
||||
def _create_exception_handler_table(self) -> None:
|
||||
self.EH_table_struct = Struct(
|
||||
'EH_table',
|
||||
self.EHABI_uint32('word0'),
|
||||
)
|
||||
Reference in New Issue
Block a user