link_reloc_desc.h (3882B)
1 #ifndef KIT_LINK_RELOC_DESC_H 2 #define KIT_LINK_RELOC_DESC_H 3 4 #include "core/core.h" 5 #include "obj/obj.h" 6 #include "obj/reloc.h" 7 8 /* Arch-aware resolution of a relocation kind's static descriptor. 9 * 10 * The per-arch slice (via link_arch_desc_for(c)->reloc_desc) takes 11 * precedence; it falls back to the arch-neutral table. Returns NULL when k 12 * is not a relocation this target applies. This is the single source of a 13 * kind's width + classification — the wire encoding and the diagnostic name 14 * live on the per-(arch,format) ops. See doc/plan/RELOC.md (WS-B). 15 * 16 * The thin reloc_kind_* predicates below replace the former generic 17 * switches (reloc_width / reloc_uses_got / reloc_is_tls_got) and the 18 * per-arch LinkArchDesc.is_* hooks; each reads one descriptor flag. */ 19 const RelocDesc* reloc_desc(const Compiler* c, RelocKind k); 20 21 /* Patched-field width in bytes, or 0 when k has no descriptor — the 22 * "unsupported relocation kind" gate the linker enforces. Nominal (gate) 23 * value for RELOC_WIDTH_DYN kinds, whose true span is read at apply time. */ 24 static inline u8 reloc_kind_width(const Compiler* c, RelocKind k) { 25 const RelocDesc* d = reloc_desc(c, k); 26 return d ? d->width : 0u; 27 } 28 29 /* Needs a GOT slot (the ELF / static GOT pass's notion): a direct GOT load 30 * OR a TLS-IE GOT slot holding a TP-relative offset. */ 31 static inline int reloc_kind_uses_got(const Compiler* c, RelocKind k) { 32 const RelocDesc* d = reloc_desc(c, k); 33 return d && (d->flags & (RELOC_USES_GOT | RELOC_IS_TLS_GOT)) ? 1 : 0; 34 } 35 36 /* GOT slot is filled with the symbol's TP-relative offset (TLS Initial-Exec) 37 * rather than its address. */ 38 static inline int reloc_kind_is_tls_got(const Compiler* c, RelocKind k) { 39 const RelocDesc* d = reloc_desc(c, k); 40 return d && (d->flags & RELOC_IS_TLS_GOT) ? 1 : 0; 41 } 42 43 /* ELF Local-Exec TLS access (the per-arch tp-relative idiom). The in-process 44 * JIT relaxes these to in-image addressing via LinkArchDesc.jit_tls_le_relax. */ 45 static inline int reloc_kind_is_tls_le(const Compiler* c, RelocKind k) { 46 const RelocDesc* d = reloc_desc(c, k); 47 return d && (d->flags & RELOC_IS_TLS_LE) ? 1 : 0; 48 } 49 50 /* A direct GOT-load instruction reloc (the Mach-O linker's notion): non-TLS 51 * GOT load. Distinct from reloc_kind_uses_got, which also counts TLS-IE. */ 52 static inline int reloc_kind_is_got_load(const Compiler* c, RelocKind k) { 53 const RelocDesc* d = reloc_desc(c, k); 54 return d && (d->flags & RELOC_USES_GOT) ? 1 : 0; 55 } 56 57 /* Range-limited call/jump that may need a JIT/range call stub or veneer. */ 58 static inline int reloc_kind_is_branch(const Compiler* c, RelocKind k) { 59 const RelocDesc* d = reloc_desc(c, k); 60 return d && (d->flags & RELOC_IS_BRANCH) ? 1 : 0; 61 } 62 63 /* Mach-O TLV descriptor page / pageoff reloc. */ 64 static inline int reloc_kind_is_tlvp(const Compiler* c, RelocKind k) { 65 const RelocDesc* d = reloc_desc(c, k); 66 return d && (d->flags & RELOC_IS_TLVP) ? 1 : 0; 67 } 68 69 /* Mach-O ADRP-direct (non-GOT) page / pageoff reloc. */ 70 static inline int reloc_kind_is_direct_page(const Compiler* c, RelocKind k) { 71 const RelocDesc* d = reloc_desc(c, k); 72 return d && (d->flags & RELOC_DIRECT_PAGE) ? 1 : 0; 73 } 74 75 /* PC-relative HI20 anchor (RISC-V AUIPC for PCREL_HI20 / GOT_HI20) that a 76 * paired PCREL_LO12 resolves against. The in-process JIT scans for the anchor 77 * to recompute the low-12 displacement under its layout. */ 78 static inline int reloc_kind_is_pcrel_anchor(const Compiler* c, RelocKind k) { 79 const RelocDesc* d = reloc_desc(c, k); 80 return d && (d->flags & RELOC_IS_PCREL_ANCHOR) ? 1 : 0; 81 } 82 83 /* COFF section-relative value (R_COFF_SECREL). A TLS Local-Exec access exactly 84 * when its target is a TLS symbol; the in-process JIT relaxes those. */ 85 static inline int reloc_kind_is_secrel(const Compiler* c, RelocKind k) { 86 const RelocDesc* d = reloc_desc(c, k); 87 return d && (d->flags & RELOC_IS_SECREL) ? 1 : 0; 88 } 89 90 #endif