format.h (16899B)
1 #ifndef KIT_OBJ_FORMAT_H 2 #define KIT_OBJ_FORMAT_H 3 4 #include <kit/object.h> 5 #include <stddef.h> 6 7 #include "core/core.h" 8 9 typedef struct LinkImage LinkImage; 10 typedef struct Linker Linker; 11 typedef struct EmuLoadOptions EmuLoadOptions; 12 typedef struct EmuLoadedImage EmuLoadedImage; 13 typedef struct EmuProcess EmuProcess; 14 typedef struct EmuLoadedObject EmuLoadedObject; 15 typedef struct EmuDynNeededIter EmuDynNeededIter; 16 typedef struct EmuDynSymbol EmuDynSymbol; 17 typedef struct EmuDynRelocIter EmuDynRelocIter; 18 typedef struct EmuDynReloc EmuDynReloc; 19 typedef u32 EmuDynRelocClass; 20 typedef u32 EmuDynRelocTableKind; 21 22 typedef ObjBuilder* (*ObjFormatReadFn)(Compiler*, const char* name, 23 const u8* data, size_t len); 24 typedef ObjBuilder* (*ObjFormatReadDsoFn)(Compiler*, const char* name, 25 const u8* data, size_t len, 26 Sym* soname_out); 27 typedef void (*ObjFormatEmitFn)(Compiler*, ObjBuilder*, Writer*); 28 typedef void (*ObjFormatLinkEmitFn)(LinkImage*, Writer*); 29 typedef void (*ObjFormatLayoutDynFn)(Linker*, LinkImage*); 30 typedef void (*ObjFormatFreeDynFn)(LinkImage*); 31 typedef void (*ObjFormatMachoStubFn)(u8* dst, u64 stub_vaddr, 32 u64 got_slot_vaddr); 33 typedef void (*ObjFormatCoffStubFn)(u8* dst, u64 stub_vaddr, 34 u64 iat_slot_vaddr); 35 36 /* Resolve a build target (arch/OS/obj/endian/float-ABI) from this format's 37 * on-disk header bytes. Invoked by kit_detect_target once kit_detect_fmt has 38 * classified the leading bytes to this format. The detector lives in the 39 * format vtable so a format compiled out of the build drops its detection 40 * logic with it — no format-identity #if in the API layer. The COFF detector 41 * additionally handles PE images (the dispatcher routes KIT_BIN_PE to COFF). */ 42 typedef KitStatus (*ObjFormatDetectTargetFn)(const u8* data, size_t len, 43 KitTargetSpec* out); 44 typedef KitStatus (*ObjFormatRewriteLinkedFn)( 45 const KitContext*, KitSlice name, const KitSlice* input, 46 const KitLinkedRewriteOptions*, KitWriter* out, 47 KitLinkedRewriteReport* report_out); 48 49 /* Synthetic-input hook: invoked before symbol resolution to inject a 50 * synthetic input object (e.g. the COFF __CTOR_LIST__/__DTOR_LIST__ 51 * boundary blob). The hook receives the Linker so it can append a 52 * LinkInput; returns the freshly built ObjBuilder, or NULL when nothing 53 * needs synthesizing for the current target. Formats with no synthetic 54 * inputs leave this NULL. */ 55 typedef void (*ObjFormatSynthInputsFn)(Linker*); 56 57 typedef struct ObjElfArchOps { 58 KitArchKind arch; 59 u32 e_machine; 60 u32 e_flags; 61 const char* default_musl_interp; 62 u32 r_relative; 63 u32 r_glob_dat; 64 u32 r_jump_slot; 65 u32 r_irelative; /* R_*_IRELATIVE static-IFUNC resolver reloc (__rela_iplt). 66 */ 67 /* Variant-I TP bias: distance from the TLS image start to where `tp` 68 * points for a freestanding (kit start.c) layout. AArch64/RISC-V place 69 * a 16-byte TCB ahead of the image, so this is 16 for those arches; 0 70 * for variant-II arches (x86_64) and any arch with no TLS support. The 71 * hosted-vs-freestanding split for RISC-V is still applied by the 72 * caller in src/obj/elf/link.c; this field is the per-arch maximum. */ 73 u32 tls_tp_bias; 74 /* SHT_REL (vs SHT_RELA): 1 for arches whose ELF ABI carries relocation 75 * addends in the relocated field rather than an explicit r_addend slot. 76 * The 32-bit ARM EABI (AAELF32) mandates REL; clang/gas/GNU ld all emit 77 * and expect `.rel.<name>` with 8-byte Elf32_Rel entries. Every other 78 * arch kit targets uses RELA (0). emit.c folds the addend into the field 79 * and writes Elf32_Rel when this is set. */ 80 u8 uses_rel; 81 u32 (*reloc_to)(u32 kind); 82 u32 (*reloc_from)(u32 wire_type); 83 /* Diagnostic spelling of a per-arch ELF reloc wire type (e.g. 84 * "R_AARCH64_CALL26"). NULL means "no per-arch name table"; callers 85 * fall back to the format-neutral reloc_kind_name(). */ 86 const char* (*reloc_name)(u32 wire_type); 87 /* Decode the float ABI from this arch's ELF e_flags. RISC-V reads 88 * EF_RISCV_FLOAT_ABI_*; other arches have no float-ABI e_flags and 89 * leave this NULL (callers treat NULL as KIT_FLOAT_ABI_DEFAULT). */ 90 KitFloatAbi (*float_abi_from_e_flags)(u32 e_flags); 91 /* REL-only: reconstruct the implicit addend a relocation carries in its 92 * relocated field (Elf32_Rel has no r_addend slot). `field` points at the 93 * `width`-byte relocated location in the target section. Only set for 94 * `uses_rel` arches (ARM); the reader calls it per REL reloc so kit's own 95 * linker reads the same addend a field-reading linker (ld.lld) would. 96 * NULL or a NOBITS target -> addend 0. */ 97 i64 (*reloc_field_addend)(u32 kind, const u8* field, u32 width); 98 /* Build this arch's ELF vendor build-attributes section payload (e.g. ARM's 99 * `.ARM.attributes`, SHT_*_ATTRIBUTES). Returns a freshly allocated buffer 100 * (in `c->scratch`) of `*size_out` bytes; the emitter synthesizes the 101 * section only when this is non-NULL. NULL for arches that emit no vendor 102 * attributes (aarch64, x86-64, RISC-V, …) — replaces the former 103 * `e_machine == EM_ARM` identity gate in the ELF emitter. */ 104 const u8* (*build_attributes)(Compiler* c, u32* size_out); 105 } ObjElfArchOps; 106 107 /* Structural role of a Mach-O relocation entry. Mach-O's r_type is a 4-bit 108 * field whose values OVERLAP across architectures (e.g. value 2 is both 109 * X86_64_RELOC_BRANCH and ARM64_RELOC_BRANCH26), so the entry's meaning can 110 * only be resolved per-arch. The shared reader threads the cross-entry state 111 * (addend carriers, subtractor pairs) the per-arch decoder reports via this 112 * role; everything arch-specific (the kind, the lo12 instruction inspection, 113 * the addend carrier) lives in the decoder. */ 114 typedef enum MachoRelocRole { 115 MACHO_RELOC_NORMAL = 0, /* `kind` is final; stands alone */ 116 MACHO_RELOC_ADDEND, /* addend-carrier pseudo-reloc (arm64): emits */ 117 /* nothing; `addend` seeds the next entry */ 118 MACHO_RELOC_SUBTRACTOR, /* minuend marker: `kind` = R_SUB*; arms the pair */ 119 MACHO_RELOC_ABSOLUTE, /* unsigned datum: carries its addend in-place */ 120 /* and becomes R_ADD* when it completes a */ 121 /* pending subtractor, else stands as `kind` */ 122 } MachoRelocRole; 123 124 /* One decoded Mach-O relocation entry (the raw on-disk bitfields). */ 125 typedef struct MachoRelocEntry { 126 u32 r_type; /* 4-bit ARM64_RELOC_* / X86_64_RELOC_* code */ 127 u32 r_pcrel; 128 u32 r_length; /* 0=byte 1=hword 2=word 3=quad */ 129 u32 r_extern; 130 u32 r_symbolnum; 131 u32 r_address; 132 const u8* insn; /* patch-site bytes (>=4 readable iff insn_len>=4), for the */ 133 u32 insn_len; /* arm64 PAGEOFF12 load/store-width inspection; else NULL */ 134 } MachoRelocEntry; 135 136 typedef struct MachoRelocDecoded { 137 u32 kind; /* RelocKind */ 138 u32 role; /* MachoRelocRole */ 139 i64 addend; /* MACHO_RELOC_ADDEND: the carried value */ 140 i64 inplace_bias; /* added to the in-place field value when recovering the */ 141 /* addend. x86_64 bakes a PC-relative reloc's addend as */ 142 /* symrel = addend + width, so the reader subtracts the */ 143 /* width (bias = -(1<<r_length)); 0 for absolute data. */ 144 u8 inplace_addend; /* extern entries recover their addend from the patch */ 145 /* field: the ABSOLUTE family (both arches) and every */ 146 /* x86_64 reloc, which has no out-of-band addend. */ 147 u8 inplace_signed; /* sign-extend the (sub-64-bit) field read — a PC-relative */ 148 /* displacement is signed; an absolute datum is not. */ 149 u8 pad[6]; 150 } MachoRelocDecoded; 151 152 typedef struct ObjMachoArchOps { 153 KitArchKind arch; 154 u32 cputype; 155 u32 cpusubtype; 156 u32 stub_size; 157 ObjFormatMachoStubFn emit_stub; 158 u32 (*reloc_to)(u32 kind); 159 u32 (*reloc_pcrel)(u32 kind); 160 u32 (*reloc_length)(u32 kind); 161 /* Decode one relocation entry to a kit RelocKind + structural role. Returns 162 * 1 on success, 0 if r_type is not a relocation this arch emits. This is the 163 * reader's inverse of (reloc_to, reloc_pcrel, reloc_length): unlike a bare 164 * wire-type map it sees r_pcrel/r_length and the patch-site bytes, which the 165 * overlapping 4-bit r_type field requires to resolve a kind unambiguously. */ 166 int (*reloc_decode)(const MachoRelocEntry* in, MachoRelocDecoded* out); 167 } ObjMachoArchOps; 168 169 typedef struct ObjCoffArchOps { 170 KitArchKind arch; 171 u16 machine; 172 u32 stub_size; 173 ObjFormatCoffStubFn emit_iat_stub; 174 u32 (*reloc_to)(u32 kind); 175 u32 (*reloc_from)(u32 wire_type); 176 } ObjCoffArchOps; 177 178 typedef enum ObjFormatArchiveAction { 179 OBJ_FORMAT_ARCHIVE_KEEP = 0, 180 OBJ_FORMAT_ARCHIVE_REPLACE = 1, 181 OBJ_FORMAT_ARCHIVE_SKIP = 2, 182 } ObjFormatArchiveAction; 183 184 /* ObjTlsModel (TLS access model) is defined in obj.h, the obj-layer 185 * public header that carries the obj_format_tls_model wrapper. */ 186 187 typedef struct ObjFormatArchiveMember { 188 const char* archive_name; 189 const char* member_name; 190 const u8* data; 191 size_t len; 192 KitBinFmt bin_fmt; 193 Sym archive_hint; 194 } ObjFormatArchiveMember; 195 196 typedef struct ObjFormatDsoReader { 197 const struct ObjFormatImpl* format; 198 ObjFormatReadDsoFn read; 199 const char* name; 200 } ObjFormatDsoReader; 201 202 typedef struct ObjFormatEmuOps { 203 KitStatus (*detect_executable)(Compiler*, KitSlice bytes, 204 KitTargetSpec* target_out); 205 KitStatus (*load_executable)(Compiler*, const EmuLoadOptions*, 206 EmuLoadedImage* out); 207 KitStatus (*map_object)(Compiler*, EmuProcess*, EmuLoadedImage*, 208 KitSlice name, KitSlice bytes, int is_main, 209 u32* out_index); 210 void (*dyn_needed_iter)(const EmuLoadedObject*, EmuDynNeededIter* out); 211 int (*dyn_needed_next)(EmuProcess*, EmuDynNeededIter*, KitSlice* out); 212 KitStatus (*dyn_symbol_lookup)(EmuProcess*, const EmuLoadedObject*, 213 KitSlice symbol, EmuDynSymbol* out); 214 KitStatus (*dyn_symbol_by_index)(EmuProcess*, const EmuLoadedObject*, 215 u64 symbol_index, EmuDynSymbol* out); 216 void (*reloc_iter)(const EmuLoadedObject*, EmuDynRelocTableKind table, 217 EmuDynRelocIter* out); 218 int (*reloc_next)(EmuProcess*, EmuDynRelocIter*, EmuDynReloc* out); 219 KitStatus (*reloc_classify)(EmuProcess*, const EmuLoadedObject*, 220 const EmuDynReloc*, EmuDynRelocClass* cls, 221 u32* kind_out); 222 u32 (*reloc_from)(KitArchKind arch, u32 wire_type); 223 } ObjFormatEmuOps; 224 225 typedef struct ObjFormatImpl { 226 ObjFmt kind; 227 const char* name; 228 const char* read_name; 229 const char* read_dso_name; 230 231 ObjFormatEmitFn emit; 232 ObjFormatReadFn read; 233 ObjFormatReadDsoFn read_dso; 234 ObjFormatLinkEmitFn link_emit; 235 ObjFormatLayoutDynFn layout_dyn; 236 ObjFormatFreeDynFn free_dyn; 237 const ObjFormatEmuOps* emu; 238 u8 split_sections_as_atoms; 239 240 /* C source-level symbol prefix the format prepends on disk: "_" for 241 * Mach-O, "" (or NULL, treated as "") for ELF / COFF / Wasm. Read by 242 * obj_format_c_mangle / obj_format_demangle_c. */ 243 const char* c_label_prefix; 244 /* Default entry symbol name for a freshly created Linker on this 245 * format: "_main" for Mach-O (LC_MAIN), "mainCRTStartup" for COFF, 246 * "_start" for ELF / Wasm. NULL means "_start". */ 247 const char* default_entry_name; 248 /* Carries DWARF debug sections file-only (not mapped into a loadable 249 * segment): ELF=1, Mach-O=1, COFF=0. */ 250 u8 carries_file_only_debug; 251 /* Builds its own static GOT / non-lazy pointer table at link time even 252 * for a static image: Mach-O=1, else 0. */ 253 u8 builds_own_static_got; 254 /* COFF pulls an archive member to satisfy a *weak* undef reference 255 * (binutils/PE COMDAT semantics); ELF/Mach-O only pull for strong 256 * undefs. COFF=1, else 0. */ 257 u8 weak_undef_pulls_archive_member; 258 /* Archive libraries are searched as a global fixed point instead of a 259 * strictly positional POSIX scan. COFF linkers use library-set semantics 260 * close to this; ELF/Mach-O keep command-line archive order. */ 261 u8 global_archive_fixpoint; 262 /* Can represent the ELF/Mach-O TLS-access symbol features the CG layer 263 * mints (local-exec/initial-exec/local-dynamic/general-dynamic): ELF=1, 264 * Mach-O=1; COFF (Windows TEB model) and Wasm have no such representation, 265 * =0. Read by obj_format_supports_symbol_feature. */ 266 u8 tls_symbol_features; 267 /* Resolves weak-external / undefined references via the mingw single- 268 * underscore alias convention (e.g. `__set_app_type` <-> `_set_app_type`) 269 * during link symbol resolution: COFF=1, else 0. Read by 270 * obj_format_weak_extern_underscore_alias. */ 271 u8 weak_extern_underscore_alias; 272 273 /* ---- Synthetic linker-section spellings ---- 274 * 275 * Canonical names the linker assigns to the synthetic sections it builds 276 * (ctor/dtor arrays + TLS) at synthesis time, before any writer sees them. 277 * The kit-internal section model is otherwise format-neutral (ELF-spelled 278 * end to end). A NULL entry means the format cannot represent that section, 279 * and the matching obj_secname_* wrapper panics. Read only via those 280 * wrappers in obj_secnames.c. */ 281 const char* secname_init_array; /* ctor table */ 282 const char* secname_fini_array; /* dtor table */ 283 const char* secname_preinit_array; /* pre-init ctors */ 284 const char* secname_tdata; /* TLS initialized data */ 285 const char* secname_tbss; /* TLS zero-fill */ 286 287 /* ---- C-source backend (c_target) emission spellings ---- 288 * 289 * The portable C backend re-emits symbols as C source; a few constructs 290 * spell differently per object format. These fields let c_target read the 291 * spelling from the format vtable instead of branching on format identity. 292 * 293 * alias_via_thunk: how an aliased symbol is re-emitted. 0 = the format 294 * accepts `__attribute__((alias("target")))` directly (ELF / PE-COFF / 295 * Wasm). 1 = the format has no working alias attribute, so the backend 296 * emits a forwarding thunk function instead (Mach-O). */ 297 u8 alias_via_thunk; 298 /* weak_undef_attr: the GCC/Clang attribute spelling that declares an 299 * *undefined* weak reference. "weak" works for ELF / PE-COFF / Wasm; on 300 * Mach-O the `weak` attribute requires a definition, so an undefined weak 301 * ref must use "weak_import". NULL is treated as "weak". */ 302 const char* weak_undef_attr; 303 304 /* Inject a synthetic input object before symbol resolution. NULL when 305 * the format synthesizes nothing. */ 306 ObjFormatSynthInputsFn synth_inputs; 307 308 const ObjElfArchOps* (*elf_arch)(KitArchKind); 309 const ObjElfArchOps* (*elf_machine)(u32 e_machine); 310 const ObjMachoArchOps* (*macho_arch)(KitArchKind); 311 const ObjMachoArchOps* (*macho_cputype)(u32 cputype); 312 const ObjCoffArchOps* (*coff_arch)(KitArchKind); 313 const ObjCoffArchOps* (*coff_machine)(u16 machine); 314 315 /* Header-bytes -> KitTargetSpec detector (see ObjFormatDetectTargetFn). */ 316 ObjFormatDetectTargetFn detect_target; 317 318 /* Raw linked-image metadata rewrite. This deliberately consumes the 319 * original bytes instead of an ObjBuilder so loader state is preserved. */ 320 ObjFormatRewriteLinkedFn rewrite_linked; 321 322 /* Optional format-specific linker ingestion policy. */ 323 int (*classify_obj_input)(Compiler*, ObjBuilder*, Sym* soname_out); 324 Sym (*archive_hint)(Compiler*, const char* archive_name); 325 ObjFormatArchiveAction (*archive_member)(Compiler*, 326 const ObjFormatArchiveMember*, 327 ObjBuilder** out); 328 } ObjFormatImpl; 329 330 const ObjFormatImpl* obj_format_lookup(ObjFmt fmt); 331 const ObjFormatImpl* obj_format_lookup_bin(KitBinFmt fmt); 332 int obj_format_dso_reader_for_bytes(const u8* data, size_t len, 333 KitBinFmt* bin_out, 334 ObjFormatDsoReader* out); 335 336 /* Internal name<->KitObjFmt mapping, backed by the ObjFormatImpl name 337 * list. The thin public KIT_API wrappers (kit_obj_fmt_from_name / 338 * kit_obj_fmt_name, declared in include/kit/object.h) are added in 339 * src/api by a later wave; these are the internal data helpers. 340 * 341 * obj_format_fmt_from_name returns 1 and writes *out on a match (case 342 * sensitive, matching the canonical ObjFormatImpl.name spelling and any 343 * registered alias); returns 0 on an unknown name. obj_format_fmt_name 344 * returns the canonical NUL-terminated literal name, or NULL for an 345 * out-of-range KitObjFmt. */ 346 int obj_format_fmt_from_name(const char* name, KitObjFmt* out); 347 const char* obj_format_fmt_name(KitObjFmt fmt); 348 349 #endif