@@ -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