reloc.c (18671B)
1 /* AArch64 relocation descriptors (width + classification). 2 * 3 * One row per relocation kind this backend applies. Reached through 4 * LinkArchDesc.reloc_desc (wired in link.c) and the arch-aware reloc_desc() 5 * dispatcher. The wire encoding + diagnostic name live in 6 * src/obj/<fmt>/reloc_aarch64.c; the instruction byte encoders live in the 7 * shared byte-patcher (src/obj/reloc_apply.c) until WS-C moves them here. 8 * 9 * Kinds with no row (the dynamic-only GLOB_DAT/JUMP_SLOT/RELATIVE/COPY, the 10 * MCEmitter-only INTRA_LABEL_ADDR, and the unused TLSLE LDST variants) are 11 * never applied through the static reloc record path and intentionally carry 12 * no descriptor. R_ABS16 and R_PREL16 are now neutral and live in the 13 * neutral_rows table; R_TPOFF64 is neutral and also lives there. */ 14 15 #include "obj/reloc.h" 16 17 #include "core/bytes.h" 18 #include "link/link_arch.h" 19 20 static const RelocDescRow aa64_rows[] = { 21 {R_AARCH64_JUMP26, {4, RELOC_IS_BRANCH}}, 22 {R_AARCH64_CALL26, {4, RELOC_IS_BRANCH}}, 23 {R_AARCH64_CONDBR19, {4, 0}}, 24 {R_AARCH64_TSTBR14, {4, 0}}, 25 {R_AARCH64_LD_PREL_LO19, {4, 0}}, 26 {R_AARCH64_ADR_PREL_LO21, {4, 0}}, 27 {R_AARCH64_ADR_PREL_PG_HI21, {4, RELOC_DIRECT_PAGE}}, 28 {R_AARCH64_ADR_PREL_PG_HI21_NC, {4, RELOC_DIRECT_PAGE}}, 29 {R_AARCH64_ADD_ABS_LO12_NC, {4, RELOC_DIRECT_PAGE}}, 30 {R_AARCH64_LDST8_ABS_LO12_NC, {4, RELOC_DIRECT_PAGE}}, 31 {R_AARCH64_LDST16_ABS_LO12_NC, {4, RELOC_DIRECT_PAGE}}, 32 {R_AARCH64_LDST32_ABS_LO12_NC, {4, RELOC_DIRECT_PAGE}}, 33 {R_AARCH64_LDST64_ABS_LO12_NC, {4, RELOC_DIRECT_PAGE}}, 34 {R_AARCH64_LDST128_ABS_LO12_NC, {4, RELOC_DIRECT_PAGE}}, 35 {R_AARCH64_ADR_GOT_PAGE, {4, RELOC_USES_GOT}}, 36 {R_AARCH64_LD64_GOT_LO12_NC, {4, RELOC_USES_GOT}}, 37 {R_AARCH64_POINTER_TO_GOT, {4, RELOC_USES_GOT}}, 38 {R_AARCH64_TLSDESC_ADR_PAGE21, {4, 0}}, 39 {R_AARCH64_TLSDESC_LD64_LO12, {4, 0}}, 40 {R_AARCH64_TLSDESC_ADD_LO12, {4, 0}}, 41 {R_AARCH64_TLSDESC_CALL, {4, 0}}, 42 {R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, {4, RELOC_IS_TLS_GOT}}, 43 {R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, {4, RELOC_IS_TLS_GOT}}, 44 {R_AARCH64_TLSLE_ADD_TPREL_HI12, {4, RELOC_IS_TLS_LE}}, 45 {R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, {4, RELOC_IS_TLS_LE}}, 46 {R_AARCH64_TLVP_LOAD_PAGE21, {4, RELOC_IS_TLVP}}, 47 {R_AARCH64_TLVP_LOAD_PAGEOFF12, {4, RELOC_IS_TLVP}}, 48 /* COFF AArch64 TLS SECREL imm12 pair: ADD-imm12 instruction relocs, 49 * AArch64-only, applied only into PE/COFF output. TLS-only, so the JIT 50 * classifies them as Local-Exec accesses via RELOC_IS_TLS_LE. */ 51 {R_COFF_AARCH64_SECREL_LOW12A, {4, RELOC_IS_TLS_LE}}, 52 {R_COFF_AARCH64_SECREL_HIGH12A, {4, RELOC_IS_TLS_LE}}, 53 {R_COFF_AARCH64_SECREL_LOW12L, {4, RELOC_IS_TLS_LE}}, 54 }; 55 56 const RelocDesc* aa64_reloc_desc(RelocKind k) { 57 return reloc_desc_row_find(aa64_rows, 58 (u32)(sizeof aa64_rows / sizeof aa64_rows[0]), k); 59 } 60 61 static u32 aa64_movz64(u32 rd, u16 imm, u32 hw) { 62 return 0xd2800000u | ((hw & 3u) << 21) | ((u32)imm << 5) | (rd & 31u); 63 } 64 65 static u32 aa64_movk64(u32 rd, u16 imm, u32 hw) { 66 return 0xf2800000u | ((hw & 3u) << 21) | ((u32)imm << 5) | (rd & 31u); 67 } 68 69 /* AArch64 instruction-immediate byte encoders (WS-C). Moved verbatim from the 70 * format-neutral byte-patcher; reached via LinkArchDesc.reloc_apply_insn for 71 * the instruction-embedded kinds. Encoding references: ARM ARMv8-A "ELF for 72 * the ARM 64-bit Architecture (AArch64)" §5.7. Returns 1 if it owns `k`. */ 73 int aa64_reloc_apply_insn(Compiler* c, RelocKind k, u8* P_bytes, u64 S, i64 A, 74 u64 P) { 75 switch (k) { 76 case R_AARCH64_TLSDESC_ADR_PAGE21: 77 case R_AARCH64_TLSDESC_LD64_LO12: 78 case R_AARCH64_TLSDESC_ADD_LO12: 79 case R_AARCH64_TLSDESC_CALL: { 80 /* Static ELF local relaxation: replace the standard TLSDESC 81 * ADRP/LDR/ADD/BLR sequence with a 4-insn materialization of the 82 * local-exec TP-relative offset in x0, matching the TLSDESC resolver's 83 * return register. Dynamic TLSDESC descriptors are rejected earlier by 84 * the ELF linker unless the target is defined TLS in this image. */ 85 u64 v = (u64)((i64)S + A); 86 u16 imm = 0; 87 if (k == R_AARCH64_TLSDESC_ADR_PAGE21) { 88 imm = (u16)(v & 0xffffu); 89 wr_u32_le(P_bytes, aa64_movz64(0, imm, 0)); 90 } else if (k == R_AARCH64_TLSDESC_LD64_LO12) { 91 imm = (u16)((v >> 16) & 0xffffu); 92 wr_u32_le(P_bytes, aa64_movk64(0, imm, 1)); 93 } else if (k == R_AARCH64_TLSDESC_ADD_LO12) { 94 imm = (u16)((v >> 32) & 0xffffu); 95 wr_u32_le(P_bytes, aa64_movk64(0, imm, 2)); 96 } else { 97 imm = (u16)((v >> 48) & 0xffffu); 98 wr_u32_le(P_bytes, aa64_movk64(0, imm, 3)); 99 } 100 (void)P; 101 return 1; 102 } 103 case R_AARCH64_POINTER_TO_GOT: { 104 i64 disp = (i64)S + A - (i64)P; 105 if (disp < -(i64)(1ll << 31) || disp > (i64)0x7fffffff) 106 compiler_panic(c, SRCLOC_NONE, 107 "link: POINTER_TO_GOT out of range (need +/-2GiB)"); 108 wr_u32_le(P_bytes, (u32)(u64)disp); 109 return 1; 110 } 111 case R_AARCH64_CONDBR19: 112 case R_AARCH64_LD_PREL_LO19: { 113 /* B.cond / CB(N)Z / LDR (literal) — imm19 in 4-byte units, 114 * signed, at bits [23:5]. Range: ±1MiB. */ 115 i64 disp = (i64)S + A - (i64)P; 116 u32 instr; 117 u32 imm19; 118 if (disp & 3) 119 compiler_panic(c, SRCLOC_NONE, 120 "link: imm19 reloc misaligned displacement"); 121 if (disp < -(i64)(1 << 20) || disp >= (i64)(1 << 20)) 122 compiler_panic(c, SRCLOC_NONE, 123 "link: imm19 reloc out of range (need ±1MiB)"); 124 imm19 = (u32)((disp >> 2) & 0x7ffffu); 125 instr = rd_u32_le(P_bytes); 126 instr = (instr & ~(0x7ffffu << 5)) | (imm19 << 5); 127 wr_u32_le(P_bytes, instr); 128 return 1; 129 } 130 case R_AARCH64_TSTBR14: { 131 /* TBZ/TBNZ — imm14 in 4-byte units, signed, at bits [18:5]. 132 * Range: ±32KiB. */ 133 i64 disp = (i64)S + A - (i64)P; 134 u32 instr; 135 u32 imm14; 136 if (disp & 3) 137 compiler_panic(c, SRCLOC_NONE, "link: TSTBR14 misaligned displacement"); 138 if (disp < -(i64)(1 << 15) || disp >= (i64)(1 << 15)) 139 compiler_panic(c, SRCLOC_NONE, 140 "link: TSTBR14 out of range (need ±32KiB)"); 141 imm14 = (u32)((disp >> 2) & 0x3fffu); 142 instr = rd_u32_le(P_bytes); 143 instr = (instr & ~(0x3fffu << 5)) | (imm14 << 5); 144 wr_u32_le(P_bytes, instr); 145 return 1; 146 } 147 case R_AARCH64_ADR_PREL_LO21: { 148 /* ADR — byte-granularity imm21, encoded as immlo[30:29] + 149 * immhi[23:5]. No 12-bit shift (unlike ADRP). Range: ±1MiB. */ 150 i64 disp = (i64)S + A - (i64)P; 151 u32 instr; 152 u32 immlo, immhi; 153 if (disp < -(i64)(1 << 20) || disp >= (i64)(1 << 20)) 154 compiler_panic(c, SRCLOC_NONE, 155 "link: ADR_PREL_LO21 out of range (need ±1MiB)"); 156 immlo = (u32)(disp & 0x3u); 157 immhi = (u32)((disp >> 2) & 0x7ffffu); 158 instr = rd_u32_le(P_bytes); 159 instr = (instr & 0x9f00001fu) | (immlo << 29) | (immhi << 5); 160 wr_u32_le(P_bytes, instr); 161 return 1; 162 } 163 case R_AARCH64_JUMP26: 164 case R_AARCH64_CALL26: { 165 /* B/BL imm26 — branch displacement in 4-byte units, signed. 166 * Clear bits [25:0] of the existing instruction and OR in the 167 * new imm26. Range check: ±128MiB. */ 168 i64 disp = (i64)S + A - (i64)P; 169 u32 instr; 170 u32 imm26; 171 if (disp & 3) 172 compiler_panic(c, SRCLOC_NONE, "link: CALL26 misaligned displacement"); 173 if (disp < -(i64)(1 << 27) || disp >= (i64)(1 << 27)) 174 compiler_panic(c, SRCLOC_NONE, 175 "link: CALL26 out of range (need ±128MiB)"); 176 imm26 = (u32)((disp >> 2) & 0x3ffffffu); 177 instr = rd_u32_le(P_bytes); 178 instr = (instr & 0xfc000000u) | imm26; 179 wr_u32_le(P_bytes, instr); 180 return 1; 181 } 182 case R_AARCH64_TLVP_LOAD_PAGE21: 183 case R_AARCH64_ADR_GOT_PAGE: 184 case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: 185 case R_AARCH64_ADR_PREL_PG_HI21: 186 case R_AARCH64_ADR_PREL_PG_HI21_NC: { 187 /* ADRP — page-relative imm21, encoded as immlo[30:29] + 188 * immhi[23:5]. Effective immediate is (S+A) page minus P page, 189 * shifted right by 12, sign-extended to 33 bits. _NC variant 190 * skips the range check (compiler asserts it can't overflow, 191 * e.g. when paired with explicit page bracketing). */ 192 i64 page_s = ((i64)S + A) & ~(i64)0xfff; 193 i64 page_p = (i64)P & ~(i64)0xfff; 194 i64 disp = page_s - page_p; 195 i64 imm21 = disp >> 12; 196 u32 instr; 197 u32 immlo, immhi; 198 if (k != R_AARCH64_ADR_PREL_PG_HI21_NC && 199 (imm21 < -(i64)(1 << 20) || imm21 >= (i64)(1 << 20))) 200 compiler_panic(c, SRCLOC_NONE, 201 "link: ADR_PREL_PG_HI21 out of range (need ±4GiB)"); 202 immlo = (u32)(imm21 & 0x3u); 203 immhi = (u32)((imm21 >> 2) & 0x7ffffu); 204 instr = rd_u32_le(P_bytes); 205 instr = (instr & 0x9f00001fu) | (immlo << 29) | (immhi << 5); 206 wr_u32_le(P_bytes, instr); 207 return 1; 208 } 209 case R_AARCH64_ADD_ABS_LO12_NC: { 210 /* ADD (immediate) imm12 at bits [21:10]. NC = no overflow check. */ 211 u64 v = ((u64)S + (u64)A) & 0xfffu; 212 u32 instr = rd_u32_le(P_bytes); 213 instr = (instr & ~(0xfffu << 10)) | ((u32)v << 10); 214 wr_u32_le(P_bytes, instr); 215 return 1; 216 } 217 case R_AARCH64_TLSLE_ADD_TPREL_HI12: 218 case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: { 219 /* AArch64 TLS local-exec. Caller passes S already as the 220 * TP-relative offset (target's image offset minus the TLS 221 * image base, plus the 16-byte AArch64 TCB). HI12 takes 222 * bits 23:12, LO12_NC takes bits 11:0; both encoded as 223 * imm12 at instruction bits [21:10] of an ADD (immediate). 224 * The HI12 form's instruction carries LSL #12 in its opcode, 225 * so bits 11:0 of the operand naturally land at scale 4096. */ 226 u64 v = (u64)((i64)S + A); 227 u32 imm12 = (k == R_AARCH64_TLSLE_ADD_TPREL_HI12) 228 ? (u32)((v >> 12) & 0xfffu) 229 : (u32)(v & 0xfffu); 230 u32 instr = rd_u32_le(P_bytes); 231 instr = (instr & ~(0xfffu << 10)) | (imm12 << 10); 232 wr_u32_le(P_bytes, instr); 233 return 1; 234 } 235 case R_AARCH64_LDST8_ABS_LO12_NC: 236 case R_AARCH64_LDST16_ABS_LO12_NC: 237 case R_AARCH64_LDST32_ABS_LO12_NC: 238 case R_AARCH64_LDST64_ABS_LO12_NC: 239 case R_AARCH64_LDST128_ABS_LO12_NC: 240 case R_AARCH64_LD64_GOT_LO12_NC: 241 case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 242 case R_AARCH64_TLVP_LOAD_PAGEOFF12: { 243 /* LDR/STR with imm12 at bits [21:10]; the imm is scaled by the 244 * access size, so we right-shift the low 12 bits of (S+A) by 245 * the size scale before encoding. NC = no overflow check. 246 * 247 * LD64_GOT_LO12_NC has the same encoding as LDST64_ABS_LO12_NC; 248 * the linker has already redirected `S` to the GOT slot. */ 249 u32 shift = (k == R_AARCH64_LDST8_ABS_LO12_NC) ? 0u 250 : (k == R_AARCH64_LDST16_ABS_LO12_NC) ? 1u 251 : (k == R_AARCH64_LDST32_ABS_LO12_NC) ? 2u 252 : (k == R_AARCH64_LDST64_ABS_LO12_NC || 253 k == R_AARCH64_LD64_GOT_LO12_NC || 254 k == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC || 255 k == R_AARCH64_TLVP_LOAD_PAGEOFF12) 256 ? 3u 257 : 4u; 258 u64 lo12 = ((u64)S + (u64)A) & 0xfffu; 259 u64 imm12 = lo12 >> shift; 260 u32 instr = rd_u32_le(P_bytes); 261 if (lo12 & ((1u << shift) - 1u)) 262 compiler_panic(c, SRCLOC_NONE, 263 "link: LDST%u_ABS_LO12_NC misaligned address " 264 "(kind=%u S=0x%llx A=%lld P=0x%llx)", 265 1u << (3 + shift), (unsigned)k, (unsigned long long)S, 266 (long long)A, (unsigned long long)P); 267 instr = (instr & ~(0xfffu << 10)) | ((u32)(imm12 & 0xfffu) << 10); 268 wr_u32_le(P_bytes, instr); 269 return 1; 270 } 271 default: 272 return 0; 273 } 274 } 275 276 /* In-process JIT TLS Local-Exec relaxation (LinkArchDesc.jit_tls_le_relax). 277 * 278 * ELF, per access: 279 * mrs rd, tpidr_el0 (no reloc) 280 * add rd, rd, #hi12 R_AARCH64_TLSLE_ADD_TPREL_HI12 <- `site` 281 * add rd, rd, #lo12 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 282 * 283 * Windows/COFF, per access — the 7-instruction TEB idiom (see 284 * aa_tls_addr_of_win): 285 * site-20 ldr rd, [x18, #0x58] TEB.ThreadLocalStoragePointer 286 * site-16 adrp x16, _tls_index } 287 * site-12 add x16, x16, :lo12:_tls_index } &_tls_index (relocs dropped) 288 * site-8 ldr w16, [x16] module TLS index 289 * site-4 ldr rd, [rd, x16, lsl #3] this module's TLS block base 290 * site add rd, rd, :secrel_hi12:sym R_COFF_AARCH64_SECREL_HIGH12A <- 291 * site+4 add rd, rd, :secrel_lo12:sym R_COFF_AARCH64_SECREL_LOW12A 292 * 293 * Single-threaded JIT: in both cases address the in-image storage directly, 294 * dropping the thread-pointer read (and, on Windows, the `_tls_index` / TEB 295 * indirection): adrp rd, &var ; add rd, rd, :lo12:&var ; nop(s). */ 296 void aa64_jit_tls_le_relax(Compiler* c, RelocKind k, u8* site, u64 storage, 297 u64 site_pc) { 298 u8* mrs; 299 u8* add_lo; 300 u32 rd; 301 /* Windows COFF idiom: the terminal HIGH12A drives the whole rewrite; the 302 * LOW12A half is then a no-op (mirrors the ELF HI12/LO12 split). */ 303 if (k == R_COFF_AARCH64_SECREL_LOW12A) return; /* handled with HIGH12A */ 304 if (k == R_COFF_AARCH64_SECREL_HIGH12A) { 305 u8* p; 306 rd = rd_u32_le(site) & 0x1fu; 307 /* nop the TEB read, the _tls_index materialize + load, and the block load 308 * (site-20 .. site-8); reuse the block-load slot at site-4 for the ADRP. */ 309 for (p = site - 20; p <= site - 8; p += 4) wr_u32_le(p, 0xd503201fu); 310 wr_u32_le(site - 4, 0x90000000u | rd); /* adrp rd, #0 */ 311 aa64_reloc_apply_insn(c, R_AARCH64_ADR_PREL_PG_HI21, site - 4, storage, 0, 312 site_pc - 4u); 313 wr_u32_le(site, 0x91000000u | (rd << 5) | rd); /* add rd, rd, #0 */ 314 aa64_reloc_apply_insn(c, R_AARCH64_ADD_ABS_LO12_NC, site, storage, 0, 315 site_pc); 316 wr_u32_le(site + 4, 0xd503201fu); /* nop the secrel_lo12 add */ 317 return; 318 } 319 if (k == R_AARCH64_TLSLE_ADD_TPREL_LO12_NC) return; /* handled with HI12 */ 320 if (k != R_AARCH64_TLSLE_ADD_TPREL_HI12) 321 compiler_panic(c, SRCLOC_NONE, "aa64 jit tls: unexpected reloc kind %u", 322 (unsigned)k); 323 mrs = site - 4; /* mrs rd, tpidr_el0 */ 324 add_lo = site + 4; /* add rd, rd, #lo12 -> nop */ 325 rd = rd_u32_le(site) & 0x1fu; 326 if (rd_u32_le(mrs) != (0xd53bd040u | rd)) 327 compiler_panic(c, SRCLOC_NONE, "aa64 jit tls: unexpected access sequence"); 328 wr_u32_le(mrs, 0x90000000u | rd); /* adrp rd, #0 */ 329 aa64_reloc_apply_insn(c, R_AARCH64_ADR_PREL_PG_HI21, mrs, storage, 0, 330 site_pc - 4u); 331 wr_u32_le(site, 0x91000000u | (rd << 5) | rd); /* add rd, rd, #0 */ 332 aa64_reloc_apply_insn(c, R_AARCH64_ADD_ABS_LO12_NC, site, storage, 0, 333 site_pc); 334 wr_u32_le(add_lo, 0xd503201fu); /* nop */ 335 } 336 337 /* In-process JIT relaxation of AArch64 indirection idioms (LinkArchDesc 338 * .jit_reloc_relax): the single-threaded JIT has no dynamic loader, GOT, or 339 * TLV resolver, so each access idiom is rewritten to address the in-image 340 * instance directly. Returns 1 if it owned `k`, 0 to fall through to the 341 * ordinary reloc apply. */ 342 int aa64_jit_reloc_relax(Compiler* c, RelocKind k, const JitRelaxCtx* ctx) { 343 u8* P_bytes = ctx->site; 344 345 /* Weak undefined target: address-of must evaluate to NULL. An ADRP + ADD 346 * pair would form a PC-relative address to vaddr 0 that exceeds ±4 GiB once 347 * the JIT places segments far from 0 (tripping link_reloc's range check). 348 * Rewrite the ADRP to MOVZ rd,#0 so rd becomes 0 directly; the paired ADD's 349 * assembled imm12 of 0 already gives rd += 0, so leave it as add rd,rd,#0. */ 350 if (ctx->weak_undef_zero) { 351 if (k == R_AARCH64_ADR_PREL_PG_HI21 || k == R_AARCH64_ADR_PREL_PG_HI21_NC) { 352 u32 rd = rd_u32_le(P_bytes) & 0x1fu; 353 wr_u32_le(P_bytes, 0xd2800000u | rd); /* movz rd, #0 */ 354 return 1; 355 } 356 if (k == R_AARCH64_ADD_ABS_LO12_NC) return 1; /* leave add rd,rd,#0 */ 357 } 358 359 /* Mach-O TLV access -> ordinary in-image load. Codegen emits the 4-insn 360 * Apple TLV sequence: 361 * adrp x0, desc@TLVPPAGE (PAGE21) 362 * ldr x0, [x0, desc@TLVPPAGEOFF] (PAGEOFF12) <- this reloc 363 * ldr xN, [x0] -- load the resolver thunk from desc[0] 364 * blr xN -- call thunk(desc) -> &var in x0 365 * With one thread the in-image .tdata/.tbss IS the single instance, and 366 * desc[+16] already holds the variable's in-image storage address (filled by 367 * the normal R_ABS64 against the storage symbol). Collapse to a direct load, 368 * dropping the thunk and the per-thread block: 369 * PAGEOFF12 : ldr x0,[x0,#imm] -> add x0,x0,#(desc & 0xfff) (x0 = &desc) 370 * +4 : ldr xN,[x0] -> ldr x0,[x0,#16] (x0 = &var) 371 * +8 : blr xN -> nop 372 * The thunk register N is scratch (the Apple TLV ABI fixes only x0: 373 * descriptor in, &var out); kit's codegen uses x16, clang picks any free 374 * register (e.g. x8). Accept any N so long as the pair is `ldr xN,[x0]` 375 * (Rn=x0, imm12=0) followed by `blr xN`. */ 376 if (k == R_AARCH64_TLVP_LOAD_PAGEOFF12) { 377 u64 v = ((u64)ctx->S + (u64)ctx->addend) & 0xfffu; 378 u32 instr = rd_u32_le(P_bytes); 379 u8* i_thunk = P_bytes + 4u; 380 u8* i_call = P_bytes + 8u; 381 u32 thunk = rd_u32_le(i_thunk); 382 u32 call = rd_u32_le(i_call); 383 u32 n = thunk & 0x1fu; 384 wr_u32_le(P_bytes, 0x91000000u | (instr & 0x3ffu) | ((u32)v << 10)); 385 if ((thunk & ~0x1fu) != 0xf9400000u || call != (0xd63f0000u | (n << 5u))) 386 compiler_panic(c, SRCLOC_NONE, 387 "kit_jit: unexpected Mach-O TLV access sequence"); 388 wr_u32_le(i_thunk, 0xf9400800u); /* ldr x0, [x0, #16] -> &var */ 389 wr_u32_le(i_call, 0xd503201fu); /* nop */ 390 return 1; 391 } 392 393 /* No real GOT in the append image: the GOT load becomes a direct add, so the 394 * register holds the symbol address itself instead of loading it from a slot. 395 * LD64_GOT_LO12_NC shares the LDR uimm12 encoding; rewrite to ADD imm12. */ 396 if (ctx->got_relaxed && k == R_AARCH64_LD64_GOT_LO12_NC) { 397 u64 v = ((u64)ctx->S + (u64)ctx->addend) & 0xfffu; 398 u32 instr = rd_u32_le(P_bytes); 399 u32 rd = instr & 0x1fu; 400 u32 rn = (instr >> 5) & 0x1fu; 401 wr_u32_le(P_bytes, 0x91000000u | rd | (rn << 5) | ((u32)v << 10)); 402 return 1; 403 } 404 405 return 0; 406 }