kit

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

obj.h (56092B)


      1 #ifndef KIT_OBJ_H
      2 #define KIT_OBJ_H
      3 
      4 #include "core/buf.h"
      5 #include "core/core.h"
      6 
      7 /* Forward decl: the synthetic-input hook (obj_format_synth_inputs) takes a
      8  * Linker but obj.h must not pull in the link subsystem. Defined in
      9  * src/link; only used here as an opaque pointer. */
     10 typedef struct Linker Linker;
     11 
     12 typedef enum SecKind {
     13   SEC_TEXT,
     14   SEC_RODATA,
     15   SEC_DATA,
     16   SEC_BSS,
     17   SEC_DEBUG,
     18   SEC_OTHER,
     19 } SecKind;
     20 
     21 typedef enum SecFlag {
     22   SF_EXEC = 1u << 0,
     23   SF_WRITE = 1u << 1,
     24   SF_ALLOC = 1u << 2,
     25   SF_TLS = 1u << 3,
     26   SF_MERGE = 1u << 4,
     27   SF_STRINGS = 1u << 5,
     28   SF_GROUP = 1u << 6,
     29   SF_LINK_ORDER = 1u << 7,
     30   SF_RETAIN = 1u << 8, /* SHF_GNU_RETAIN: do not GC even if unreferenced */
     31 } SecFlag;
     32 
     33 typedef enum SecSem {
     34   SSEM_PROGBITS,
     35   SSEM_NOBITS,
     36   SSEM_SYMTAB,
     37   SSEM_STRTAB,
     38   SSEM_RELA,
     39   SSEM_REL,
     40   SSEM_NOTE,
     41   SSEM_INIT_ARRAY,
     42   SSEM_FINI_ARRAY,
     43   SSEM_PREINIT_ARRAY,
     44   SSEM_GROUP,
     45   SSEM_WASM_CUSTOM,
     46 } SecSem;
     47 
     48 typedef enum SymBind {
     49   SB_LOCAL,
     50   SB_GLOBAL,
     51   SB_WEAK,
     52 } SymBind;
     53 
     54 typedef enum SymVis {
     55   SV_DEFAULT,
     56   SV_HIDDEN,
     57   SV_PROTECTED,
     58   SV_INTERNAL,
     59 } SymVis;
     60 
     61 typedef enum SymKind {
     62   SK_UNDEF,
     63   SK_FUNC,
     64   SK_OBJ,
     65   SK_SECTION,
     66   SK_FILE,
     67   SK_COMMON,
     68   SK_TLS,
     69   SK_ABS,
     70   /* Defined symbol with no specific type — assembly labels, AArch64
     71    * mapping symbols (`$x`, `$d`). Distinct from SK_UNDEF (undefined
     72    * external) so the linker keeps definedness keyed on SK_UNDEF. */
     73   SK_NOTYPE,
     74   /* GNU IFUNC: a function whose implementation is selected at runtime
     75    * by a resolver. Round-trips as STT_GNU_IFUNC (10); presence forces
     76    * EI_OSABI=ELFOSABI_GNU on emit. */
     77   SK_IFUNC,
     78 } SymKind;
     79 
     80 typedef enum ObjExtKind {
     81   OBJ_EXT_NONE,
     82   OBJ_EXT_ELF,
     83   OBJ_EXT_COFF,
     84   OBJ_EXT_MACHO,
     85   OBJ_EXT_WASM,
     86   /* Wasm-target frontend-supplied import descriptors keyed by symbol name.
     87    * Populated by lang/c when an extern declaration carries
     88    * __attribute__((import_module(...), import_name(...))); consumed by the
     89    * wasm backend when promoting undefined function symbols to imports. */
     90   OBJ_EXT_WASM_IMPORTS,
     91 } ObjExtKind;
     92 
     93 typedef u32 ObjSecId;
     94 #define OBJ_SEC_NONE 0u
     95 
     96 typedef u32 ObjGroupId;
     97 #define OBJ_GROUP_NONE 0u
     98 
     99 /* Per-ObjBuilder symbol handle. Object files own their symbol namespace:
    100  * local/static symbols, section symbols, file symbols, unnamed labels, common
    101  * definitions, and external references are all represented by ObjSymId values
    102  * scoped to one builder. 0 is reserved as "none". */
    103 typedef u32 ObjSymId;
    104 #define OBJ_SYM_NONE 0u
    105 
    106 typedef u32 ObjAtomId;
    107 #define OBJ_ATOM_NONE 0u
    108 
    109 typedef enum ObjAtomFlag {
    110   OBJ_ATOM_RETAIN = 1u << 0,
    111 } ObjAtomFlag;
    112 
    113 typedef enum RelocKind {
    114   R_NONE = 0,
    115   R_ABS32,
    116   R_ABS64,
    117   R_REL32,
    118   R_REL64,
    119   R_PC32,
    120   R_PC64,
    121   R_GOT32,
    122   R_PLT32,
    123   /* Neutral data-word kinds completing the ABS/PREL/TPOFF families. */
    124   R_ABS8,
    125   R_ABS16,
    126   R_PREL16,
    127   /* Internal-only: a raw 64-bit local-exec tpoff written into a TLS GOT
    128    * slot by link_emit_internal_tpoff64.  Never appears on the wire.
    129    * x86_64 stores variant-II (X - tls_memsz); AArch64 and RISC-V store
    130    * variant-I ((X - tls_vaddr) + TCB).  Byte encoding is identical on
    131    * all three arches: a plain 64-bit little-endian write. */
    132   R_TPOFF64,
    133   R_AARCH64_ADR_GOT_PAGE,
    134   R_AARCH64_LD64_GOT_LO12_NC,
    135   R_AARCH64_JUMP26,
    136   R_AARCH64_CALL26,
    137   R_AARCH64_CONDBR19,
    138   R_AARCH64_TSTBR14,
    139   R_AARCH64_LD_PREL_LO19,
    140   R_AARCH64_ADR_PREL_LO21,
    141   /* MCEmitter-only function-local label address materialization. The fixup
    142    * patches a fixed 16-byte sequence as either ADR+B+literal when in range,
    143    * or LDR-literal+B+relocated-literal when the ADR range is exceeded. */
    144   R_AARCH64_INTRA_LABEL_ADDR,
    145   R_AARCH64_ADR_PREL_PG_HI21,
    146   R_AARCH64_ADR_PREL_PG_HI21_NC,
    147   R_AARCH64_ADD_ABS_LO12_NC,
    148   R_AARCH64_LDST8_ABS_LO12_NC,
    149   R_AARCH64_LDST16_ABS_LO12_NC,
    150   R_AARCH64_LDST32_ABS_LO12_NC,
    151   R_AARCH64_LDST64_ABS_LO12_NC,
    152   R_AARCH64_LDST128_ABS_LO12_NC,
    153   /* AArch64 Mach-O TLV (thread-local variable) descriptor access. The
    154    * compiler emits these to reference a TLV descriptor in
    155    * __DATA,__thread_vars; the linker routes both through a synthetic
    156    * __DATA,__thread_ptrs slot (analogous to __got for non-TLV externs).
    157    *
    158    *   adrp x0, _var@TLVPPAGE         ; TLVP_LOAD_PAGE21
    159    *   ldr  x0, [x0, _var@TLVPPAGEOFF]; TLVP_LOAD_PAGEOFF12  -> descriptor
    160    *   ldr  x1, [x0]                  ; thunk (filled by dyld)
    161    *   blr  x1                        ; thunk(x0=descriptor) -> x0 = TLV addr
    162    *
    163    * Encoding-wise PAGE21 is ADRP-form and PAGEOFF12 is a 64-bit-LDR
    164    * lo12 (scale=3). The linker rewrites S to the matching __thread_ptrs
    165    * slot's vaddr before applying. */
    166   R_AARCH64_TLVP_LOAD_PAGE21,
    167   R_AARCH64_TLVP_LOAD_PAGEOFF12,
    168   /* AArch64 TLS Local-Exec model. */
    169   R_AARCH64_TLSLE_ADD_TPREL_HI12,
    170   R_AARCH64_TLSLE_ADD_TPREL_LO12,
    171   R_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
    172   R_AARCH64_TLSLE_LDST8_TPREL_LO12,
    173   R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC,
    174   R_AARCH64_TLSLE_LDST16_TPREL_LO12,
    175   R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC,
    176   R_AARCH64_TLSLE_LDST32_TPREL_LO12,
    177   R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC,
    178   R_AARCH64_TLSLE_LDST64_TPREL_LO12,
    179   R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC,
    180   /* Dynamic-only relocs: emitted into .rela.dyn / .rela.plt of an
    181    * ET_DYN/ET_EXEC output and processed by the runtime loader. They
    182    * never appear in ET_REL inputs from a compiler; the linker may
    183    * synthesize them during dynamic-exe / shared-lib emit, and the
    184    * reader recognizes them when it walks an ET_DYN's .rela.* sections
    185    * (currently only used for symbol-name extraction, not applied). */
    186   R_AARCH64_GLOB_DAT,
    187   R_AARCH64_JUMP_SLOT,
    188   R_AARCH64_RELATIVE,
    189   R_AARCH64_COPY,
    190   /* x86_64 reloc kinds. Most map directly to the existing R_ABS and
    191    * R_PC entries; the few here are the x86_64-only encodings (8-bit
    192    * displacements, GOT/PLT, dynamic linker-only entries). */
    193   R_X64_PC8,
    194   R_X64_32S,
    195   R_X64_PLT32,
    196   R_X64_GOTPCREL,
    197   R_X64_GOTPCRELX,
    198   R_X64_REX_GOTPCRELX,
    199   R_X64_GOTPC32,
    200   R_X64_GOTOFF64,
    201   R_X64_TPOFF32,
    202   R_X64_DTPOFF32,
    203   R_X64_DTPMOD64,
    204   R_X64_DTPOFF64,
    205   R_X64_TLSGD,
    206   R_X64_TLSLD,
    207   R_X64_GOTTPOFF,
    208   R_X64_GLOB_DAT,
    209   R_X64_JUMP_SLOT,
    210   R_X64_RELATIVE,
    211   R_X64_COPY,
    212   /* Mach-O x86_64 TLV access: RIP-relative disp32 in `movq sym@TLVP(%rip),
    213    * %rdi` addressing the __thread_ptrs slot that holds the TLV descriptor
    214    * address (the descriptor-model peer of arm64's TLVP_LOAD_PAGE21/PAGEOFF12;
    215    * maps to X86_64_RELOC_TLV). Distinct from the ELF R_X64_TPOFF32 Local-Exec
    216    * kind. */
    217   R_X64_TLV,
    218   R_RV_HI20,
    219   R_RV_LO12_I,
    220   R_RV_LO12_S,
    221   R_RV_BRANCH,
    222   R_RV_JAL,
    223   R_RV_CALL,
    224   R_RV_PCREL_HI20,
    225   R_RV_PCREL_LO12_I,
    226   R_RV_PCREL_LO12_S,
    227   /* Intra-section label address materialization via an AUIPC+ADDI pair.
    228    * Used only by MCEmitter intra-section label fixups (CGTarget
    229    * load_label_addr). Width is 8 bytes, covering both instructions; the
    230    * fixup site is the AUIPC and the disp is the label byte offset
    231    * relative to the AUIPC site. */
    232   R_RV_INTRA_AUIPC_ADDI,
    233   R_RV_GOT_HI20,
    234   /* TLS Initial-Exec: %tls_ie_pcrel_hi(sym). Paired with R_RV_PCREL_LO12_I
    235    * on the follow-on ld. The GOT entry holds (&sym - tp); the AUIPC/ld
    236    * pair materializes that offset into a register so the caller adds tp. */
    237   R_RV_TLS_GOT_HI20,
    238   R_RV_TPREL_HI20,
    239   R_RV_TPREL_LO12_I,
    240   R_RV_TPREL_LO12_S,
    241   R_RV_TPREL_ADD,
    242   R_ADD8,
    243   R_ADD16,
    244   R_ADD32,
    245   R_ADD64,
    246   R_SUB8,
    247   R_SUB16,
    248   R_SUB32,
    249   R_SUB64,
    250   R_RV_ALIGN,
    251   R_RV_RVC_BRANCH,
    252   R_RV_RVC_JUMP,
    253   R_RV_RELAX,
    254   R_SUB6,
    255   R_SET6,
    256   R_SET_ULEB128,
    257   R_SUB_ULEB128,
    258   R_WASM_FUNCIDX,
    259   R_WASM_TABLEIDX,
    260   R_WASM_MEMOFS,
    261   R_WASM_TYPEIDX,
    262   /* COFF/PE-only reloc kinds — section-relative fixups used by Windows
    263    * TLS Local-Exec lowering and debug info. SECREL = 32-bit offset
    264    * from the start of the containing section. SECTION = 16-bit section
    265    * index (1-based). Both arch-independent on the kit side; the
    266    * per-arch translators map to IMAGE_REL_{AMD64,ARM64}_SECREL/SECTION. */
    267   R_COFF_SECREL,
    268   R_COFF_SECTION,
    269   /* AArch64 Windows TLS access uses an ADD-imm12-pair to materialize a
    270    * 24-bit SECREL value into a register:
    271    *   add  xd, xd, #:secrel_hi12:sym, lsl #12   ; HIGH12A bits [23:12]
    272    *   add  xd, xd, #:secrel_lo12:sym            ; LOW12A  bits [11:0]
    273    * The instruction at the patch site already has sh=1 (HIGH) or sh=0
    274    * (LOW) preset by the codegen; the linker only patches the imm12
    275    * field at bits [21:10]. NC variants ("no carry / no overflow check"
    276    * in PE terminology) mean the high bits of SECREL above 24 are
    277    * discarded — fine for any .tls section under 16 MiB. */
    278   R_COFF_AARCH64_SECREL_LOW12A,
    279   R_COFF_AARCH64_SECREL_HIGH12A,
    280   /* AArch64 TLS Initial-Exec. The ADRP/LDR pair loads the symbol's
    281    * TP-relative offset from a GOT slot; the linker fills that slot with a
    282    * 64-bit tpoff (R_TPOFF64) and redirects these to the slot, so they apply
    283    * exactly like the regular ADR_GOT_PAGE / LD64_GOT_LO12_NC pair.
    284    * Appended at the enum tail so the public KIT_RELOC_* values (object.h)
    285    * keep their pinned numbering. */
    286   R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,
    287   R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC,
    288   /* COFF ADDR32NB: 32-bit image-relative RVA (S + A - ImageBase), used by
    289    * PE exception tables and other image metadata. */
    290   R_COFF_ADDR32NB,
    291   /* AArch64 Mach-O POINTER_TO_GOT: a 32-bit PC-relative data relocation that
    292    * materializes the address of a GOT entry. Used by Apple toolchains in
    293    * unwind metadata such as __eh_frame. */
    294   R_AARCH64_POINTER_TO_GOT,
    295   /* AArch64 ELF TLSDESC static relocations. The ELF executable linker
    296    * currently accepts these only for defined local TLS and relaxes the
    297    * four-instruction descriptor call sequence to materialize a TP-relative
    298    * local-exec offset. Dynamic TLSDESC descriptors are intentionally not
    299    * represented yet. */
    300   R_AARCH64_TLSDESC_ADR_PAGE21,
    301   R_AARCH64_TLSDESC_LD64_LO12,
    302   R_AARCH64_TLSDESC_ADD_LO12,
    303   R_AARCH64_TLSDESC_CALL,
    304   /* RISC-V TLS General-Dynamic / Local-Dynamic access. Executable links
    305    * currently relax it to local-exec when the TLS symbol is defined in the
    306    * image. Appended at the enum tail to keep existing public values stable. */
    307   R_RV_TLS_GD_HI20,
    308   /* AArch64 Windows SECREL low-12 load/store form. Appended at the enum tail
    309    * to keep existing public relocation values stable. */
    310   R_COFF_AARCH64_SECREL_LOW12L,
    311   /* 32-bit ARM (Thumb-2, M-profile) ELF relocations. Static-only, Thumb-only:
    312    * BL never relaxes to BLX (everything is Thumb on Cortex-M). The split-
    313    * immediate byte patcher lives in src/arch/arm32/reloc.c. Data words reuse
    314    * the neutral R_ABS32/R_REL32/R_ABS16/R_ABS8 kinds. Appended at the enum
    315    * tail to keep existing public relocation values stable. */
    316   R_ARM_THM_CALL,         /* BL/BLX (T1): 25-bit {S,I1,I2,imm10,imm11}, +-16MB */
    317   R_ARM_THM_JUMP24,       /* B.W (T4): same 25-bit field */
    318   R_ARM_THM_JUMP19,       /* B<cond>.W (T3): 21-bit {S,J2,J1,imm6,imm11}, +-1MB */
    319   R_ARM_THM_MOVW_ABS_NC,  /* MOVW (T3): imm16 = (S+A)[15:0], imm4:i:imm3:imm8 */
    320   R_ARM_THM_MOVT_ABS,     /* MOVT (T3): imm16 = (S+A)[31:16] */
    321   R_ARM_THM_MOVW_PREL_NC, /* PC-rel MOVW (PIC; follow-on) */
    322   R_ARM_THM_MOVT_PREL,    /* PC-rel MOVT (PIC; follow-on) */
    323   R_ARM_TLS_LE32,         /* TLS local-exec: S + A - tp (variant I; follow-on) */
    324 } RelocKind;
    325 
    326 typedef struct Section {
    327   Sym name;
    328   u16 kind;
    329   u16 flags;
    330   u16 sem;      /* SecSem */
    331   u16 ext_kind; /* ObjExtKind */
    332   u32 align;
    333   u32 entsize;
    334   ObjSecId link;       /* section index or OBJ_SEC_NONE */
    335   u32 info;            /* section-format dependent, typed by sem/ext_kind */
    336   ObjGroupId group_id; /* OBJ_GROUP_NONE if not in a COMDAT/group */
    337   u32 bss_size;        /* nonzero only for SEC_BSS */
    338   u64 addr;            /* load vaddr (sh_addr); 0 for relocatable inputs */
    339   /* Format-specific raw section type (ELF sh_type, COFF Characteristics
    340    * subfield, etc.).  Set by .o readers when the canonical SecSem
    341    * mapping is lossy — e.g., SHT_LLVM_ADDRSIG (0x6FFF4C03) and
    342    * SHT_ARM_ATTRIBUTES (0x70000003) collapse to SSEM_PROGBITS but
    343    * the emitter must write back the original value to round-trip.
    344    * Zero means "no override; derive from sem". */
    345   u32 ext_type;
    346   u32 ext_flags; /* same idea for format-specific sh_flags bits
    347                     not represented in SecFlag (e.g. SHF_EXCLUDE) */
    348   /* Tombstone for strip/objcopy-style mutations. Set by
    349    * obj_section_remove; honored by obj_sweep_dead and the emitters.
    350    * Iterators / direct ID-based access on the builder must consult this
    351    * bit and skip removed entries. */
    352   u8 removed;
    353   Buf bytes;
    354 } Section;
    355 
    356 typedef struct Reloc {
    357   ObjSecId section_id;
    358   u32 offset;
    359   u16 kind;
    360   u8 has_explicit_addend;
    361   u8 pair; /* paired/following relocation, format-specific */
    362   /* Tombstone set by obj_sweep_dead when the reloc points at a removed
    363    * section or symbol. Lives in the slack between `pair` and `sym` — no
    364    * struct-size change. */
    365   u8 removed;
    366   ObjSymId sym;
    367   i64 addend;
    368 } Reloc;
    369 
    370 typedef struct ObjSym {
    371   Sym name;
    372   u16 bind;
    373   u16 kind;
    374   u8 vis;
    375   u8 ext_kind;
    376   u16 flags;
    377   ObjSecId section_id; /* OBJ_SEC_NONE if undef */
    378   u64 value;           /* offset within section, or absolute */
    379   u64 size;
    380   u64 common_align; /* nonzero for SK_COMMON */
    381   /* Lifecycle gate for spurious-UNDEF pruning at .o emit time.
    382    *
    383    * The C frontend mints an ObjSym for every `extern` declaration it
    384    * parses (so a header like <stdio.h> creates 50+ ObjSyms in one TU).
    385    * Most of those are never the target of any relocation. `referenced`
    386    * tracks that distinction: obj_reloc_ex sets it on the target, and
    387    * the file emitters (elf_emit / macho_emit) drop entries that are
    388    * still SK_UNDEF + (SB_GLOBAL|SB_WEAK) + !referenced from the output
    389    * symbol table.
    390    *
    391    * Definitions never need the gate — kind != SK_UNDEF for those, so
    392    * the filter never considers them. Readers (elf_read, macho_read)
    393    * mark every read-in symbol referenced=1 so a roundtrip preserves
    394    * UNDEFs that came from another tool's output. */
    395   u8 referenced;
    396   /* Tombstone for strip/objcopy. Set by obj_symbol_remove or cascaded
    397    * by obj_sweep_dead when this symbol is defined in a removed section.
    398    * The UNDEF-prune predicate (was: !referenced && SK_UNDEF && global/weak)
    399    * is also folded into the sweep, so emit-time symbol loops only need to
    400    * check `removed`. */
    401   u8 removed;
    402   /* This symbol names an address subordinate to the preceding content unit
    403    * rather than starting a separately collectible/reorderable atom. Mach-O
    404    * writes this semantic as N_ALT_ENTRY; other formats may ignore it. */
    405   u8 atom_subordinate;
    406 } ObjSym;
    407 
    408 typedef struct ObjGroup {
    409   Sym name;
    410   ObjSymId signature;
    411   ObjSecId* sections;
    412   u32 nsections;
    413   u32 flags;
    414   /* Tombstone — set by obj_group_remove, or cascaded by obj_sweep_dead
    415    * when every member section has been removed (or the signature symbol
    416    * has been removed). */
    417   u8 removed;
    418 } ObjGroup;
    419 
    420 typedef struct ObjAtom {
    421   ObjSecId section_id;
    422   u32 offset;
    423   u32 size;
    424   ObjSymId signature;
    425   u32 flags;
    426   u8 removed;
    427 } ObjAtom;
    428 
    429 /* The single concrete in-memory object representation.
    430  * Written by MCEmitter/CGTarget (during compile) or by an .o reader (during
    431  * link). Read by file emitters, the linker (file and JIT), and objdump.
    432  *
    433  * Invariant: post-finalize state is identical in shape to what an .o reader
    434  * would produce from a written-out object — so consumers don't care which
    435  * path produced it.
    436  *
    437  * Lifecycle gates:
    438  *   1. MCEmitter/CGTarget (or a .o reader) issues writes.
    439  *   2. cgtarget_finalize must be called before any debug_emit or read access on
    440  *      the builder. At -O2 it flushes lowered code into sections.
    441  *   3. debug_emit (if -g) writes .debug_* sections.
    442  *   4. obj_finalize closes the builder: computes flat section offsets, applies
    443  *      pending fixups within sections, and freezes the read-side view.
    444  *      No further writes are permitted afterward.
    445  *   5. File emitters and the linker consume via the read API.
    446  *
    447  * The handle type itself is the public KitObjBuilder, aliased to ObjBuilder
    448  * inside libkit (see src/core/core.h). */
    449 
    450 ObjBuilder* obj_new(Compiler*);
    451 void obj_free(ObjBuilder*);
    452 
    453 /* The owning Compiler; needed by consumers (e.g. kit_disasm_iter_new)
    454  * that take a bare ObjBuilder and still must pool_str() symbol names
    455  * against the right pool. */
    456 Compiler* obj_compiler(const ObjBuilder*);
    457 
    458 /* Pre-size the symbol-name index for `n` incoming symbols (object readers know
    459  * the count from the symtab header). Skips the resize cascade when ingesting a
    460  * symbol-heavy object. No-op if already large enough; order-preserving. */
    461 void obj_reserve_symbols(ObjBuilder*, u32 n);
    462 
    463 /* ---- write side (MCEmitter/CGTarget and .o readers) ---- */
    464 ObjSecId obj_section(ObjBuilder*, Sym name, SecKind, u16 flags, u32 align);
    465 ObjSecId obj_section_ex(ObjBuilder*, Sym name, SecKind, SecSem, u16 flags,
    466                         u32 align, u32 entsize, u32 link, u32 info);
    467 void obj_section_set_flags(ObjBuilder*, ObjSecId, u16 flags);
    468 void obj_section_set_entsize(ObjBuilder*, ObjSecId, u32 entsize);
    469 void obj_section_set_align(ObjBuilder*, ObjSecId, u32 align);
    470 void obj_section_set_group(ObjBuilder*, ObjSecId, ObjGroupId);
    471 void obj_section_set_link_info(ObjBuilder*, ObjSecId, ObjSecId link, u32 info);
    472 void obj_section_set_addr(ObjBuilder*, ObjSecId, u64 addr);
    473 /* Set format-specific raw sh_type/sh_flags overrides (see Section.ext_type
    474  * comment).  Zero ext_type means "no override". */
    475 void obj_section_set_ext(ObjBuilder*, ObjSecId, ObjExtKind, u32 ext_type,
    476                          u32 ext_flags);
    477 void obj_write(ObjBuilder*, ObjSecId section_id, const void* data, size_t n);
    478 /* Resolve a section's byte buffer for direct emit. Returns NULL for the
    479  * OBJ_SEC_NONE sentinel, an unknown id, or a NOBITS/.bss section (which stores
    480  * only a size, not bytes — callers must route those through obj_write so the
    481  * bss_size accounting runs). The returned pointer is stable: SegVec elements do
    482  * not move, so callers may cache it until the next set_section. */
    483 Buf* obj_section_bytes(ObjBuilder*, ObjSecId section_id);
    484 u8* obj_reserve(ObjBuilder*, ObjSecId section_id, size_t n);
    485 void obj_reserve_bss(ObjBuilder*, ObjSecId section_id, u32 size, u32 align);
    486 /* Pad `section_id` to `align`, returning the resulting offset.  For
    487  * PROGBITS sections this writes zero bytes; for NOBITS it bumps
    488  * bss_size.  Callers that share a section across multiple symbols use
    489  * this to ensure each placement starts at the symbol's required
    490  * alignment, since dedup of obj_section means a placement isn't
    491  * automatically aligned just because the section's own align is set. */
    492 u32 obj_align_to(ObjBuilder*, ObjSecId section_id, u32 align);
    493 u32 obj_pos(ObjBuilder*, ObjSecId section_id);
    494 void obj_patch(ObjBuilder*, ObjSecId section_id, u32 ofs, const void* data,
    495                size_t n);
    496 
    497 ObjSymId obj_symbol(ObjBuilder*, Sym name, SymBind, SymKind,
    498                     ObjSecId section_id, u64 value, u64 size);
    499 ObjSymId obj_symbol_ex(ObjBuilder*, Sym name, SymBind, SymVis, SymKind,
    500                        ObjSecId section_id, u64 value, u64 size,
    501                        u64 common_align);
    502 /* Allocate a stable symbol id for data that may be discarded before emission.
    503  * The returned symbol is tombstoned and not entered in the name index; callers
    504  * must publish it with obj_symbol_define_live if the data is actually emitted.
    505  */
    506 ObjSymId obj_symbol_defer(ObjBuilder*, Sym name, SymBind, SymVis, SymKind,
    507                           u64 size);
    508 ObjSymId obj_symbol_find(ObjBuilder*, Sym name);
    509 /* obj_symbol_ex creates a symbol; obj_symbol_define fills in the
    510  * (section_id, value, size) fields of an already-created symbol. The pair
    511  * supports forward references: an undefined ObjSymId is created when first
    512  * needed for a relocation, and defined later when its definition is emitted. */
    513 void obj_symbol_define(ObjBuilder*, ObjSymId, ObjSecId section_id, u64 value,
    514                        u64 size);
    515 void obj_symbol_define_live(ObjBuilder*, ObjSymId, ObjSecId section_id,
    516                             u64 value, u64 size);
    517 
    518 void obj_reloc(ObjBuilder*, ObjSecId section_id, u32 offset, RelocKind,
    519                ObjSymId sym, i64 addend);
    520 void obj_reloc_ex(ObjBuilder*, ObjSecId section_id, u32 offset, RelocKind,
    521                   ObjSymId sym, i64 addend, int explicit_addend, int pair);
    522 
    523 /* Force ObjSym::referenced = 1 on the named symbol. obj_reloc_ex calls this
    524  * automatically; the readers (elf_read / macho_read) call it on every
    525  * ingested symbol so a roundtrip preserves UNDEFs that another tool
    526  * emitted into the input. */
    527 void obj_sym_mark_referenced(ObjBuilder*, ObjSymId);
    528 void obj_sym_set_referenced(ObjBuilder*, ObjSymId, int referenced);
    529 
    530 ObjAtomId obj_atom_define(ObjBuilder*, ObjSecId section_id, u32 offset,
    531                           u32 size, ObjSymId signature, u32 flags);
    532 
    533 ObjGroupId obj_group(ObjBuilder*, Sym name, ObjSymId signature, u32 flags);
    534 void obj_group_add_section(ObjBuilder*, ObjGroupId group_id,
    535                            ObjSecId section_id);
    536 
    537 void obj_finalize(ObjBuilder*);
    538 
    539 /* ---- post-finalize mutators (strip / objcopy support) ----
    540  *
    541  * Mutators flip per-entry fields and / or `removed` tombstones. Cascading
    542  * cleanup (drop relocs against removed sections, etc.) is deferred to
    543  * obj_sweep_dead, which the emitters call automatically. Mutators are
    544  * cheap individual field writes; they do not re-index or compact storage,
    545  * so ObjSecId / ObjSymId / ObjGroupId remain stable.
    546  *
    547  * No-ops when given OBJ_SEC_NONE / OBJ_SYM_NONE / OBJ_GROUP_NONE, and
    548  * silently ignore ids that are out of range or already removed (the
    549  * driver tools call these in bulk and benefit from idempotency). */
    550 void obj_section_remove(ObjBuilder*, ObjSecId);
    551 void obj_symbol_remove(ObjBuilder*, ObjSymId);
    552 void obj_group_remove(ObjBuilder*, ObjGroupId);
    553 void obj_section_rename(ObjBuilder*, ObjSecId, Sym new_name);
    554 void obj_symbol_rename(ObjBuilder*, ObjSymId, Sym new_name);
    555 void obj_symbol_set_bind(ObjBuilder*, ObjSymId, SymBind);
    556 void obj_symbol_set_vis(ObjBuilder*, ObjSymId, SymVis);
    557 /* Replace `section_id`'s contents wholesale with `n` bytes from `data`.
    558  * Resets bss_size (so a former NOBITS section gains real bytes) and
    559  * preserves the section's other attributes (name, kind, flags, align).
    560  * Existing relocations against the section are kept — caller is
    561  * responsible for issuing obj_symbol_remove on any defined symbols whose
    562  * (value, size) no longer fits, etc. */
    563 void obj_section_replace_bytes(ObjBuilder*, ObjSecId, const u8* data, size_t n);
    564 
    565 /* Tombstone-driven consistency sweep. Called by each file-format emitter
    566  * at the top of emit; consumers that walk a builder by raw section/symbol/
    567  * reloc/group ID after sweep must respect the `removed` bit on each entry.
    568  *
    569  * Does the following passes:
    570  *   1. Cascade: any symbol defined in a removed section becomes removed.
    571  *   2. UNDEF prune: any non-referenced SK_UNDEF global/weak becomes removed
    572  *      (folds the historical "spurious extern from a header" filter).
    573  *   3. Reloc cleanup: any reloc whose containing section, defining section,
    574  *      or target symbol is removed becomes removed.
    575  *   4. Group compaction: each group's section list is filtered in place to
    576  *      drop removed members; a group whose list empties out (or whose
    577  *      signature symbol has been removed) is itself marked removed.
    578  *   5. Section link cleanup: Section.link cleared if it points at a
    579  *      removed section.
    580  *
    581  * Idempotent — safe to call multiple times. On a never-mutated builder
    582  * only pass 2 has any effect. */
    583 void obj_sweep_dead(ObjBuilder*);
    584 
    585 /* Format-specific ELF e_flags (per-arch ABI bits, e.g. EF_RISCV_RVC |
    586  * EF_RISCV_FLOAT_ABI_DOUBLE on RV64). Set by read_elf during input
    587  * parsing; consumed by emit_elf for round-trip. The setter records
    588  * a presence bit so emit_elf can distinguish "preserve from input"
    589  * from "no input — synthesize per-arch default". */
    590 void obj_set_elf_e_flags(ObjBuilder*, u32 e_flags);
    591 int obj_get_elf_e_flags(const ObjBuilder*, u32* out);
    592 
    593 /* COFF short-import shim annotation. Set by read_coff when the input
    594  * is a Microsoft "short import" record (Sig1=0, Sig2=0xFFFF) found
    595  * inside a .lib archive member: the ObjBuilder synthesizes the
    596  * imported symbol(s) the long-form import object would have provided,
    597  * and stores the providing DLL name here so the archive-ingestion
    598  * layer (Phase 4.3) can reclassify the resulting LinkInput as a
    599  * DSO with this name as the soname. Unset (returns 0 from the
    600  * getter) on every other input. The setter records a presence bit
    601  * the same way obj_set_elf_e_flags does. */
    602 void obj_set_coff_import_dll(ObjBuilder*, Sym dll_name);
    603 int obj_get_coff_import_dll(const ObjBuilder*, Sym* out);
    604 /* COFF short-import IMPORT NAME override: the name the loader resolves in the
    605  * DLL when the short-import NameType makes it differ from the local symbol
    606  * name (NOPREFIX/UNDECORATE strip decoration; EXPORTAS carries an explicit
    607  * export name). Set by read_coff_short_import; consumed by the COFF
    608  * import-table synthesis for the PE hint/name-table entry. The local symbol
    609  * keeps its own name so kit's references still resolve. Unset on inputs whose
    610  * import name equals the symbol name. */
    611 void obj_set_coff_import_name(ObjBuilder*, Sym import_name);
    612 int obj_get_coff_import_name(const ObjBuilder*, Sym* out);
    613 
    614 /* COFF WEAK_EXTERNAL alias: symbol `sym` is an alias for the symbol named
    615  * `target` (the aux record's fall-back/default symbol). Recorded by read_coff
    616  * for genuine alias declarations (IMAGE_WEAK_EXTERN_SEARCH_ALIAS) so the linker
    617  * can resolve the weak symbol to its target by name — e.g. mingw x86_64's
    618  * `_setjmp` aliasing `__intrinsic_setjmp`, a redirection the single-underscore
    619  * naming heuristic can't derive. The getter returns 0 when `sym` has no
    620  * recorded alias (the common case). See src/link/link_resolve.c. */
    621 void obj_set_weak_alias(ObjBuilder*, ObjSymId sym, Sym target);
    622 Sym obj_get_weak_alias(const ObjBuilder*, ObjSymId sym);
    623 /* Enumerate the recorded weak-external aliases (for building a cross-input
    624  * name->target map at link time). Count is 0 on inputs that carry none. */
    625 u32 obj_weak_alias_count(const ObjBuilder*);
    626 int obj_weak_alias_at(const ObjBuilder*, u32 i, ObjSymId* sym_out,
    627                       Sym* target_out);
    628 
    629 /* Per-symbol format-specific flag bits.  ObjSym.flags is otherwise
    630  * unused; readers stash format-specific attribute bits there so the
    631  * matching emitter can re-apply them.  Today this is Mach-O n_desc
    632  * pass-through (N_NO_DEAD_STRIP, etc.) — bits the canonical
    633  * ObjSym.bind/vis/kind triple doesn't model.  ELF callers are free
    634  * to use the same field for their own pass-through; the contract is
    635  * "bits go in / same bits come out", not a shared semantic. */
    636 void obj_symbol_set_flags(ObjBuilder*, ObjSymId, u16 flags);
    637 void obj_symbol_set_atom_subordinate(ObjBuilder*, ObjSymId, int subordinate);
    638 
    639 /* ---- read side (linker, file emitters, objdump) ---- */
    640 u32 obj_section_count(const ObjBuilder*);
    641 const Section* obj_section_get(const ObjBuilder*, ObjSecId id);
    642 u32 obj_reloc_count(const ObjBuilder*, ObjSecId section_id);
    643 u32 obj_reloc_total(const ObjBuilder*);
    644 const Reloc* obj_reloc_at(const ObjBuilder*, u32 idx); /* 0..total-1 */
    645 /* The global indices of section_id's live relocs, ascending (the order
    646  * obj_reloc_at expects), via a cached per-section index — O(1) lookup instead
    647  * of rescanning the flat table. *out_len gets the count (may be 0 -> NULL). */
    648 const u32* obj_reloc_section(const ObjBuilder*, ObjSecId section_id,
    649                              u32* out_len);
    650 
    651 /* Diagnostic spelling for a RelocKind. The returned pointer is a static
    652  * literal that mirrors the enum identifier without the R_ prefix (e.g.
    653  * R_RV_CALL -> "RV_CALL", R_AARCH64_CALL26 -> "AARCH64_CALL26"). NULL is
    654  * never returned; unknown kinds collapse to "UNKNOWN". */
    655 const char* reloc_kind_name(RelocKind);
    656 const ObjSym* obj_symbol_get(const ObjBuilder*, ObjSymId);
    657 u32 obj_atom_count(const ObjBuilder*);
    658 const ObjAtom* obj_atom_get(const ObjBuilder*, ObjAtomId);
    659 int obj_section_has_atoms(const ObjBuilder*, ObjSecId);
    660 ObjAtomId obj_atom_find(const ObjBuilder*, ObjSecId section_id, u32 offset);
    661 ObjAtomId obj_atom_find_symbol(const ObjBuilder*, ObjSymId);
    662 u32 obj_group_count(const ObjBuilder*);
    663 const ObjGroup* obj_group_get(const ObjBuilder*, ObjGroupId id);
    664 
    665 /* Symbol iteration: ObjSymId is scoped to this builder, but callers should not
    666  * assume dense contiguous ids or direct indexing. The builder may store symbols
    667  * in segments internally; use the cursor.
    668  *
    669  * The iterator is raw — it visits every symbol slot including those whose
    670  * `removed` tombstone is set. Callers that want post-sweep semantics must
    671  * check ObjSym::removed themselves. (Consistent with Section.removed and
    672  * Reloc.removed: tombstones live as a per-entry field, not behind the
    673  * iterator.) */
    674 typedef struct ObjSymIter ObjSymIter;
    675 typedef struct ObjSymEntry {
    676   ObjSymId id;
    677   const ObjSym* sym;
    678 } ObjSymEntry;
    679 ObjSymIter* obj_symiter_new(const ObjBuilder*);
    680 int obj_symiter_next(ObjSymIter*, ObjSymEntry* out); /* returns 0 at end */
    681 void obj_symiter_free(ObjSymIter*);
    682 
    683 /* Group iteration: peer of obj_symiter for groups (COMDAT and friends).
    684  * Same segmented-storage caveat — use the cursor, don't index directly.
    685  * Like obj_symiter, this is raw: tombstoned groups are still returned;
    686  * callers consult ObjGroup::removed. */
    687 typedef struct ObjGroupIter ObjGroupIter;
    688 typedef struct ObjGroupEntry {
    689   ObjGroupId id;
    690   const ObjGroup* group;
    691 } ObjGroupEntry;
    692 ObjGroupIter* obj_groupiter_new(const ObjBuilder*);
    693 int obj_groupiter_next(ObjGroupIter*, ObjGroupEntry* out); /* 0 at end */
    694 void obj_groupiter_free(ObjGroupIter*);
    695 
    696 /* Writer is the public KitWriter type aliased to Writer inside libkit
    697  * (see src/core/core.h). The streaming API lives in <kit/core.h> as
    698  * kit_writer_*. */
    699 
    700 /* ---- format-aware canonical section names ----
    701  *
    702  * For sections the linker synthesizes (init/fini arrays, TLS template
    703  * sections), the spelling diverges across object formats: ELF uses
    704  * `.init_array` / `.tdata` / etc., Mach-O uses
    705  * `__DATA,__mod_init_func` / `__DATA,__thread_data` / etc.  These
    706  * helpers pick the right name for the active target.obj so the linker
    707  * doesn't carry per-format switches at every synthesis site.  ELF
    708  * returns the historical names; Mach-O / COFF panic until those
    709  * writers land. */
    710 Sym obj_secname_init_array(Compiler*);
    711 Sym obj_secname_fini_array(Compiler*);
    712 Sym obj_secname_preinit_array(Compiler*);
    713 Sym obj_secname_tdata(Compiler*);
    714 Sym obj_secname_tbss(Compiler*);
    715 
    716 /* DWARF debug-section name translation for Mach-O.
    717  *
    718  * kit carries DWARF sections under their ELF spelling (".debug_info")
    719  * internally; on Mach-O they live in the __DWARF segment with "__"-
    720  * prefixed section names ("__debug_info").  The transform drops the
    721  * leading '.', prepends "__", and truncates to Mach-O's 16-byte
    722  * `sectname` field — which reproduces the names Apple's toolchain uses
    723  * (e.g. ".debug_str_offsets" -> "__debug_str_offs").
    724  *
    725  * Writes the bare Mach-O section name (NUL-terminated, <=16 chars) into
    726  * `out` (>=17 bytes) and returns 1 when (`name`,`len`) is a ".debug_*"
    727  * section; returns 0 otherwise, leaving `out` untouched.  Shared by the
    728  * Mach-O writer (emit) and the DWARF reader (section lookup) so the two
    729  * agree on the truncated spelling. */
    730 int obj_macho_debug_sectname(const char* name, size_t len, char out[17]);
    731 
    732 /* Canonical Mach-O "segname,sectname" spelling for a SecKind, as a
    733  * NUL-terminated literal.  The single source of truth shared by the Mach-O
    734  * object writer (name_to_seg_sect) and the `cc -S` printer (asm_emit.c), so
    735  * the textual `.section` directive and the binary section header never drift:
    736  *   SEC_RODATA -> "__TEXT,__const", SEC_DATA -> "__DATA,__data",
    737  *   SEC_BSS -> "__DATA,__bss", SEC_TEXT -> "__TEXT,__text".
    738  * Returns NULL for kinds with no fixed canonical Mach-O home (SEC_OTHER /
    739  * SEC_DEBUG), which callers spell from the section's own name. */
    740 const char* obj_macho_canon_secname(SecKind kind);
    741 
    742 /* Inverse of obj_macho_canon_secname: classify a Mach-O native
    743  * "segname,sectname" spelling (e.g. "__TEXT,__text", "__DATA,__bss")
    744  * into a SecKind.  Used by a format-neutral reader / objdump path that
    745  * holds the on-disk Mach-O section name and wants the canonical kit
    746  * SecKind without re-deriving the per-segment rules at every call.
    747  * `name` / `len` are the comma-joined spelling.  Returns 1 and writes
    748  * *kind on a recognized spelling; returns 0 (leaving *kind untouched)
    749  * for an unrecognized name (caller treats as SEC_OTHER). */
    750 int obj_macho_seckind_for_secname(const char* name, size_t len, SecKind* kind);
    751 
    752 /* Translate a kit-internal (ELF-spelled) section name to its Mach-O
    753  * native spelling.  Generalizes obj_macho_debug_sectname: handles the
    754  * ".debug_*" -> "__DWARF,__debug_*" DWARF case and ".eh_frame" ->
    755  * "__TEXT,__eh_frame".  Writes the comma-joined "segname,sectname"
    756  * (NUL-terminated) into `out` (>= 40 bytes covers seg(16)+','+sect(16)+
    757  * NUL) and returns 1 when `name` is one of the recognized
    758  * format-divergent sections; returns 0 (leaving `out` untouched)
    759  * otherwise, so the caller falls back to its own spelling. */
    760 int obj_macho_native_secname(const char* name, size_t len, char out[40]);
    761 
    762 /* ---- thread-local storage emission ---------------------------------
    763  *
    764  * The frontend collects a `_Thread_local` definition's bytes (or marks
    765  * it BSS), alignment, and any pointer-init relocs, then calls
    766  * obj_define_tls to materialize the storage and bind the user-visible
    767  * symbol.  The obj layer owns the format split:
    768  *
    769  *   ELF   : `sym` is defined directly in `.tdata` / `.tbss`; the
    770  *           supplied relocs are applied at the same section/offset.
    771  *
    772  *   Mach-O: the data lives under a private `<name>$tlv$init` symbol in
    773  *           `__DATA,__thread_data` / `__DATA,__thread_bss`; `sym` is
    774  *           defined onto a 24-byte TLV *descriptor* in
    775  *           `__DATA,__thread_vars` whose three slots are
    776  *           [_tlv_bootstrap, 0, &init].  dyld rewrites slot[0] to a
    777  *           per-descriptor thunk and fills slot[1] with a pthread_key
    778  *           during image-load; the compiler's TLVP_LOAD_PAGE21 /
    779  *           PAGEOFF12 codegen sequence targets the descriptor.
    780  *
    781  * The `_tlv_bootstrap` undef extern is cached on the ObjBuilder so a
    782  * second TLV var in the same TU shares one symbol entry. */
    783 typedef struct ObjTlsReloc {
    784   u32 offset; /* within the data buffer */
    785   RelocKind kind;
    786   ObjSymId target;
    787   i64 addend;
    788 } ObjTlsReloc;
    789 
    790 void obj_define_tls(Compiler*, ObjBuilder*, ObjSymId sym, const u8* data,
    791                     u32 size, int has_nonzero_init, u32 align,
    792                     const ObjTlsReloc* relocs, u32 nrelocs);
    793 
    794 /* True when reads of `_Thread_local` storage go through a per-variable
    795  * descriptor + thunk call rather than a direct TP-relative offset.
    796  * Mach-O: yes (TLVP_LOAD_PAGE21 + thunk in descriptor[0]).
    797  * ELF: no (Local-Exec / Initial-Exec: `mrs tpidr_el0` + tprel offset). */
    798 int obj_format_tls_via_descriptor(const Compiler*);
    799 
    800 /* ---- format-aware codegen policy ----
    801  *
    802  * Backends consult these predicates instead of branching on
    803  * target.os / target.obj directly, so the OS/format knowledge stays
    804  * concentrated in src/obj/ and a future format lands as one case here
    805  * rather than fan-out in every CGTarget. */
    806 
    807 /* True when references to undefined external symbols must be
    808  * materialized via an indirection slot (GOT / non-lazy pointer)
    809  * rather than direct page+offset addressing. Mach-O: yes — dyld
    810  * binds dylib imports through __DATA,__got at runtime, and the
    811  * direct PAGE21/PAGEOFF12 fixups can't carry that binding. ELF
    812  * static link: no — the linker resolves SK_UNDEFs at link time and
    813  * patches the direct ADRP/ADD bytes in place. */
    814 int obj_format_extern_via_got(const Compiler*);
    815 
    816 /* True when `sym` must be reached via the GOT at the current site: the
    817  * format binds extern data through indirection
    818  * (obj_format_extern_via_got) AND the symbol is undefined in this
    819  * object (section_id == OBJ_SEC_NONE). Pure format/symbol policy with
    820  * no per-arch behavior — shared by every backend that emits GOT loads. */
    821 int obj_symbol_extern_via_got(const Compiler*, ObjBuilder*, ObjSymId);
    822 int obj_format_split_sections_as_atoms(const Compiler*);
    823 
    824 /* Apply the active object format's C-symbol mangling to `name` (a
    825  * NUL-terminated C string) and return the result interned in
    826  * `c->global`.  Mach-O prepends a single `_`; ELF / COFF / Wasm intern
    827  * verbatim.  Mirrors the on-disk policy that decl.c / cc.c emit, so
    828  * link-time and JIT-time lookups by source-level name find the symbol
    829  * regardless of target.  Mach-O temp buffer is allocated from
    830  * `c->ctx->heap`. */
    831 Sym obj_format_c_mangle(Compiler*, const char* name);
    832 
    833 /* Inverse of obj_format_c_mangle for diagnostic display: if `*name`
    834  * carries the active format's leading C-mangle byte, advance the
    835  * pointer past it and decrement `*len`.  No-op for formats with no
    836  * prefix.  Lets diagnostics print the source-level symbol name across
    837  * targets. */
    838 void obj_format_demangle_c(const Compiler*, const char** name, size_t* len);
    839 
    840 /* Default entry symbol name for a freshly created Linker on the active
    841  * object format: `_main` for Mach-O (LC_MAIN names main, dyld owns
    842  * startup), `_start` for ELF / COFF / Wasm (set by crt1.o).  Returned
    843  * as a NUL-terminated literal; the caller interns. */
    844 const char* obj_format_default_entry_name(const Compiler*);
    845 
    846 /* C source-level symbol prefix the active object format prepends on disk:
    847  * "_" for Mach-O, "" for ELF / COFF / Wasm.  The single source of truth
    848  * read by obj_format_c_mangle / obj_format_demangle_c; never NULL (a
    849  * format with no prefix returns ""). */
    850 const char* obj_format_c_label_prefix(const Compiler*);
    851 
    852 /* ---- thread-local storage model ----
    853  *
    854  * How compiled code reaches a `_Thread_local` on a given (format, OS):
    855  *   OBJ_TLS_ELF_LE          : direct TP-relative offset (ELF Local-Exec /
    856  *                             Initial-Exec): `mrs tpidr_el0` + tprel.
    857  *   OBJ_TLS_MACHO_DESCRIPTOR: per-variable descriptor + thunk call; the
    858  *                             TLVP reloc pair targets the descriptor.
    859  *   OBJ_TLS_WINDOWS_TEB     : Windows TEB-based access (SECREL into the
    860  *                             per-thread TLS block via the TEB). */
    861 typedef enum ObjTlsModel {
    862   OBJ_TLS_ELF_LE = 0,
    863   OBJ_TLS_MACHO_DESCRIPTOR = 1,
    864   OBJ_TLS_WINDOWS_TEB = 2,
    865 } ObjTlsModel;
    866 
    867 /* Returns how compiled code reaches a `_Thread_local` on the active
    868  * (format, OS): OBJ_TLS_WINDOWS_TEB for COFF, OBJ_TLS_MACHO_DESCRIPTOR
    869  * for Mach-O, OBJ_TLS_ELF_LE otherwise.  The single source of truth for
    870  * the TLS-access decision; obj_format_tls_via_descriptor is now a thin
    871  * wrapper over (model == OBJ_TLS_MACHO_DESCRIPTOR). */
    872 ObjTlsModel obj_format_tls_model(const Compiler*);
    873 
    874 /* In-process JIT: true when a reference to symbol `name` is dropped because the
    875  * format's TLS access idiom that materializes it is relaxed to in-image
    876  * addressing (COFF Windows `_tls_index`; none elsewhere). Beside
    877  * obj_format_tls_model as the TLS-mechanism authority. */
    878 int obj_format_jit_drops_symbol_ref(const Compiler*, Sym name);
    879 
    880 /* In-process JIT: true when an *undefined* reference to `name` is satisfied
    881  * internally by the JIT image and so needs no external definition: Mach-O
    882  * `__tlv_bootstrap` (descriptor slot[0] rewritten to the JIT thunk) and COFF
    883  * `_tls_index` (TLS access relaxed to in-image addressing). The single arbiter
    884  * for every JIT undef-accept site, keeping src/link free of pseudo-symbol
    885  * names. Broader than obj_format_jit_drops_symbol_ref, which gates reloc
    886  * dropping and covers only `_tls_index`. */
    887 int obj_format_jit_undef_internal(const Compiler*, Sym name);
    888 
    889 /* True when the active object format carries DWARF debug sections
    890  * file-only (not mapped into a loadable segment): ELF / Mach-O yes,
    891  * COFF no. */
    892 int obj_format_carries_file_only_debug(const Compiler*);
    893 
    894 /* True when the active object format builds its own static GOT /
    895  * non-lazy-pointer table at link time even for a static image:
    896  * Mach-O yes, else no. */
    897 int obj_format_builds_own_static_got(const Compiler*);
    898 
    899 /* True when the active object format can represent a KitCgSymFeat
    900  * `symfeat`.  Today this is the TLS-model axis: ELF / Mach-O can
    901  * represent every modeled TLS feature, COFF cannot (Windows TEB TLS
    902  * uses a different mechanism).  Non-TLS features return 1 for every
    903  * format.  `symfeat` is a KitCgSymFeat value (cast to int at the
    904  * boundary). */
    905 int obj_format_supports_symbol_feature(const Compiler*, int symfeat);
    906 
    907 /* True when the active object format pulls an archive member to satisfy a
    908  * *weak* undefined reference (PE/COFF COMDAT semantics).  COFF yes,
    909  * ELF / Mach-O no (they pull only for strong undefs). */
    910 int obj_format_weak_undef_pulls_archive_member(const Compiler*);
    911 
    912 /* True when the active object format resolves archive libraries as a global
    913  * fixed point rather than by strictly positional POSIX order. COFF yes,
    914  * ELF / Mach-O / Wasm no. */
    915 int obj_format_global_archive_fixpoint(const Compiler*);
    916 
    917 /* True when the active object format recovers weak-external / undefined
    918  * references via the mingw single-underscore alias convention (e.g.
    919  * `__set_app_type` <-> `_set_app_type`) during link symbol resolution.
    920  * COFF yes, ELF / Mach-O / Wasm no. */
    921 int obj_format_weak_extern_underscore_alias(const Compiler*);
    922 
    923 /* True when static-IFUNC resolution on the active target goes through a
    924  * `[__rela_iplt_start, __rela_iplt_end)` table of R_*_IRELATIVE relocs
    925  * (walked by FreeBSD's crt before main) rather than kit's ctor-based
    926  * __kit_ifunc_init path.  The one place the (os == FREEBSD && obj == ELF)
    927  * knowledge lives. */
    928 int obj_format_static_ifunc_via_rela_iplt(const Compiler*);
    929 
    930 /* The R_*_IRELATIVE resolver reloc wire type for the active target's
    931  * __rela_iplt table (paired with the predicate above), resolved through the
    932  * target object format so the generic iplt pass names no format literal.
    933  * Returns 0 when the format has no such reloc. */
    934 u32 obj_format_static_ifunc_irelative_type(const Compiler*);
    935 
    936 /* Format boundary-symbol classifier.  Asks the active object format
    937  * whether `name` is a symbol the format itself owns as a boundary /
    938  * synthetic global, and if so what SymKind it carries.  Returns 1 and
    939  * writes *symkind (a SymKind value) when the format owns `name`
    940  * (PE `__ImageBase` / `_tls_used` -> SK_ABS); returns 0 otherwise,
    941  * leaving *symkind untouched.  Lets generic link code classify boundary
    942  * symbols without a per-format switch. */
    943 int obj_format_boundary_sym_kind(const Compiler*, KitSlice name, int* symkind);
    944 
    945 /* Invoke the active object format's synthetic-input hook (if any) before
    946  * symbol resolution.  No-op for formats with no synthetic inputs.  The
    947  * hook builds and appends a synthetic LinkInput via Linker internals, so
    948  * it takes the Linker; declared here as the obj-side dispatch point.
    949  * (The COFF body is wired by T-LINK — see registry.c synth_inputs note.) */
    950 void obj_format_synth_inputs(const Compiler*, Linker*);
    951 
    952 /* ---- format-specific extension payload ----
    953  *
    954  * Generic object tables stay format-neutral. Format-specific module-level
    955  * metadata (today: only the in-progress Wasm module model) hangs off the
    956  * builder under an ObjExtKind tag. One payload per kind. ObjBuilder owns the
    957  * pointer's lifetime — obj_free invokes the registered free function. */
    958 typedef void (*ObjExtFreeFn)(Compiler*, void*);
    959 void obj_ext_set(ObjBuilder*, ObjExtKind, void* payload, ObjExtFreeFn);
    960 void* obj_ext_get(const ObjBuilder*, ObjExtKind);
    961 void obj_ext_clear(ObjBuilder*, ObjExtKind);
    962 
    963 /* ============================================================
    964  * Linked-image view (executables / shared objects)
    965  *
    966  * Relocatable inputs (ET_REL / MH_OBJECT / COFF .obj) have no image:
    967  * obj_image() returns NULL. The ET_EXEC / ET_DYN (and Mach-O / PE peer)
    968  * readers attach an ObjImage carrying the segment + dynamic view that the
    969  * section / symbol tables don't model. The section and symbol tables stay
    970  * populated where the format still carries them; the image is the extra
    971  * dimension. The builder owns the image; obj_free releases it.
    972  * ============================================================ */
    973 
    974 typedef enum ObjKind {
    975   OBJ_KIND_REL,  /* relocatable object — no image */
    976   OBJ_KIND_EXEC, /* executable */
    977   OBJ_KIND_DYN,  /* shared object / dylib / DLL */
    978   OBJ_KIND_CORE, /* core dump — detected, not parsed (reserved) */
    979 } ObjKind;
    980 
    981 enum { /* ObjSegment.perms bits */
    982        OBJ_SEG_X = 1u << 0,
    983        OBJ_SEG_W = 1u << 1,
    984        OBJ_SEG_R = 1u << 2
    985 };
    986 
    987 typedef struct ObjSegment {
    988   Sym name;      /* PT_* spelling / Mach-O segname, or 0 */
    989   u64 vaddr;     /* virtual address */
    990   u64 paddr;     /* physical/load address where present; else vaddr */
    991   u64 vsize;     /* size in memory */
    992   u64 file_off;  /* offset of segment contents in the file */
    993   u64 file_size; /* size on disk (< vsize when the segment carries bss) */
    994   u32 perms;     /* OBJ_SEG_R | _W | _X */
    995   u32 align;     /* power of two; 1 if none */
    996 } ObjSegment;
    997 
    998 typedef struct ObjImageDep {
    999   Sym name;           /* DT_NEEDED / imported DLL / dylib install-name */
   1000   const Sym* imports; /* imported symbol names (PE/Mach-O); NULL for ELF */
   1001   u32 nimports;
   1002 } ObjImageDep;
   1003 
   1004 /* Dynamic-table symbol. Distinct from the .symtab entries in the Symbols
   1005  * table — these come from .dynsym / dyld export trie / PE export table. */
   1006 typedef struct ObjImageSym {
   1007   Sym name;
   1008   SymBind bind;
   1009   SymKind kind;
   1010   ObjSecId section; /* OBJ_SEC_NONE for undefined imports */
   1011   u64 value;
   1012   u64 size;
   1013   /* ELF symbol-version name (interned) for a DSO export. 0 when the input
   1014    * carries no versioning for this entry. `version_hidden` distinguishes
   1015    * non-default compatibility aliases such as fstat@FBSD_1.0 from default
   1016    * exports such as fstat@@FBSD_1.5. The linker uses this both to emit the
   1017    * default requirement for plain imports and to satisfy explicit
   1018    * name@VERSION imports without losing the requested version. */
   1019   Sym version;
   1020   u8 version_hidden;
   1021   u8 pad[3];
   1022 } ObjImageSym;
   1023 
   1024 /* Dynamic relocation (.rela.dyn / .rela.plt, dyld binds, PE base relocs).
   1025  * References the dynamic symbol by interned name; the sym index is implicit
   1026  * in the dynamic table and not preserved here. */
   1027 typedef struct ObjImageReloc {
   1028   ObjSecId section; /* OBJ_SEC_NONE when the file has no section table */
   1029   u64 offset;
   1030   Sym sym_name; /* 0 for symbol-less relative relocs */
   1031   i64 addend;
   1032   RelocKind kind;
   1033 } ObjImageReloc;
   1034 
   1035 /* Raw, format-specific image field that doesn't fit the neutral model.
   1036  * One flat triple list per image, in the spirit of the per-section
   1037  * kit_obj_section_format_flags escape hatch: a neutral container with
   1038  * per-format tag semantics (documented on the public KitObjImageRaw):
   1039  *   PE   : data dirs  tag=0..15 (index), value=RVA, extra=size;
   1040  *          subsystem  tag=KIT_OBJ_RAW_PE_SUBSYSTEM, value=u16;
   1041  *          dllchars   tag=KIT_OBJ_RAW_PE_DLLCHARS,  value=u16
   1042  *   ELF  : .dynamic   tag=d_tag, value=d_val, extra=0
   1043  *   Mach-O: load cmds tag=cmd,   value=file offset, extra=cmdsize */
   1044 typedef struct ObjImageRaw {
   1045   u32 tag;
   1046   u64 value;
   1047   u64 extra;
   1048 } ObjImageRaw;
   1049 
   1050 typedef struct ObjImage ObjImage; /* defined in obj.c */
   1051 
   1052 /* Accessor — NULL on relocatable inputs. */
   1053 const ObjImage* obj_image(const ObjBuilder*);
   1054 /* Lazily create (and return) the builder's image with the given kind.
   1055  * Readers call this once they know the input is EXEC/DYN. Idempotent;
   1056  * a second call updates the kind and returns the existing image. */
   1057 ObjImage* obj_image_ensure(ObjBuilder*, ObjKind);
   1058 
   1059 /* Image scalar setters (readers). */
   1060 void obj_image_set_entry(ObjImage*, u64 entry);
   1061 void obj_image_set_base(ObjImage*, u64 image_base);
   1062 void obj_image_set_interp(ObjImage*, Sym interp);
   1063 void obj_image_set_soname(ObjImage*, Sym soname);
   1064 
   1065 /* Image table appenders (readers). Each copies its argument by value into a
   1066  * builder-heap-owned vector. obj_image_add_dep additionally deep-copies the
   1067  * ObjImageDep.imports[] name array into image-heap memory, so the reader may
   1068  * pass a transient (scratch) array; the Sym values themselves must still be
   1069  * interned in the compiler's global pool. */
   1070 void obj_image_add_segment(ObjImage*, const ObjSegment*);
   1071 void obj_image_add_dep(ObjImage*, const ObjImageDep*);
   1072 void obj_image_add_rpath(ObjImage*, Sym rpath);
   1073 void obj_image_add_dynsym(ObjImage*, const ObjImageSym*);
   1074 void obj_image_add_dynreloc(ObjImage*, const ObjImageReloc*);
   1075 /* Raw format-specific image fields (see ObjImageRaw). Copied by value. */
   1076 void obj_image_add_raw(ObjImage*, const ObjImageRaw*);
   1077 /* Undefined symbol names a DSO references (interned). The linker's
   1078  * --gc-sections pass roots executable definitions of these so a shared
   1079  * library's back-references (e.g. libc.so.7 → `environ` / `__progname`)
   1080  * survive section GC. */
   1081 void obj_image_add_undef(ObjImage*, Sym name);
   1082 
   1083 /* Image read-side queries (object_file.c glue, objdump). */
   1084 ObjKind obj_image_kind(const ObjImage*);
   1085 u64 obj_image_entry(const ObjImage*);
   1086 u64 obj_image_base(const ObjImage*);
   1087 Sym obj_image_interp(const ObjImage*);
   1088 Sym obj_image_soname(const ObjImage*);
   1089 u32 obj_image_nsegments(const ObjImage*);
   1090 const ObjSegment* obj_image_segment(const ObjImage*, u32 idx);
   1091 u32 obj_image_ndeps(const ObjImage*);
   1092 const ObjImageDep* obj_image_dep(const ObjImage*, u32 idx);
   1093 u32 obj_image_nrpaths(const ObjImage*);
   1094 Sym obj_image_rpath(const ObjImage*, u32 idx);
   1095 u32 obj_image_ndynsyms(const ObjImage*);
   1096 const ObjImageSym* obj_image_dynsym(const ObjImage*, u32 idx);
   1097 u32 obj_image_ndynrelocs(const ObjImage*);
   1098 const ObjImageReloc* obj_image_dynreloc(const ObjImage*, u32 idx);
   1099 u32 obj_image_nundefs(const ObjImage*);
   1100 Sym obj_image_undef(const ObjImage*, u32 idx);
   1101 u32 obj_image_nraws(const ObjImage*);
   1102 const ObjImageRaw* obj_image_raw(const ObjImage*, u32 idx);
   1103 
   1104 /* ---- file format emitters ---- */
   1105 void emit_elf(Compiler*, ObjBuilder*, Writer*);
   1106 void emit_coff(Compiler*, ObjBuilder*, Writer*);
   1107 void emit_macho(Compiler*, ObjBuilder*, Writer*);
   1108 void emit_wasm(Compiler*, ObjBuilder*, Writer*);
   1109 
   1110 /* ---- file format readers (for ld and objdump) ---- */
   1111 ObjBuilder* read_elf(Compiler*, const char* name, const u8* data, size_t len);
   1112 /* ELF ET_DYN reader. Produces an ObjBuilder containing only the DSO's
   1113  * exported (dynsym) symbols. Defined dynsym entries land as ObjSyms
   1114  * with their original SymBind/SymKind so the linker's symbol-resolution
   1115  * pass can match them by name. The DSO's sections, relocations, and
   1116  * groups are all skipped — DSOs contribute no bytes to the output.
   1117  *
   1118  * If `soname_out` is non-NULL, *soname_out receives the DT_SONAME
   1119  * interned into the compiler's global Sym pool, or 0 if the DSO has
   1120  * no SONAME. */
   1121 ObjBuilder* read_elf_dso(Compiler*, const char* name, const u8* data,
   1122                          size_t len, Sym* soname_out);
   1123 ObjBuilder* read_coff(Compiler*, const char* name, const u8* data, size_t len);
   1124 /* PE32+ DLL reader.  Walks the IMAGE_DIRECTORY_ENTRY_EXPORT data
   1125  * directory and produces an ObjBuilder containing one defined symbol
   1126  * (OBJ_SEC_NONE, SB_GLOBAL, SK_FUNC) per name in the Export Name
   1127  * Table — the peer of read_elf_dso / read_macho_dso.  The DLL's
   1128  * own Name string (the analogue of DT_SONAME / LC_ID_DYLIB) is
   1129  * interned and returned via *soname_out, or 0 if missing.
   1130  *
   1131  * Scope: PE32+ images with IMAGE_FILE_DLL set, machine AMD64 or
   1132  * ARM64.  Ordinal-only exports (in the EAT but not the ENT) are not
   1133  * synthesized in v1 — almost all real-world imports are by name. */
   1134 ObjBuilder* read_coff_dso(Compiler*, const char* name, const u8* data,
   1135                           size_t len, Sym* soname_out);
   1136 /* PE32+ linked-image reader (peer of read_elf_image / read_macho_image).
   1137  * Handles both executables (IMAGE_FILE_DLL clear -> OBJ_KIND_EXEC) and
   1138  * DLLs (set -> OBJ_KIND_DYN), populating the neutral ObjImage: one
   1139  * segment per PE section, exports -> dynsyms + soname, imports -> deps +
   1140  * undefined dynsyms, base relocs -> RELATIVE dynrelocs, plus a full
   1141  * section/symbol view via the ObjBuilder Section table, and the raw
   1142  * data-directory / subsystem / dllchars escape-hatch entries.  Lenient:
   1143  * malformed sub-tables are skipped; truncated core headers panic.
   1144  * Dispatched from read_coff on the DOS 'MZ' magic. */
   1145 ObjBuilder* read_coff_image(Compiler*, const char* name, const u8* data,
   1146                             size_t len);
   1147 ObjBuilder* read_macho(Compiler*, const char* name, const u8* data, size_t len);
   1148 /* Mach-O MH_DYLIB reader. Produces an ObjBuilder containing only the
   1149  * dylib's exported symbols (as defined OBJ_SEC_NONE entries — the
   1150  * peer of read_elf_dso). LC_ID_DYLIB's install-name is interned and
   1151  * returned via *install_name_out (the Mach-O analogue of DT_SONAME).
   1152  *
   1153  * arm64-only for v1; other cputypes panic. */
   1154 ObjBuilder* read_macho_dso(Compiler*, const char* name, const u8* data,
   1155                            size_t len, Sym* install_name_out);
   1156 /* Apple `.tbd` (text-based stub) reader.  Parses the YAML-shaped TAPI
   1157  * format produced by Apple's SDKs (see /usr/lib/lib*.tbd in
   1158  * `xcrun --show-sdk-path`).  Extracts the umbrella install-name and the
   1159  * union of every exported / re-exported symbol whose `targets:` block
   1160  * names the active arch (e.g. arm64-macos).  Symbols are emitted into
   1161  * the ObjBuilder verbatim (they already include the leading `_` Apple
   1162  * uses for C symbols), so resolve_undefs matches them against the
   1163  * Mach-O on-disk symbol names directly.
   1164  *
   1165  * The arch string ("arm64" or "x86_64") comes from Compiler.target. */
   1166 ObjBuilder* read_tbd(Compiler*, const char* name, const u8* data, size_t len,
   1167                      Sym* install_name_out);
   1168 
   1169 /* ---- shared string-table builder (ELF / COFF / Mach-O symtab strtabs) ----
   1170  *
   1171  * Each object writer builds a string table: a leading prefix byte(s) followed
   1172  * by NUL-terminated names, with each name's byte offset recorded in its symbol
   1173  * record. Names repeat (a symbol defined and referenced; many `.rela.<sec>`
   1174  * section names), so the table dedupes identical strings — purely a size
   1175  * optimization (any valid offset to the right bytes is conformant), which is
   1176  * why the policy can be identical across all three formats.
   1177  *
   1178  * The bytes live in one contiguous, growable buffer; dedup is an open-addressed
   1179  * hash of {hash,off,len} that verifies a candidate by reading `data+off` (so it
   1180  * retains no external pointers and needs no per-add flatten). This replaced a
   1181  * per-add buf_flatten + linear substring scan that was O(n^2) in the symbol
   1182  * count -- 31% of all instructions when compiling sqlite to ELF. The dedup is
   1183  * exact-match (not the old suffix/tail-merge), so the table is marginally
   1184  * larger than binutils' where a name is a suffix of another, but still minimal
   1185  * and valid. */
   1186 typedef struct ObjStrtabEnt {
   1187   u32 hash;
   1188   u32 off;
   1189   u32 len; /* 0 marks an empty slot (len-0 strings are never stored) */
   1190 } ObjStrtabEnt;
   1191 
   1192 typedef struct ObjStrtab {
   1193   u8* data; /* contiguous table bytes (mutable: a caller may patch a prefix) */
   1194   u32 len;
   1195   u32 cap;
   1196   ObjStrtabEnt* slots; /* dedup index; NULL/empty when !dedup */
   1197   u32 scap;            /* power-of-two slot capacity */
   1198   u32 sused;
   1199   Heap* heap;
   1200   u8 dedup;
   1201 } ObjStrtab;
   1202 
   1203 void obj_strtab_init(ObjStrtab*, Heap*, int dedup);
   1204 /* Append prefix bytes that belong to the table but are never a dedup target
   1205  * (a leading NUL, a COFF 4-byte size-field placeholder). */
   1206 void obj_strtab_put_raw(ObjStrtab*, const void* bytes, u32 n);
   1207 /* Add a name; return its byte offset. With dedup an exact duplicate returns the
   1208  * prior offset (O(1) amortized). len 0 -> offset 0 (the empty string). */
   1209 u32 obj_strtab_add(ObjStrtab*, const char* s, u32 len);
   1210 u32 obj_strtab_size(const ObjStrtab*);
   1211 u8* obj_strtab_data(ObjStrtab*);
   1212 void obj_strtab_fini(ObjStrtab*);
   1213 
   1214 #endif