Skip to content

Commit 544b7ee

Browse files
committed
[aarch64] Fix handling of ARM64_RELOC_GOT_LOAD_PAGEOFF12 and ARM64_RELOC_GOT_LOAD_PAGE21
1 parent 1527677 commit 544b7ee

1 file changed

Lines changed: 35 additions & 29 deletions

File tree

arch/arm64/arch_arm64.cpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,38 +2925,27 @@ class Arm64MachoRelocationHandler : public RelocationHandler
29252925
}
29262926
else if (info.nativeType == ARM64_RELOC_PAGEOFF12 || info.nativeType == ARM64_RELOC_GOT_LOAD_PAGEOFF12)
29272927
{
2928-
/* verify relocation point to qualifying instructions */
2929-
if ((insword & 0x3B000000) != 0x39000000 && (insword & 0x11C00000) != 0x11000000)
2930-
return false;
2931-
2932-
/* verify it's a positive/forward jump (the imm12 is unsigned) */
2933-
int64_t delta = reloc->GetTarget() - PAGE_NO_OFF(reloc->GetAddress());
2934-
if (delta < 0)
2935-
return false;
2936-
2937-
/* disassemble instruction, is last operand an immediate? is there a shift? */
2938-
Instruction instr;
2939-
if (aarch64_decompose(*(uint32_t*)dest, &instr, reloc->GetAddress()) != 0)
2940-
return false;
2941-
2942-
int n_operands = 0;
2943-
while (instr.operands[n_operands].operandClass != NONE)
2944-
n_operands++;
2945-
2946-
if (instr.operands[n_operands - 1].operandClass != IMM32 &&
2947-
instr.operands[n_operands - 1].operandClass != IMM64)
2928+
int left_shift;
2929+
if ((insword & 0x3B000000) == 0x39000000)
2930+
{
2931+
// ldr/str unsigned immediate has size in top two bits
2932+
left_shift = (insword >> 30) & 0x3;
2933+
}
2934+
else if ((insword & 0x11C00000) == 0x11000000)
2935+
{
2936+
// add/sub immediate
2937+
left_shift = 0;
2938+
}
2939+
else
2940+
{
29482941
return false;
2949-
2950-
int left_shift = (instr.operands[n_operands - 1].shiftValueUsed) ?
2951-
instr.operands[n_operands - 1].shiftValue :
2952-
0;
2942+
}
29532943

29542944
/* re-encode */
2955-
/* left shift is upon DECODING, we right shift to bias this */
2956-
delta = delta >> left_shift;
2957-
// SF=X|OP=0|S=0|100010|SH=X|IMM12=XXXXXXXXXXXX|RN=XXXXX|RD=XXXXX
2958-
uint16_t imm12 = (insword & 0x3FFC00) >> 10;
2959-
imm12 = PAGE_OFF(imm12 + delta);
2945+
// add/sub: SF=X|OP=0|S=0|100010|SH=X|IMM12=XXXXXXXXXXXX|RN=XXXXX|RD=XXXXX
2946+
// ldr/str: Size=XX|111|001|OP=XX|IMM12=XXXXXXXXXXXX|Rn=XXXXX|Rt=XXXXX
2947+
uint64_t page_offset = PAGE_OFF((uint64_t)reloc->GetTarget() + info.addend);
2948+
uint32_t imm12 = (page_offset >> left_shift) & 0xfff;
29602949
insword = (insword & 0xFFC003FF) | (imm12 << 10);
29612950
*(uint32_t*)dest = insword;
29622951
}
@@ -3025,6 +3014,23 @@ class Arm64MachoRelocationHandler : public RelocationHandler
30253014
logger->LogWarn("Unsupported relocation: %s (%x)", GetRelocationString(relocType), relocType);
30263015
return true;
30273016
}
3017+
3018+
virtual size_t GetOperandForExternalRelocation(const uint8_t* data, uint64_t addr, size_t length,
3019+
Ref<LowLevelILFunction> il, Ref<Relocation> relocation) override
3020+
{
3021+
(void)data;
3022+
(void)addr;
3023+
(void)length;
3024+
(void)il;
3025+
auto info = relocation->GetInfo();
3026+
switch (info.nativeType)
3027+
{
3028+
case ARM64_RELOC_GOT_LOAD_PAGE21:
3029+
return BN_NOCOERCE_EXTERN_PTR;
3030+
default:
3031+
return BN_AUTOCOERCE_EXTERN_PTR;
3032+
}
3033+
}
30283034
};
30293035

30303036
/* structs used in relocation handling */

0 commit comments

Comments
 (0)