@@ -2899,7 +2899,21 @@ class Arm64MachoRelocationHandler : public RelocationHandler
28992899 { // Magic number defined in MachOView.cpp for chained fixups
29002900 *(uint64_t *)dest = info.target + info.addend ;
29012901 }
2902- else if (info.nativeType == ARM64_RELOC_PAGE21)
2902+ else if (info.nativeType == ARM64_RELOC_BRANCH26)
2903+ {
2904+ // B/BL: OP=X|00101|IMM26=XXXXXXXXXXXXXXXXXXXXXXXXXX
2905+ // imm26 is signed number of 4-byte instructions
2906+ int64_t delta = (int64_t )reloc->GetTarget () - (int64_t )reloc->GetAddress ();
2907+ if (delta < -(1LL << 27 ) || delta >= (1LL << 27 ) || (delta & 3 ))
2908+ {
2909+ // Relocation can't apply bc the delta is out of range or not 4-byte aligned
2910+ return false ;
2911+ }
2912+ // Keep the opcode, shift the delta bc the encoding is in terms of 4-byte instructions
2913+ insword = (insword & 0xFC000000 ) | ((uint32_t )(delta >> 2 ) & 0x03FFFFFF );
2914+ *(uint32_t *)dest = insword;
2915+ }
2916+ else if (info.nativeType == ARM64_RELOC_PAGE21 || info.nativeType == ARM64_RELOC_GOT_LOAD_PAGE21)
29032917 {
29042918 // 21 bits across IMMHI:IMMLO
29052919 // OP=1|IMMLO=XX|10000|IMMHI=XXXXXXXXXXXXXXXXXXX|RD=XXXXX
@@ -2909,7 +2923,7 @@ class Arm64MachoRelocationHandler : public RelocationHandler
29092923 insword = insword | ((page_delta >> 2 ) << 5 ); // IMMHI
29102924 *(uint32_t *)dest = insword;
29112925 }
2912- else if (info.nativeType == ARM64_RELOC_PAGEOFF12)
2926+ else if (info.nativeType == ARM64_RELOC_PAGEOFF12 || info. nativeType == ARM64_RELOC_GOT_LOAD_PAGEOFF12 )
29132927 {
29142928 /* verify relocation point to qualifying instructions */
29152929 if ((insword & 0x3B000000 ) != 0x39000000 && (insword & 0x11C00000 ) != 0x11000000 )
@@ -2985,17 +2999,19 @@ class Arm64MachoRelocationHandler : public RelocationHandler
29852999 result[i].hasSign = false ;
29863000 break ;
29873001 case ARM64_RELOC_PAGE21:
3002+ case ARM64_RELOC_GOT_LOAD_PAGE21:
29883003 // eg: the number of pages to get to <addr> in "adrp x1, <addr>"
2989- // printf("GetRelocationInfo(): ARM64_RELOC_PAGE21 .address=0x%llX\n", result[i].address);
3004+ // GOT_LOAD: the page of the GOT slot
29903005 break ;
29913006 case ARM64_RELOC_PAGEOFF12:
3007+ case ARM64_RELOC_GOT_LOAD_PAGEOFF12:
29923008 // eg: the 12-bit <immediate> in "add x8, x8, #<immediate>"
2993- // printf("GetRelocationInfo(): ARM64_RELOC_PAGEOFF12 .address=0x%llX\n",
2994- // result[i].address);
3009+ // GOT_LOAD: 12-bit offset in the GOT slot page (usually used with ARM64_RELOC_GOT_LOAD_PAGE21)
29953010 break ;
29963011 case ARM64_RELOC_BRANCH26:
2997- case ARM64_RELOC_GOT_LOAD_PAGE21:
2998- case ARM64_RELOC_GOT_LOAD_PAGEOFF12:
3012+ // 26-bit immediate for branch instrs
3013+ result[i].pcRelative = true ;
3014+ break ;
29993015 case ARM64_RELOC_TLVP_LOAD_PAGE21:
30003016 case ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
30013017 case ARM64_RELOC_ADDEND:
0 commit comments