summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2026-04-13 20:14:42 -0400
committerJosh Ferrell <josh@vector35.com>2026-04-13 20:14:42 -0400
commit15276775d379c8ca24f6a2f53827e853ecd3f6f2 (patch)
treee1504951edb4498472c17a845b69d68b12baa978 /arch
parent64f0668dedd528790837393dc8d59bf5da458478 (diff)
[aarch64] Add support for ARM64_RELOC_BRANCH26, ARM64_RELOC_GOT_LOAD_PAGE21, ARM64_RELOC_GOT_LOAD_PAGEOFF12
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/arch_arm64.cpp30
1 files changed, 23 insertions, 7 deletions
diff --git a/arch/arm64/arch_arm64.cpp b/arch/arm64/arch_arm64.cpp
index a56ed35b..b9cae273 100644
--- a/arch/arm64/arch_arm64.cpp
+++ b/arch/arm64/arch_arm64.cpp
@@ -2899,7 +2899,21 @@ class Arm64MachoRelocationHandler : public RelocationHandler
{ // Magic number defined in MachOView.cpp for chained fixups
*(uint64_t*)dest = info.target + info.addend;
}
- else if (info.nativeType == ARM64_RELOC_PAGE21)
+ else if (info.nativeType == ARM64_RELOC_BRANCH26)
+ {
+ // B/BL: OP=X|00101|IMM26=XXXXXXXXXXXXXXXXXXXXXXXXXX
+ // imm26 is signed number of 4-byte instructions
+ int64_t delta = (int64_t)reloc->GetTarget() - (int64_t)reloc->GetAddress();
+ if (delta < -(1LL << 27) || delta >= (1LL << 27) || (delta & 3))
+ {
+ // Relocation can't apply bc the delta is out of range or not 4-byte aligned
+ return false;
+ }
+ // Keep the opcode, shift the delta bc the encoding is in terms of 4-byte instructions
+ insword = (insword & 0xFC000000) | ((uint32_t)(delta >> 2) & 0x03FFFFFF);
+ *(uint32_t*)dest = insword;
+ }
+ else if (info.nativeType == ARM64_RELOC_PAGE21 || info.nativeType == ARM64_RELOC_GOT_LOAD_PAGE21)
{
// 21 bits across IMMHI:IMMLO
// OP=1|IMMLO=XX|10000|IMMHI=XXXXXXXXXXXXXXXXXXX|RD=XXXXX
@@ -2909,7 +2923,7 @@ class Arm64MachoRelocationHandler : public RelocationHandler
insword = insword | ((page_delta >> 2) << 5); // IMMHI
*(uint32_t*)dest = insword;
}
- else if (info.nativeType == ARM64_RELOC_PAGEOFF12)
+ else if (info.nativeType == ARM64_RELOC_PAGEOFF12 || info.nativeType == ARM64_RELOC_GOT_LOAD_PAGEOFF12)
{
/* verify relocation point to qualifying instructions */
if ((insword & 0x3B000000) != 0x39000000 && (insword & 0x11C00000) != 0x11000000)
@@ -2985,17 +2999,19 @@ class Arm64MachoRelocationHandler : public RelocationHandler
result[i].hasSign = false;
break;
case ARM64_RELOC_PAGE21:
+ case ARM64_RELOC_GOT_LOAD_PAGE21:
// eg: the number of pages to get to <addr> in "adrp x1, <addr>"
- // printf("GetRelocationInfo(): ARM64_RELOC_PAGE21 .address=0x%llX\n", result[i].address);
+ // GOT_LOAD: the page of the GOT slot
break;
case ARM64_RELOC_PAGEOFF12:
+ case ARM64_RELOC_GOT_LOAD_PAGEOFF12:
// eg: the 12-bit <immediate> in "add x8, x8, #<immediate>"
- // printf("GetRelocationInfo(): ARM64_RELOC_PAGEOFF12 .address=0x%llX\n",
- // result[i].address);
+ // GOT_LOAD: 12-bit offset in the GOT slot page (usually used with ARM64_RELOC_GOT_LOAD_PAGE21)
break;
case ARM64_RELOC_BRANCH26:
- case ARM64_RELOC_GOT_LOAD_PAGE21:
- case ARM64_RELOC_GOT_LOAD_PAGEOFF12:
+ // 26-bit immediate for branch instrs
+ result[i].pcRelative = true;
+ break;
case ARM64_RELOC_TLVP_LOAD_PAGE21:
case ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
case ARM64_RELOC_ADDEND: