link_reloc_desc.h (4619B)
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 */ 46 static inline int reloc_kind_is_tls_le(const Compiler* c, RelocKind k) { 47 const RelocDesc* d = reloc_desc(c, k); 48 return d && (d->flags & RELOC_IS_TLS_LE) ? 1 : 0; 49 } 50 51 /* A direct GOT-load instruction reloc (the Mach-O linker's notion): non-TLS 52 * GOT load. Distinct from reloc_kind_uses_got, which also counts TLS-IE. */ 53 static inline int reloc_kind_is_got_load(const Compiler* c, RelocKind k) { 54 const RelocDesc* d = reloc_desc(c, k); 55 return d && (d->flags & RELOC_USES_GOT) ? 1 : 0; 56 } 57 58 /* Range-limited call/jump that may need a JIT/range call stub or veneer. */ 59 static inline int reloc_kind_is_branch(const Compiler* c, RelocKind k) { 60 const RelocDesc* d = reloc_desc(c, k); 61 return d && (d->flags & RELOC_IS_BRANCH) ? 1 : 0; 62 } 63 64 /* Mach-O TLV descriptor page / pageoff reloc. */ 65 static inline int reloc_kind_is_tlvp(const Compiler* c, RelocKind k) { 66 const RelocDesc* d = reloc_desc(c, k); 67 return d && (d->flags & RELOC_IS_TLVP) ? 1 : 0; 68 } 69 70 /* Mach-O ADRP-direct (non-GOT) page / pageoff reloc. */ 71 static inline int reloc_kind_is_direct_page(const Compiler* c, RelocKind k) { 72 const RelocDesc* d = reloc_desc(c, k); 73 return d && (d->flags & RELOC_DIRECT_PAGE) ? 1 : 0; 74 } 75 76 /* PC-relative HI20 anchor (RISC-V AUIPC for PCREL_HI20 / GOT_HI20) that a 77 * paired PCREL_LO12 resolves against. The in-process JIT scans for the anchor 78 * to recompute the low-12 displacement under its layout. */ 79 static inline int reloc_kind_is_pcrel_anchor(const Compiler* c, RelocKind k) { 80 const RelocDesc* d = reloc_desc(c, k); 81 return d && (d->flags & RELOC_IS_PCREL_ANCHOR) ? 1 : 0; 82 } 83 84 /* COFF section-relative value (R_COFF_SECREL). A TLS Local-Exec access exactly 85 * when its target is a TLS symbol; the in-process JIT relaxes those. */ 86 static inline int reloc_kind_is_secrel(const Compiler* c, RelocKind k) { 87 const RelocDesc* d = reloc_desc(c, k); 88 return d && (d->flags & RELOC_IS_SECREL) ? 1 : 0; 89 } 90 91 /* Relaxation marker that patches no bytes (RISC-V RELAX / TPREL_ADD / ALIGN). 92 * No reloc record is emitted for these — they are dropped during layout. */ 93 static inline int reloc_kind_is_marker(const Compiler* c, RelocKind k) { 94 const RelocDesc* d = reloc_desc(c, k); 95 return d && (d->flags & RELOC_MARKER) ? 1 : 0; 96 } 97 98 /* Variable-width kind (RISC-V ULEB128 SET/SUB): the descriptor width is only a 99 * nominal gate value; the true field length is read from the bytes at apply 100 * time, so the layout pass must bound-check the offset before the apply scan. 101 */ 102 static inline int reloc_kind_is_width_dyn(const Compiler* c, RelocKind k) { 103 const RelocDesc* d = reloc_desc(c, k); 104 return d && (d->flags & RELOC_WIDTH_DYN) ? 1 : 0; 105 } 106 107 #endif