kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

link_internal.h (27580B)


      1 #ifndef KIT_LINK_INTERNAL_H
      2 #define KIT_LINK_INTERNAL_H
      3 
      4 /* Shared private definitions for the linker (link.c, link_layout.c,
      5  * link_reloc.c, link_elf.c, link_jit.c). Not part of any public surface;
      6  * not included by anything outside src/link/. */
      7 
      8 #include "core/core.h"
      9 #include "core/hashmap.h"
     10 #include "core/segvec.h"
     11 #include "link/link.h"
     12 #include "obj/obj.h"
     13 #include "obj/symresolve.h"
     14 
     15 /* Per-input mapping built during link_resolve. ObjSymId / ObjSecId are
     16  * scoped to a single ObjBuilder, so the linker maintains an explicit
     17  * lookup from each input's id space into the global LinkSymId /
     18  * LinkSectionId space. Indices are dense (0..count-1 within the input);
     19  * the array is sized to the input's nsymbols / nsections at allocation
     20  * time. Index 0 of each id space is the "none" sentinel and maps to the
     21  * matching LINK_*_NONE. */
     22 typedef struct InputMap {
     23   LinkSymId* sym; /* size = ObjBuilder.nsymbols */
     24   u32 nsym;
     25   LinkSectionId* section; /* size = ObjBuilder.nsections */
     26   u32 nsection;
     27   LinkSectionId* atom; /* size = ObjBuilder.natoms */
     28   u32 natom;
     29   ObjAtomId* sym_atom;   /* size = nsym; ObjSymId -> ObjAtomId */
     30   ObjAtomId* reloc_atom; /* size = obj_reloc_total(input) */
     31   u32 nreloc;
     32   u8* section_has_atoms;   /* size = nsection */
     33   u32* section_atom_first; /* size = nsection; index into section_atom_ids */
     34   u32* section_atom_count; /* size = nsection */
     35   ObjAtomId* section_atom_ids; /* active atoms grouped by section */
     36   u32 nsection_atom_ids;
     37   /* COMDAT discard mask, size = nsection. Set by link_resolve_symbols
     38    * for COFF/PE SELECTANY: when an input's COMDAT section conflicts
     39    * with an earlier definition, the duplicate section is marked here
     40    * so link_gc_compute and link_layout_sections skip it. */
     41   u8* comdat_discarded;
     42 } InputMap;
     43 
     44 void link_input_map_alloc(LinkImage*, InputMap*, ObjBuilder*, u32 nsym_slots);
     45 
     46 static inline ObjAtomId link_input_sym_atom(const InputMap* m, ObjSymId sym) {
     47   return (m && m->sym_atom && sym < m->nsym) ? m->sym_atom[sym] : OBJ_ATOM_NONE;
     48 }
     49 
     50 static inline ObjAtomId link_input_reloc_atom(const InputMap* m,
     51                                               u32 reloc_index) {
     52   return (m && m->reloc_atom && reloc_index < m->nreloc)
     53              ? m->reloc_atom[reloc_index]
     54              : OBJ_ATOM_NONE;
     55 }
     56 
     57 static inline int link_input_section_has_atoms(const InputMap* m,
     58                                                ObjSecId sid) {
     59   return m && m->section_has_atoms && sid < m->nsection &&
     60          m->section_has_atoms[sid];
     61 }
     62 
     63 static inline void link_input_section_atoms(const InputMap* m, ObjSecId sid,
     64                                             u32* first, u32* count) {
     65   if (m && sid < m->nsection && m->section_atom_first &&
     66       m->section_atom_count) {
     67     *first = m->section_atom_first[sid];
     68     *count = m->section_atom_count[sid];
     69   } else {
     70     *first = 0;
     71     *count = 0;
     72   }
     73 }
     74 
     75 static inline LinkSectionId link_input_reloc_section(const InputMap* m,
     76                                                      const Reloc* r,
     77                                                      u32 reloc_index) {
     78   if (!m || !r || r->section_id == OBJ_SEC_NONE || r->section_id >= m->nsection)
     79     return LINK_SEC_NONE;
     80   if (link_input_section_has_atoms(m, r->section_id)) {
     81     ObjAtomId aid = link_input_reloc_atom(m, reloc_index);
     82     if (aid == OBJ_ATOM_NONE || aid >= m->natom) return LINK_SEC_NONE;
     83     return m->atom[aid];
     84   }
     85   return m->section[r->section_id];
     86 }
     87 
     88 static inline LinkSectionId link_input_symbol_section(const InputMap* m,
     89                                                       const ObjSym* s,
     90                                                       ObjSymId sym) {
     91   if (!m || !s || s->section_id == OBJ_SEC_NONE || s->section_id >= m->nsection)
     92     return LINK_SEC_NONE;
     93   if (link_input_section_has_atoms(m, s->section_id)) {
     94     ObjAtomId aid = link_input_sym_atom(m, sym);
     95     if (aid == OBJ_ATOM_NONE || aid >= m->natom) return LINK_SEC_NONE;
     96     return m->atom[aid];
     97   }
     98   return m->section[s->section_id];
     99 }
    100 
    101 /* ---- ObjSym classification (single source of truth) ---------------------
    102  *
    103  * The linker's three lanes (AOT exe/shared in link_resolve.c, `-r`
    104  * relocatable in link_relocatable.c, in-process JIT in link_jit.c) all
    105  * classify input symbols the same way. These predicates are the one
    106  * authority; every lane routes through them. */
    107 
    108 /* Resolution policy now lives in obj/symresolve.h so the LTO staging merge can
    109  * reuse it. These keep the historical link_* spellings (every lane routes
    110  * through them) as thin wrappers over the shared definitions. */
    111 static inline int link_bind_strength(u16 bind) {
    112   return symresolve_bind_strength(bind);
    113 }
    114 static inline int link_sym_is_def(const ObjSym* s) {
    115   return symresolve_sym_is_def(s);
    116 }
    117 static inline int link_sym_is_spurious_undef(const ObjSym* s) {
    118   return symresolve_sym_is_spurious_undef(s);
    119 }
    120 
    121 /* In-section byte count for an input section: BSS/NOBITS report their
    122  * zero-fill size, everything else its emitted byte total
    123  * (link_layout.c / link_jit.c). */
    124 static inline u32 link_section_size_for_link(const Section* s) {
    125   return (s->sem == SSEM_NOBITS || s->kind == SEC_BSS) ? s->bss_size
    126                                                        : s->bytes.total;
    127 }
    128 
    129 /* Open-addressed name -> LinkSymId hash for global / weak definitions
    130  * and lookups (kit_jit_lookup, entry-symbol resolution). Locals never
    131  * land in this table. Sym 0 is the empty-slot sentinel (it's also the
    132  * "none" id per core.h:42 and never appears as a real name). */
    133 
    134 static inline u32 link_sym_hash_(Sym s) { return hash_u32((u32)s); }
    135 HASHMAP_DEFINE(SymHash, Sym, LinkSymId, link_sym_hash_);
    136 
    137 /* Convenience wrappers: the existing call sites pass LinkSymId by value
    138  * (LINK_SYM_NONE on miss) and use insert-if-absent semantics. */
    139 static inline void symhash_init(SymHash* h, Heap* heap) {
    140   SymHash_init(h, heap);
    141 }
    142 static inline void symhash_reserve(SymHash* h, u32 n) { SymHash_reserve(h, n); }
    143 static inline void symhash_fini(SymHash* h) { SymHash_fini(h); }
    144 static inline LinkSymId symhash_get(const SymHash* h, Sym name) {
    145   LinkSymId* hit = SymHash_get(h, name);
    146   return hit ? *hit : LINK_SYM_NONE;
    147 }
    148 static inline void symhash_set(SymHash* h, Sym name, LinkSymId id) {
    149   (void)SymHash_set(h, name, id);
    150 }
    151 static inline int symhash_insert(SymHash* h, Sym name, LinkSymId id,
    152                                  LinkSymId* existing_out) {
    153   return SymHash_try_insert(h, name, id, existing_out);
    154 }
    155 
    156 struct KitJit; /* forward; see link_jit.c */
    157 
    158 /* Archive ingestion state. Members are eagerly parsed into ObjBuilders
    159  * at link_add_archive_bytes time; the demand/whole-archive decision is
    160  * deferred to link_resolve, where matching members are transferred into
    161  * Linker.inputs. ObjBuilder ownership: while `included` is 0 the archive
    162  * owns the builder (freed in linker_release); on inclusion the pointer
    163  * moves into a LinkInput slot and `obj` is nulled to avoid double-free. */
    164 typedef struct LinkArchiveMember {
    165   Sym name; /* interned member name; 0 if anonymous */
    166   ObjBuilder* obj;
    167   u8 included;
    168   u8 pad[7];
    169 } LinkArchiveMember;
    170 
    171 typedef struct LinkArchive {
    172   Sym name;
    173   LinkArchiveMember* members;
    174   u32 nmembers;
    175   u32 order;
    176   u8 whole_archive;
    177   u8 link_mode;
    178   u8 group_id;
    179   u8 pad;
    180 } LinkArchive;
    181 
    182 SEGVEC_DEFINE(LinkInputs, LinkInput, 4); /* 16 entries per segment */
    183 SEGVEC_DEFINE(LinkArchives, LinkArchive, 4);
    184 
    185 struct Linker {
    186   Compiler* c;
    187   Heap* heap;
    188   LinkInputs inputs; /* LinkInputId = slot index + 1 */
    189   LinkArchives archives;
    190   u32 next_input_order;
    191   Sym entry_name;
    192   /* Set by link_set_script. NULL: layout takes the existing default
    193    * bucket-based path. Non-NULL: layout_sections_scripted walks the
    194    * script's output sections in declaration order. Borrowed; the
    195    * script and every sub-object must outlive link_resolve. */
    196   const KitLinkScript* script;
    197   /* -Ttext override of the static ET_EXEC image base. text_base_set==0 leaves
    198    * the default IMAGE_BASE_STATIC; ignored on PIE/shared/scripted layouts. */
    199   int text_base_set;
    200   u64 text_base;
    201   int gc_sections;
    202   int strip_debug;
    203   int allow_undefined;
    204   /* Set by kit_link_exe before link_resolve.  When 1, layout_iplt
    205    * synthesizes a .init_array entry pointing at __kit_ifunc_init so
    206    * the emitted ET_EXEC binary fills its IFUNC slots at startup.  The
    207    * JIT path leaves this 0 — slots are pre-resolved in-process by
    208    * link_jit.c, no ctor needed. */
    209   int emit_static_exe;
    210   /* In-process JIT lane (set by kit_link_jit).  Currently used to
    211    * tolerate undef `__tlv_bootstrap` on Mach-O inputs — the JIT image
    212    * has no dyld, descriptor[+0] is rewritten to kit's thunk during
    213    * kit_jit_from_image, so the symbol's resolved value doesn't
    214    * matter.  Without this, clang-produced .o files (which emit
    215    * `__tlv_bootstrap` as a plain non-weak undef) would panic at
    216    * link_resolve_undefs. */
    217   int jit_mode;
    218   /* Shared-library / DSO output. Shares dynamic ELF layout with PIE
    219    * executables, but has no required entry point and no PT_INTERP. */
    220   int emit_shared;
    221   /* PIE / ET_DYN output. Set by kit_link_exe when opts->pie or any
    222    * DSO input is present. Triggers layout_dyn (Phase 4) and the
    223    * dynamic ELF emit path (Phase 6). */
    224   int emit_pie;
    225   u16 pe_subsystem;
    226   /* RISC-V psABI e_flags accumulated from object inputs selected for this
    227    * link. Float-ABI/RVE conflicts are rejected while registering inputs;
    228    * RVC/TSO feature-presence bits are OR-merged. */
    229   u32 elf_e_flags;
    230   Sym elf_e_flags_source;
    231   u8 have_elf_e_flags;
    232   /* Caller-supplied PT_INTERP. layout_dyn falls back to a target-
    233    * derived default when this is 0. */
    234   Sym interp_path;
    235   /* ---- Flags/policy plumbed from KitLinkSessionOptions by src/api/link.c
    236    * (the kernel-C "linker flags and policy" + strict-validation work). The
    237    * arrays are borrowed; they must outlive link_resolve. ---- */
    238   const KitLinkDefsym* defsyms; /* --defsym NAME=EXPR */
    239   u32 ndefsyms;
    240   const KitLinkSectionStart* section_starts; /* --section-start / -Tdata/-Tbss */
    241   u32 nsection_starts;
    242   KitSlice soname;
    243   const KitSlice* rpaths;
    244   u32 nrpaths;
    245   const KitSlice* runpaths;
    246   u32 nrunpaths;
    247   u8 orphan_handling; /* KitLinkOrphanHandling */
    248   int fatal_warnings; /* --fatal-warnings */
    249   int freestanding_strict; /* strict freestanding link validation */
    250   LinkExternResolver resolver;
    251   void* resolver_user;
    252   /* Borrowed JIT host. Set by kit_link_jit before link_resolve so the
    253    * layout/reloc passes can read execmem->page_size and the JIT mapper
    254    * can reach the host's reserve/protect/tls hooks without rummaging
    255    * through Compiler.ctx (which no longer carries those). NULL on the
    256    * AOT exe/shared lanes. */
    257   const KitJitHost* jit_host;
    258   CompilerCleanup* deferred; /* registered by link_new */
    259 };
    260 
    261 /* ---- GC liveness (link_resolve.c) ---------------------------------------- */
    262 
    263 typedef struct GcLive {
    264   u8**
    265       marks; /* marks[input_idx][obj_sec_id] for implicit whole-section units */
    266   u8** atom_marks; /* atom_marks[input_idx][obj_atom_id] for explicit atoms */
    267   u32* nsec;       /* obj_section_count per input */
    268   u32* natom;      /* obj_atom_count per input */
    269   u32 ninputs;
    270 } GcLive;
    271 
    272 typedef struct GcQueue {
    273   u64* items; /* hi32=input_idx, low31=id, bit31=set for atom */
    274   u32 n;
    275   u32 cap;
    276 } GcQueue;
    277 
    278 /* ---- Cross-file helpers (link_layout.c → link_reloc_layout.c) ------------ */
    279 
    280 /* Four-bucket segment partitioning by permission (defined in link_layout.c). */
    281 typedef enum SegBucket {
    282   SEG_RX = 0,  /* SF_ALLOC | SF_EXEC                  */
    283   SEG_R = 1,   /* SF_ALLOC, no EXEC, no WRITE          */
    284   SEG_RW = 2,  /* SF_ALLOC | SF_WRITE (incl. BSS)      */
    285   SEG_TLS = 3, /* SF_ALLOC | SF_TLS (.tdata + .tbss)   */
    286   SEG_NBUCKETS = 4,
    287 } SegBucket;
    288 
    289 /* section_kept: 1 for allocatable progbits/nobits sections (link_layout.c). */
    290 int link_section_kept(const Section* s);
    291 /* section_kept_fileonly: 1 for non-allocatable .debug_* sections that the
    292  * AOT ELF path carries through as file-only sections (link_layout.c). */
    293 int link_section_kept_fileonly(const Section* s);
    294 /* bucket_for: map section flags to SegBucket (link_layout.c). */
    295 SegBucket link_bucket_for(u16 flags);
    296 /* layout_page_size: page size for segment alignment (link_layout.c). */
    297 u64 link_layout_page_size(Linker* l);
    298 
    299 /* Append a fresh symbol slot and return its id (link_layout.c). */
    300 LinkSymId link_append_symbol(LinkImage* img, const LinkSymbol* tmpl);
    301 /* Append a fresh reloc slot and return it (link_layout.c). */
    302 LinkRelocApply* link_append_reloc_slot(LinkImage* img);
    303 
    304 /* Emit or upsert a synthetic global boundary symbol (link_layout.c). */
    305 void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name,
    306                             u64 vaddr);
    307 void link_emit_section_boundary_sym(Linker* l, LinkImage* img, const char* name,
    308                                     LinkSectionId section_id, u64 value);
    309 
    310 /* Detect __start_<X> / __stop_<X> with <X> a valid C identifier.
    311  * Defined in link_resolve.c; used by link_reloc_layout.c. */
    312 int link_gc_split_start_stop(const char* s, size_t n, size_t* out_off,
    313                              size_t* out_len, int* out_is_start);
    314 
    315 /* GC liveness helpers (link_resolve.c). */
    316 int link_gc_live_get(const GcLive* g, u32 ii, ObjSecId j);
    317 int link_gc_atom_live_get(const GcLive* g, u32 ii, ObjAtomId j);
    318 
    319 /* Segment/section growth helpers for iplt (link_reloc_layout.c). */
    320 u32 link_iplt_alloc_segments(LinkImage* img, u32 nseg);
    321 u32 link_iplt_alloc_sections(LinkImage* img, u32 nsec);
    322 
    323 /* Append one fixed-size synthetic region to the image: a fresh
    324  * page-aligned PT_LOAD segment plus its single covering section, sized
    325  * `size` with permissions `perms` (SF_* flags) and section semantics
    326  * `sem`. The region is placed at page-align(max segment end) so it never
    327  * overlaps existing content. A zero-filled byte buffer of `size` bytes is
    328  * allocated for the segment; *out_vaddr receives the image-relative base
    329  * and *out_bytes the buffer. `sec_align` sets the section's alignment
    330  * (the segment always aligns to the page). Returns the new section's id.
    331  * Backs the GOT / JIT-call-stub / IPLT layout passes
    332  * (link_reloc_layout.c). */
    333 LinkSectionId link_synth_region(LinkImage* img, Linker* l, Sym name, u16 perms,
    334                                 u16 sem, u64 size, u32 sec_align,
    335                                 u64* out_vaddr, u8** out_bytes);
    336 
    337 /* Append one fixed 8-byte ABS64 reloc-apply record targeting `target` at
    338  * `offset` within synthetic section `lsid` (write_vaddr == its file
    339  * offset, as every synthetic region is identity-mapped at layout time).
    340  * Backs the GOT / IPLT / JIT-slot fills (link_reloc_layout.c). */
    341 void link_emit_internal_abs64(LinkImage* img, LinkSectionId lsid, u32 offset,
    342                               u64 write_vaddr, LinkSymId target);
    343 
    344 /* ---- Public entries (link_resolve.c) --------------------------------------
    345  */
    346 void link_ingest_archives(struct Linker*);
    347 void link_merge_elf_e_flags(struct Linker*, ObjBuilder*, KitSlice label);
    348 /* PE/COFF only: synthesize a tiny ObjBuilder providing the mingw CRT
    349  * `__CTOR_LIST__` / `__CTOR_END__` / `__DTOR_LIST__` / `__DTOR_END__`
    350  * boundary symbols.  See link_resolve.c for the contract. */
    351 void link_synth_coff_ctor_dtor_list(struct Linker*);
    352 void link_resolve_symbols(struct Linker*, LinkImage*);
    353 void link_resolve_undefs(struct Linker*, LinkImage*);
    354 void link_gc_compute(struct Linker*, LinkImage*, GcLive*);
    355 void link_gc_live_alloc(GcLive* g, struct Linker* l, Heap* h);
    356 void link_gc_live_free(GcLive* g, Heap* h);
    357 void link_gc_drop_dead_globals(struct Linker*, LinkImage*, const GcLive*);
    358 LinkImage* link_image_alloc(Compiler*);
    359 
    360 /* ---- Public entries (link_layout.c) ---------------------------------------
    361  */
    362 void link_layout_sections(struct Linker*, LinkImage*, const GcLive*);
    363 void link_layout_commons(struct Linker*, LinkImage*);
    364 void link_emit_segment_bytes(struct Linker*, LinkImage*);
    365 /* Carry .debug_* sections through as file-only sections + populate the
    366  * debug registry (link_layout.c). AOT ELF path only; gated by the
    367  * caller on !strip_debug / !jit_mode / ELF target. */
    368 void link_layout_debug(struct Linker*, LinkImage*);
    369 /* Byte buffer for a file-only debug LinkSection, or NULL if `id` is not
    370  * a registered file-only section (link_layout.c). */
    371 u8* link_fileonly_bytes(LinkImage*, LinkSectionId);
    372 
    373 /* ---- Public entries (link_reloc_layout.c) ---------------------------------
    374  */
    375 void link_assign_symbol_vaddrs(struct Linker*, LinkImage*);
    376 void link_emit_array_boundaries(struct Linker*, LinkImage*);
    377 void link_emit_tls_boundaries(struct Linker*, LinkImage*);
    378 void link_emit_encoding_section_boundaries(struct Linker*, LinkImage*);
    379 void link_layout_jit_stubs(struct Linker*, LinkImage*, u32 map_size,
    380                            LinkSymId** stub_map_out);
    381 void link_layout_got(struct Linker*, LinkImage*, u32 map_size,
    382                      LinkSymId** got_map_out);
    383 void link_layout_iplt(struct Linker*, LinkImage*);
    384 void link_emit_relocations(struct Linker*, LinkImage*, const LinkSymId* got_map,
    385                            const LinkSymId* stub_map);
    386 void link_resolve_entry(struct Linker*, LinkImage*);
    387 
    388 /* Defined in link.c. Walks the Linker's inputs and records each input's
    389  * ObjBuilder on the LinkImage so the JIT debug view can reach its
    390  * .debug_* sections after link_free runs.  LINK_INPUT_OBJ_BYTES
    391  * builders are moved (the LinkInput's obj pointer is nulled so
    392  * linker_release skips them); LINK_INPUT_OBJ builders are borrowed
    393  * (the caller still owns).  DSO / TBD inputs are skipped. */
    394 void link_capture_debug_inputs(struct Linker*, LinkImage*);
    395 
    396 /* Default PE/COFF ImageBase for executables.  Mirrored in link_coff.c
    397  * (the emitter writes this into the optional header).  Exposed here so
    398  * link_layout can synthesize the `__ImageBase` symbol at the same
    399  * vaddr, before resolve_undefs runs. */
    400 #define LINK_PE_IMAGE_BASE 0x140000000ULL
    401 
    402 /* Define / upsert a synthetic global symbol resolved to `vaddr`.
    403  * Satisfies any prior undef ref (e.g. _DYNAMIC from Scrt1.o,
    404  * __dso_handle from libc_nonshared.a) and fans out across per-input
    405  * duplicate name slots so emit_reloc_records sees the resolved
    406  * vaddr.  Implemented in link_layout.c. */
    407 void link_define_boundary(struct Linker*, LinkImage*, const char* name,
    408                           u64 vaddr);
    409 
    410 /* SegVec instances for image-owned tables. Pointers returned by *_at /
    411  * *_push remain valid for the LinkImage's lifetime. */
    412 SEGVEC_DEFINE(LinkSyms, LinkSymbol, 6);       /*  64 entries per segment */
    413 SEGVEC_DEFINE(LinkRelocs, LinkRelocApply, 7); /* 128 entries per segment */
    414 
    415 /* ---- Dynamic-link synthesis state (Phase 4) ----
    416  *
    417  * The ELF linker's dynamic-link working state (.dynsym / .dynstr / .gnu.hash
    418  * / .rela.* / .plt / .got.plt / .dynamic) and its wire-format records live in
    419  * the ELF-only header src/obj/elf/link_dyn.h. LinkImage holds it as an opaque
    420  * `LinkDynState* dyn` so the COFF/Mach-O linkers never see the ELF field
    421  * names; only the ELF linker dereferences it. */
    422 typedef struct LinkDynState LinkDynState;
    423 
    424 struct LinkImage {
    425   Compiler* c;
    426   Heap* heap;
    427   CompilerCleanup* deferred; /* registered by link_resolve */
    428   /* Borrowed back-pointer set by link_resolve.  The Linker is not
    429    * mutated through this handle; it's used by the format-specific emit
    430    * passes that need to walk LinkInputs (e.g. resolving an imported
    431    * symbol's dso_input_id back to the providing dylib's install-name). */
    432   struct Linker* linker;
    433 
    434   /* Final merged RISC-V ELF flags, copied after archive selection. */
    435   u32 elf_e_flags;
    436   u8 have_elf_e_flags;
    437 
    438   LinkSyms syms;   /* LinkSymId = slot index + 1 */
    439   SymHash globals; /* name -> LinkSymId for global/weak */
    440 
    441   LinkSection* sections; /* id = index + 1 */
    442   u32 nsections;
    443 
    444   LinkSegment* segments; /* id = index + 1 */
    445   u32 nsegments;
    446   u8** segment_bytes;        /* one per segment; size = file_size */
    447   size_t* segment_bytes_cap; /* allocation size for free */
    448 
    449   LinkRelocs relocs;
    450 
    451   /* IFUNC trampoline table (image-relative vaddrs).  One entry per
    452    * defined STT_GNU_IFUNC symbol: (resolver_vaddr, slot_vaddr).  The
    453    * JIT path walks this after applying relocations, calls each
    454    * resolver in-process, and stores the result into the slot's write
    455    * alias.  The ELF emit path uses it to seed a startup init routine
    456    * (or panics when the routine is not yet wired in). */
    457   u64* iplt_pairs; /* 2 * niplt entries */
    458   u32 niplt;
    459 
    460   LinkSymId entry_sym;
    461 
    462   /* TLS image span (image-relative).  Set when any input contributes
    463    * an SF_TLS section.  filesz covers the .tdata bytes that initialize
    464    * the per-thread block; memsz adds .tbss zero-fill.  tls_align is
    465    * the natural alignment of the TLS image (max of contributing
    466    * sections), distinct from the containing PT_LOAD's page align.
    467    * AArch64 ELF ABI: TP-relative offset of a TLS symbol with image
    468    * offset `o` is `o + 16` (16-byte TCB ahead of the TLS data). */
    469   u64 tls_vaddr;
    470   u64 tls_filesz;
    471   u64 tls_memsz;
    472   u32 tls_align;
    473 
    474   InputMap* input_maps; /* one per input; indexed by input_id-1 */
    475   u32 ninput_maps;
    476 
    477   /* Debug-capture state for the JIT path.  Populated by
    478    * link_capture_debug_inputs at the tail of link_resolve so the input
    479    * ObjBuilders (which carry .debug_* sections + their per-section
    480    * relocations — neither consumed nor mutated by layout) survive the
    481    * Linker's teardown and become reachable from kit_jit_view.
    482    *
    483    * Parallel to input_maps: dbg_objs[i] is the ObjBuilder for input
    484    * (i+1), or NULL when no debug info is present / the input kind isn't
    485    * relevant (DSO/TBD).  dbg_objs_owned[i] is 1 when the image must
    486    * obj_free the builder at link_image_free (transferred from
    487    * LINK_INPUT_OBJ_BYTES), 0 when borrowed (LINK_INPUT_OBJ — caller
    488    * still owns). */
    489   ObjBuilder** dbg_objs;
    490   u8* dbg_objs_owned;
    491   u32 dbg_objs_n;
    492 
    493   /* File-only debug-section registry (AOT ELF path).  link_layout_debug
    494    * appends one file-only LinkSection per surviving .debug_* contribution
    495    * as a contiguous id range [dbg_first_lsid, dbg_first_lsid+dbg_count).
    496    * dbg_bytes[i] / dbg_size[i] hold that contribution's own byte buffer
    497    * (relocs applied in place at reloc-offset), indexed by lsid -
    498    * dbg_first_lsid.  Empty on the JIT / Mach-O / COFF lanes. */
    499   LinkSectionId dbg_first_lsid;
    500   u32 dbg_count;
    501   u8** dbg_bytes;
    502   u64* dbg_size;
    503 
    504   /* Dynamic-link state (Phase 4). NULL when emit_pie was not set on
    505    * the Linker — i.e., the static-exe / JIT path. Owned by the image. */
    506   LinkDynState* dyn;
    507   /* Mirror of Linker.emit_pie at link_resolve time; consulted by emit. */
    508   int pie;
    509   /* Mirror of Linker.emit_shared at link_resolve time; consulted by emit. */
    510   int shared;
    511   /* Set when layout was driven by Linker.script. The emitter then keeps
    512    * segment vaddrs at their script-assigned absolute values, drops the
    513    * self-describing headers PT_LOAD / build-id PT_NOTE, and only shifts
    514    * file offsets to make room for ehdr+phdrs. */
    515   u8 scripted;
    516   /* -Ttext: when text_base_set, the static-exe image base override, mirrored
    517    * from Linker at link_resolve time. Ignored if pie/scripted. */
    518   int text_base_set;
    519   u64 text_base;
    520 
    521   /* Final emit facts recorded by the format emitter for the link-map /
    522    * symbols side-files (kit_link_session_write_map / _write_symbols, which run
    523    * on the format-neutral image *after* emit). The emitter owns runtime-base
    524    * selection and headers synthesis, so the report writers read the resolved
    525    * values back from here instead of re-deriving format-specific policy.
    526    *
    527    * load_base is the runtime base the emitter added to image-relative vaddrs:
    528    * IMAGE_BASE_STATIC, or a -Ttext override, for a static ET_EXEC; 0 for
    529    * PIE/scripted/JIT (which keep image-relative addresses). The headers_*
    530    * fields describe the synthesized read-only headers load segment (ELF: the
    531    * ehdr+phdrs PT_LOAD mapped at load_base); headers_present is 0 when the
    532    * format emits no separate headers segment (scripted ELF, non-ELF). All
    533    * stay zero until emit runs, so a report taken without an emit reports
    534    * image-relative addresses, as before. */
    535   u64 load_base;
    536   u64 headers_filesz;
    537   u64 headers_memsz;
    538   u32 headers_align;
    539   u8 headers_present;
    540 };
    541 
    542 /* Whether S is the canonical LinkSymbol for its non-local name.
    543  *
    544  * Resolution deliberately keeps one LinkSymbol per input symbol: after an
    545  * undefined reference is resolved, its per-input slot mirrors the definition
    546  * so relocations can retain their stable LinkSymId.  img->globals remains the
    547  * authority for the single canonical global/weak slot.  Format emitters and
    548  * post-link reports must use this predicate rather than mistaking those
    549  * resolved reference slots for distinct definitions.
    550  *
    551  * Locals and nameless records are outside the global-name authority and are
    552  * therefore not canonical globals.  A named non-local missing from globals is
    553  * retained defensively; synthetic/import bookkeeping can briefly have that
    554  * shape while an image is being assembled. */
    555 static inline int link_symbol_is_canonical_global(const LinkImage* img,
    556                                                   const LinkSymbol* s) {
    557   LinkSymId canonical;
    558   if (!img || !s || !s->name || s->bind == SB_LOCAL) return 0;
    559   canonical = symhash_get(&img->globals, s->name);
    560   return canonical == LINK_SYM_NONE || canonical == s->id;
    561 }
    562 
    563 /* Page granularity used for ELF segment alignment and the file-offset /
    564  * vaddr congruence the runtime loader requires. 16 KiB matches AArch64
    565  * Apple Silicon and the common Linux/AArch64 kernel config; 4 KiB pages
    566  * are also valid at runtime since 16K is a multiple. */
    567 #define PAGE_SIZE 0x4000u
    568 
    569 /* Apply one relocation in place. P_bytes points at the first byte of the
    570  * relocation site within the final memory; S is the resolved final
    571  * address of the target symbol; A the addend; P the final address of
    572  * the relocation site. Panics on unsupported kinds. */
    573 void link_reloc_apply(Compiler*, RelocKind, u8* P_bytes, u64 S, i64 A, u64 P);
    574 
    575 /* kit emits local-exec TLS only: a thread-local's offset within THIS image's
    576  * TLS block is fixed at link time, so a local-exec access (or the TP-relative
    577  * fill of a TLS initial-exec GOT slot) is valid only against a thread-local
    578  * *defined in the image being linked*.  Panic with a clear diagnostic if `tgt`
    579  * is imported from a shared object (its TLS block belongs to another module,
    580  * sized and placed by the dynamic loader) or resolved to a non-thread-local
    581  * definition.  There is no initial-exec/global-dynamic fallback to relax to,
    582  * so the only alternative is a silently bogus tp-relative offset -- hence the
    583  * hard error.  A no-op when `tgt` is a thread-local defined here. */
    584 void link_require_local_tls(Compiler*, const LinkSymbol* tgt);
    585 
    586 /* Public link_emit_image_writer dispatches by Compiler.target.obj. The
    587  * ELF and Mach-O writers get architecture identity from LinkArchDesc;
    588  * reloc application remains keyed by RelocKind. COFF arrives later. */
    589 void link_emit_elf(LinkImage*, Writer*);
    590 void link_emit_macho(LinkImage*, Writer*);
    591 void link_emit_coff(LinkImage*, Writer*);
    592 
    593 /* Format-agnostic 16-byte image identity, derived from per-segment
    594  * post-shift bytes + vaddrs/sizes.  ELF wraps it in a
    595  * .note.gnu.build-id; Mach-O will wrap it in LC_UUID; COFF/PE in a
    596  * debug directory entry.  One source of truth so the bytes match
    597  * across formats. */
    598 #define LINK_IMAGE_ID_BYTES 16u
    599 void link_image_id_compute(const LinkImage*, u8 out[LINK_IMAGE_ID_BYTES]);
    600 
    601 #endif