diff --git a/tests/testAArch64BtiTargetType.py b/tests/testAArch64BtiTargetType.py new file mode 100644 index 00000000..e74ded98 --- /dev/null +++ b/tests/testAArch64BtiTargetType.py @@ -0,0 +1,99 @@ +#!/usr/bin/python +"""`bti j` marks a jump target, not a callable entry. + +`USE_AARCH64_BTI_TARGET_TYPE` refuses a `bti j` word as a function start: the hint says an +indirect *branch* may land there, which a compiler emits for jump-table cases and cleanup +blocks inside a routine, where `bti c` marks a call target and stays a plausible entry. + +Every AArch64 binary bundled with this repo carries its `bti j` words inside exception +landing pads, where the shape test refuses them on its own account and the LSDA rule refuses +them before that -- so on those the flag is redundant and changes nothing either way. The +image below places the word where the shape test would otherwise accept it: after alignment +padding, opening a block that looks exactly like an entry, in a raw buffer that declares no +`.eh_frame` and so no landing pads at all. That is the one arrangement in which the flag +decides the outcome by itself. +""" + +import struct +import unittest + +from smda.Disassembler import Disassembler +from smda.SmdaConfig import SmdaConfig + +BASE = 0x400000 + +NOP = 0xD503201F +RET = 0xD65F03C0 +#: stp x29, x30, [sp, #-16]! / ldp x29, x30, [sp], #16 -- an ordinary frame open and close +STP_FRAME = 0xA9BF7BFD +LDP_FRAME = 0xA8C17BFD + +BTI = 0xD503241F +BTI_C = 0xD503245F +BTI_J = 0xD503249F +BTI_JC = 0xD50324DF + +#: where the hint word lands, and where the block behind it starts +HINT = BASE + 0x20 +BODY = HINT + 4 + + +def words(*values): + return b"".join(struct.pack("