link.c (31151B)
1 /* Linker: lifecycle, input registration, and LinkImage accessors. 2 * 3 * Resolution and layout live in link_layout.c; relocation application 4 * in link_reloc.c; format-specific emit in link_elf.c; JIT mapping in 5 * link_jit.c. 6 * 7 * Discipline (see link.h:136): inputs are never destroyed by 8 * link_resolve, LinkInputId / ObjBuilder* mappings are stable for the 9 * Linker's lifetime, and resolution produces a fresh LinkImage rather 10 * than mutating the Linker. The single-shot implementation must keep 11 * those invariants so a future incremental re-resolve can plug in. */ 12 13 #include "link/link.h" 14 15 #include <kit/archive.h> 16 #include <kit/core.h> 17 #include <kit/object.h> 18 #include <kit/target.h> 19 #include <string.h> 20 21 #include "core/heap.h" 22 #include "core/pool.h" 23 #include "core/slice.h" 24 #include "core/vec.h" 25 #include "link/link_internal.h" 26 #include "obj/elf/elf.h" 27 #include "obj/format.h" 28 29 static const char* link_float_abi_name(KitFloatAbi abi) { 30 switch (abi) { 31 case KIT_FLOAT_ABI_DEFAULT: 32 return "default"; 33 case KIT_FLOAT_ABI_SOFT: 34 return "soft"; 35 case KIT_FLOAT_ABI_SINGLE: 36 return "single"; 37 case KIT_FLOAT_ABI_DOUBLE: 38 return "double"; 39 } 40 return "unknown"; 41 } 42 43 /* OS compatibility is deliberately directional: an ELF object carrying the 44 * generic/Linux OSABI may be consumed by Linux, Android, or a freestanding 45 * image, because that header value is what assemblers use for otherwise 46 * platform-neutral relocatables. A FreeBSD object or a Mach-O platform stamp 47 * is never borrowed across operating systems. */ 48 static int link_target_os_compatible(KitTargetSpec expected, 49 KitTargetSpec actual) { 50 if (expected.os == actual.os) return 1; 51 if (expected.obj != KIT_OBJ_ELF || actual.os != KIT_OS_LINUX) return 0; 52 return expected.os == KIT_OS_ANDROID || 53 expected.os == KIT_OS_FREESTANDING; 54 } 55 56 static const char* link_target_mismatch(KitTargetSpec expected, 57 KitTargetSpec actual) { 58 if (expected.arch != actual.arch) return "architecture"; 59 if (expected.obj != actual.obj) return "object format"; 60 if (expected.ptr_size != actual.ptr_size) return "pointer size"; 61 if (expected.big_endian != actual.big_endian) return "endianness"; 62 if (!link_target_os_compatible(expected, actual)) return "operating system"; 63 if ((expected.arch == KIT_ARCH_RV32 || expected.arch == KIT_ARCH_RV64) && 64 expected.float_abi != KIT_FLOAT_ABI_DEFAULT && 65 actual.float_abi != KIT_FLOAT_ABI_DEFAULT && 66 expected.float_abi != actual.float_abi) 67 return "float ABI"; 68 return NULL; 69 } 70 71 static void link_target_panic(Linker* l, Slice name, Slice container, 72 KitTargetSpec actual, const char* reason) { 73 KitTargetSpec expected = l->c->target; 74 if (container.s) { 75 compiler_panic( 76 l->c, SRCLOC_NONE, 77 "link: incompatible input '%.*s(%.*s)': %s mismatch; expected " 78 "arch=%s os=%s format=%s ptr=%u endian=%s float=%s, got " 79 "arch=%s os=%s format=%s ptr=%u endian=%s float=%s", 80 SLICE_ARG(container), SLICE_ARG(name), reason, 81 kit_target_arch_name(expected.arch), kit_target_os_name(expected.os), 82 kit_target_obj_name(expected.obj), (u32)expected.ptr_size, 83 expected.big_endian ? "big" : "little", 84 link_float_abi_name((KitFloatAbi)expected.float_abi), 85 kit_target_arch_name(actual.arch), kit_target_os_name(actual.os), 86 kit_target_obj_name(actual.obj), (u32)actual.ptr_size, 87 actual.big_endian ? "big" : "little", 88 link_float_abi_name((KitFloatAbi)actual.float_abi)); 89 } 90 compiler_panic( 91 l->c, SRCLOC_NONE, 92 "link: incompatible input '%.*s': %s mismatch; expected " 93 "arch=%s os=%s format=%s ptr=%u endian=%s float=%s, got " 94 "arch=%s os=%s format=%s ptr=%u endian=%s float=%s", 95 SLICE_ARG(name), reason, kit_target_arch_name(expected.arch), 96 kit_target_os_name(expected.os), kit_target_obj_name(expected.obj), 97 (u32)expected.ptr_size, expected.big_endian ? "big" : "little", 98 link_float_abi_name((KitFloatAbi)expected.float_abi), 99 kit_target_arch_name(actual.arch), kit_target_os_name(actual.os), 100 kit_target_obj_name(actual.obj), (u32)actual.ptr_size, 101 actual.big_endian ? "big" : "little", 102 link_float_abi_name((KitFloatAbi)actual.float_abi)); 103 } 104 105 static void link_validate_target(Linker* l, Slice name, Slice container, 106 KitTargetSpec actual) { 107 const char* reason = link_target_mismatch(l->c->target, actual); 108 if (reason) link_target_panic(l, name, container, actual, reason); 109 } 110 111 static void link_validate_obj_target(Linker* l, Slice name, ObjBuilder* ob) { 112 Compiler* source = obj_compiler(ob); 113 if (!source) 114 compiler_panic(l->c, SRCLOC_NONE, 115 "link: input '%.*s' has no target-owning compiler", 116 SLICE_ARG(name)); 117 link_validate_target(l, name, SLICE_NULL, source->target); 118 } 119 120 static void link_validate_bytes_target(Linker* l, Slice name, Slice container, 121 const u8* data, size_t len, 122 int allow_text_dso) { 123 KitTargetSpec actual; 124 KitStatus st = kit_detect_target(data, len, &actual); 125 if (st == KIT_OK) { 126 link_validate_target(l, name, container, actual); 127 return; 128 } 129 if (allow_text_dso && kit_detect_fmt(data, len) == KIT_BIN_UNKNOWN) return; 130 if (container.s) 131 compiler_panic(l->c, SRCLOC_NONE, 132 "link: cannot determine target of input '%.*s(%.*s)'", 133 SLICE_ARG(container), SLICE_ARG(name)); 134 compiler_panic(l->c, SRCLOC_NONE, 135 "link: cannot determine target of input '%.*s'", 136 SLICE_ARG(name)); 137 } 138 139 void link_merge_elf_e_flags(Linker* l, ObjBuilder* ob, KitSlice label) { 140 u32 incoming; 141 u32 known = EF_RISCV_RVC | EF_RISCV_FLOAT_ABI_MASK | EF_RISCV_RVE | 142 EF_RISCV_TSO; 143 u32 must_match = EF_RISCV_FLOAT_ABI_MASK | EF_RISCV_RVE | ~known; 144 u32 merge_bits = EF_RISCV_RVC | EF_RISCV_TSO; 145 KitFloatAbi incoming_abi; 146 KitFloatAbi target_abi; 147 Slice first; 148 if (!l || !ob || l->c->target.obj != KIT_OBJ_ELF || 149 (l->c->target.arch != KIT_ARCH_RV32 && 150 l->c->target.arch != KIT_ARCH_RV64) || 151 !obj_get_elf_e_flags(ob, &incoming)) 152 return; 153 incoming_abi = elf_riscv_float_abi_from_e_flags(incoming); 154 target_abi = (KitFloatAbi)l->c->target.float_abi; 155 if (target_abi != KIT_FLOAT_ABI_DEFAULT && incoming_abi != target_abi) { 156 compiler_panic(l->c, SRCLOC_NONE, 157 "link: incompatible input '%.*s': RISC-V float ABI is %s, " 158 "link target requires %s (e_flags=0x%x)", 159 SLICE_ARG(label), link_float_abi_name(incoming_abi), 160 link_float_abi_name(target_abi), incoming); 161 } 162 if (!l->have_elf_e_flags) { 163 l->elf_e_flags = incoming; 164 l->elf_e_flags_source = pool_intern_slice(l->c->global, label); 165 l->have_elf_e_flags = 1; 166 return; 167 } 168 if ((l->elf_e_flags & must_match) != (incoming & must_match)) { 169 first = l->elf_e_flags_source 170 ? pool_slice(l->c->global, l->elf_e_flags_source) 171 : SLICE_LIT("<first input>"); 172 compiler_panic(l->c, SRCLOC_NONE, 173 "link: incompatible RISC-V ELF e_flags: input '%.*s' has " 174 "0x%x, input '%.*s' has 0x%x (float ABI, RVE, and reserved " 175 "bits must agree)", 176 SLICE_ARG(label), incoming, SLICE_ARG(first), 177 l->elf_e_flags); 178 } 179 l->elf_e_flags |= incoming & merge_bits; 180 } 181 182 /* ---- SrcLoc helper ---- */ 183 184 /* SymHash is a HASHMAP_DEFINE instance — see link_internal.h. The thin 185 * symhash_* wrappers there preserve the historic insert-if-absent / by- 186 * value get API. */ 187 188 /* ---- Linker lifecycle ---- */ 189 190 static void linker_release(Linker* l) { 191 u32 i, j; 192 if (!l) return; 193 /* Free the ObjBuilders we own (the ones we read from bytes inputs). 194 * link_add_obj inputs are caller-owned and stay alive. */ 195 for (i = 0; i < LinkInputs_count(&l->inputs); ++i) { 196 LinkInput* in = LinkInputs_at(&l->inputs, i); 197 if ((in->kind == LINK_INPUT_OBJ_BYTES || 198 in->kind == LINK_INPUT_DSO_BYTES) && 199 in->obj) 200 obj_free(in->obj); 201 } 202 /* Free archive member ObjBuilders that were never pulled into inputs. 203 * Pulled members had their `obj` pointer transferred and nulled, so 204 * obj_free(NULL) is safe regardless. */ 205 for (i = 0; i < LinkArchives_count(&l->archives); ++i) { 206 LinkArchive* ar = LinkArchives_at(&l->archives, i); 207 for (j = 0; j < ar->nmembers; ++j) { 208 if (ar->members[j].obj) obj_free(ar->members[j].obj); 209 } 210 if (ar->members) 211 l->heap->free(l->heap, ar->members, sizeof(*ar->members) * ar->nmembers); 212 } 213 LinkArchives_fini(&l->archives); 214 LinkInputs_fini(&l->inputs); 215 l->heap->free(l->heap, l, sizeof(*l)); 216 } 217 218 static void linker_cleanup(void* arg) { linker_release((Linker*)arg); } 219 220 Linker* link_new(Compiler* c) { 221 Heap* h = (Heap*)c->ctx->heap; 222 Linker* l = (Linker*)h->alloc(h, sizeof(*l), _Alignof(Linker)); 223 if (!l) return NULL; 224 memset(l, 0, sizeof(*l)); 225 l->c = c; 226 l->heap = h; 227 LinkInputs_init(&l->inputs, h); 228 LinkArchives_init(&l->archives, h); 229 /* Default entry: ELF/static convention uses `_start`. Mach-O's 230 * LC_MAIN names main directly (dyld owns the C runtime startup), 231 * so the on-disk symbol is `_main` (the mangled form of `main`). 232 * Format choice lives in obj_format_default_entry_name. */ 233 l->entry_name = pool_intern_slice( 234 c->global, slice_from_cstr(obj_format_default_entry_name(c))); 235 /* Match the rest of libkit's lifetime story: the new'd Linker is 236 * registered for cleanup in case a panic fires before link_free. */ 237 l->deferred = compiler_defer(c, linker_cleanup, l); 238 return l; 239 } 240 241 void link_free(Linker* l) { 242 Compiler* c; 243 CompilerCleanup* d; 244 if (!l) return; 245 c = l->c; 246 d = l->deferred; 247 linker_release(l); 248 if (d) compiler_undefer(c, d); 249 } 250 251 /* ---- input registration ---- */ 252 253 static LinkInput* inputs_push(Linker* l, LinkInputId* id_out) { 254 u32 idx; 255 LinkInput* in = LinkInputs_push(&l->inputs, &idx); 256 if (!in) 257 compiler_panic(l->c, SRCLOC_NONE, "link: out of memory growing inputs"); 258 *id_out = (LinkInputId)(idx + 1u); 259 in->id = *id_out; 260 return in; 261 } 262 263 LinkInputId link_add_obj(Linker* l, ObjBuilder* ob) { 264 LinkInputId id; 265 LinkInput* in; 266 if (!l || !ob) return LINK_INPUT_NONE; 267 link_validate_obj_target(l, SLICE_LIT("<in-memory object>"), ob); 268 link_merge_elf_e_flags(l, ob, SLICE_LIT("<in-memory object>")); 269 in = inputs_push(l, &id); 270 in->kind = LINK_INPUT_OBJ; 271 in->order = l->next_input_order++; 272 in->obj = ob; 273 return id; 274 } 275 276 LinkInputId link_add_obj_bytes(Linker* l, const char* name, const u8* data, 277 size_t len) { 278 ObjBuilder* ob; 279 LinkInput* in; 280 LinkInputId id; 281 KitBinFmt fmt; 282 const ObjFormatImpl* impl; 283 const char* reader_name; 284 Slice label; 285 if (!l || !data || !len) return LINK_INPUT_NONE; 286 label = name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"); 287 link_validate_bytes_target(l, label, SLICE_NULL, data, len, 0); 288 fmt = kit_detect_fmt(data, len); 289 impl = obj_format_lookup_bin(fmt); 290 if (!impl || !impl->read) 291 compiler_panic( 292 l->c, SRCLOC_NONE, 293 "link_add_obj_bytes: unsupported object format " 294 "(fmt=%u) for '%.*s'", 295 (u32)fmt, 296 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 297 reader_name = impl->read_name; 298 ob = impl->read(l->c, name, data, len); 299 if (!ob) 300 compiler_panic( 301 l->c, SRCLOC_NONE, "link_add_obj_bytes: %.*s returned NULL for '%.*s'", 302 SLICE_ARG(slice_from_cstr(reader_name)), 303 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 304 link_merge_elf_e_flags(l, ob, label); 305 in = inputs_push(l, &id); 306 in->order = l->next_input_order++; 307 in->obj = ob; /* re-uses the ObjBuilder slot for ownership */ 308 in->name = name ? pool_intern_cstr(l->c->global, name) : 0; 309 { 310 Sym soname = 0; 311 if (impl->classify_obj_input && 312 impl->classify_obj_input(l->c, ob, &soname)) { 313 in->kind = LINK_INPUT_DSO_BYTES; 314 in->soname = soname; 315 } else { 316 in->kind = LINK_INPUT_OBJ_BYTES; 317 } 318 } 319 return id; 320 } 321 322 LinkInputId link_add_dso_bytes(Linker* l, const char* name, const u8* data, 323 size_t len) { 324 ObjBuilder* ob = NULL; 325 LinkInput* in; 326 LinkInputId id; 327 Sym soname = 0; 328 KitBinFmt fmt; 329 ObjFormatDsoReader reader; 330 const ObjFormatImpl* target_impl; 331 const char* reader_name; 332 Slice label; 333 if (!l || !data || !len) return LINK_INPUT_NONE; 334 label = name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"); 335 link_validate_bytes_target(l, label, SLICE_NULL, data, len, 1); 336 if (!obj_format_dso_reader_for_bytes(data, len, &fmt, &reader)) 337 compiler_panic( 338 l->c, SRCLOC_NONE, 339 "link_add_dso_bytes: unsupported DSO format " 340 "(fmt=%u) for '%.*s'", 341 (u32)fmt, 342 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 343 target_impl = obj_format_lookup(l->c->target.obj); 344 if (!target_impl || reader.format != target_impl) 345 compiler_panic( 346 l->c, SRCLOC_NONE, 347 "link: incompatible input '%.*s': object format mismatch; expected " 348 "format=%s, got format=%s", 349 SLICE_ARG(label), kit_target_obj_name(l->c->target.obj), 350 reader.format && reader.format->name ? reader.format->name : "unknown"); 351 reader_name = reader.name; 352 ob = reader.read(l->c, name, data, len, &soname); 353 if (!ob) 354 compiler_panic( 355 l->c, SRCLOC_NONE, "link_add_dso_bytes: %.*s returned NULL for '%.*s'", 356 SLICE_ARG(slice_from_cstr(reader_name)), 357 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 358 link_merge_elf_e_flags(l, ob, label); 359 in = inputs_push(l, &id); 360 in->kind = LINK_INPUT_DSO_BYTES; 361 in->order = l->next_input_order++; 362 in->obj = ob; 363 in->name = name ? pool_intern_cstr(l->c->global, name) : 0; 364 /* DT_SONAME wins; fall back to the file's basename if the DSO has 365 * no SONAME (matches GNU ld's behaviour for hand-rolled libraries 366 * that forgot to set DT_SONAME). */ 367 if (soname != 0) { 368 in->soname = soname; 369 } else if (name) { 370 const char* base = name; 371 const char* p; 372 for (p = name; *p; ++p) 373 if (*p == '/') base = p + 1; 374 in->soname = pool_intern_cstr(l->c->global, base); 375 } else { 376 in->soname = 0; 377 } 378 return id; 379 } 380 381 LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data, 382 size_t len, u8 whole_archive, u8 link_mode, 383 u8 group_id) { 384 KitSlice in_arc; 385 KitArIter* it = NULL; 386 KitArMember mem; 387 LinkArchive* ar; 388 u32 n; 389 Sym archive_hint = 0; 390 const ObjFormatImpl* target_impl; 391 392 if (!l || !data || !len) return LINK_INPUT_NONE; 393 target_impl = obj_format_lookup(l->c->target.obj); 394 if (target_impl && target_impl->archive_hint) 395 archive_hint = target_impl->archive_hint(l->c, name); 396 397 in_arc.data = data; 398 in_arc.len = len; 399 if (kit_ar_iter_new(kit_compiler_context(l->c), &in_arc, &it) != KIT_OK || 400 !it) 401 compiler_panic( 402 l->c, SRCLOC_NONE, 403 "link_add_archive_bytes: '%.*s' is not a valid ar archive", 404 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 405 406 /* Two-pass: count members so we allocate the member array exactly 407 * once. The linker_release path frees by nmembers, so we need 408 * allocation size to match. */ 409 n = 0; 410 while (kit_ar_iter_next(it, &mem) == KIT_ITER_ITEM) ++n; 411 kit_ar_iter_free(it); 412 it = NULL; 413 414 ar = LinkArchives_push(&l->archives, NULL); 415 if (!ar) 416 compiler_panic(l->c, SRCLOC_NONE, "link: out of memory growing archives"); 417 ar->name = name ? pool_intern_cstr(l->c->global, name) : 0; 418 ar->order = l->next_input_order++; 419 ar->whole_archive = whole_archive; 420 ar->link_mode = link_mode; 421 ar->group_id = group_id; 422 ar->nmembers = n; 423 ar->members = 424 n ? (LinkArchiveMember*)l->heap->alloc(l->heap, sizeof(*ar->members) * n, 425 _Alignof(LinkArchiveMember)) 426 : NULL; 427 if (n && !ar->members) 428 compiler_panic(l->c, SRCLOC_NONE, "link: oom on archive members"); 429 if (n) memset(ar->members, 0, sizeof(*ar->members) * n); 430 431 /* Pass 2: parse each member as object. ar.c's iterator skips the 432 * symbol-index ('/' and '__.SYMDEF') and long-name ('//') members 433 * for us, so every member returned here is a real object file. 434 * Format is detected per-member so a single archive could in 435 * principle hold mixed formats (in practice it never does). */ 436 if (kit_ar_iter_new(kit_compiler_context(l->c), &in_arc, &it) != KIT_OK || 437 !it) 438 compiler_panic( 439 l->c, SRCLOC_NONE, 440 "link_add_archive_bytes: ar_iter_init failed on '%.*s' " 441 "second pass", 442 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 443 n = 0; 444 while (kit_ar_iter_next(it, &mem) == KIT_ITER_ITEM && n < ar->nmembers) { 445 ObjBuilder* ob = NULL; 446 KitBinFmt mfmt = kit_detect_fmt(mem.data, mem.size); 447 const ObjFormatImpl* member_impl = obj_format_lookup_bin(mfmt); 448 link_validate_bytes_target( 449 l, mem.name.len ? mem.name : SLICE_LIT("(unnamed)"), 450 name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"), mem.data, 451 mem.size, 0); 452 if (target_impl && target_impl->archive_member) { 453 ObjFormatArchiveMember desc; 454 ObjFormatArchiveAction action; 455 memset(&desc, 0, sizeof(desc)); 456 desc.archive_name = name; 457 desc.member_name = mem.name.s; 458 desc.data = mem.data; 459 desc.len = mem.size; 460 desc.bin_fmt = mfmt; 461 desc.archive_hint = archive_hint; 462 action = target_impl->archive_member(l->c, &desc, &ob); 463 if (action != OBJ_FORMAT_ARCHIVE_KEEP) { 464 ar->members[n].name = 465 mem.name.len ? pool_intern_slice(l->c->global, mem.name) : 0; 466 ar->members[n].obj = ob; 467 ++n; 468 continue; 469 } 470 } 471 if (!member_impl || !member_impl->read) 472 compiler_panic( 473 l->c, SRCLOC_NONE, 474 "link_add_archive_bytes: unsupported member " 475 "format (fmt=%u) for '%.*s' in archive '%.*s'", 476 (u32)mfmt, 477 SLICE_ARG(mem.name.len ? mem.name : SLICE_LIT("(unnamed)")), 478 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 479 ob = member_impl->read(l->c, mem.name.s, mem.data, mem.size); 480 if (!ob) 481 compiler_panic( 482 l->c, SRCLOC_NONE, 483 "link_add_archive_bytes: object read failed for " 484 "member '%.*s' of archive '%.*s'", 485 SLICE_ARG(mem.name.len ? mem.name : SLICE_LIT("(unnamed)")), 486 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 487 ar->members[n].name = 488 mem.name.len ? pool_intern_slice(l->c->global, mem.name) : 0; 489 ar->members[n].obj = ob; 490 ++n; 491 } 492 kit_ar_iter_free(it); 493 return (LinkInputId)LinkArchives_count( 494 &l->archives); /* opaque non-zero handle */ 495 } 496 497 /* Intern a C-source-level symbol name in the format the input objects 498 * use on the wire. Format-specific mangling (Mach-O `_` prefix, 499 * verbatim everywhere else) lives in obj_format_c_mangle. */ 500 Sym link_intern_c_name(Linker* l, const char* name) { 501 if (!l || !name) return 0; 502 return obj_format_c_mangle(l->c, name); 503 } 504 505 void link_set_entry(Linker* l, KitSlice name) { 506 if (!l || !name.s || name.len == 0) return; 507 /* entry names from the API/script are interned arena/pool slices and 508 * thus NUL-terminated; the mangler scans a C string. */ 509 l->entry_name = link_intern_c_name(l, name.s); 510 } 511 512 void link_clear_entry(Linker* l) { 513 if (!l) return; 514 l->entry_name = 0; 515 } 516 517 void link_set_script(Linker* l, const KitLinkScript* script) { 518 if (!l || !script) return; 519 l->script = script; 520 if (script->entry.s && script->entry.len) 521 l->entry_name = link_intern_c_name(l, script->entry.s); 522 } 523 524 void link_set_extern_resolver(Linker* l, LinkExternResolver fn, void* user) { 525 if (!l) return; 526 l->resolver = fn; 527 l->resolver_user = user; 528 } 529 530 void link_set_gc_sections(Linker* l, int enable) { 531 if (!l) return; 532 l->gc_sections = enable; 533 /* Accepted but ignored this cut. Quiet by design — driver/ld.c may 534 * pass 0 unconditionally and we don't want to noise that. */ 535 } 536 537 void link_set_strip_debug(Linker* l, int enable) { 538 if (!l) return; 539 l->strip_debug = enable; 540 /* Executable layouts already omit non-alloc debug sections. Keep the flag 541 * recorded so driver -S/--strip-debug flows through the linker surface. */ 542 } 543 544 void link_set_allow_undefined(Linker* l, int enable) { 545 if (!l) return; 546 l->allow_undefined = enable ? 1 : 0; 547 } 548 549 void link_set_shared(Linker* l, int enable) { 550 if (!l) return; 551 l->emit_shared = enable ? 1 : 0; 552 } 553 554 void link_set_emit_static_exe(Linker* l, int enable) { 555 if (!l) return; 556 l->emit_static_exe = enable ? 1 : 0; 557 } 558 559 void link_set_jit_mode(Linker* l, int enable) { 560 if (!l) return; 561 l->jit_mode = enable ? 1 : 0; 562 } 563 564 void link_set_pie(Linker* l, int enable) { 565 if (!l) return; 566 l->emit_pie = enable ? 1 : 0; 567 } 568 569 void link_set_text_base(Linker* l, u64 base) { 570 if (!l) return; 571 l->text_base_set = 1; 572 l->text_base = base; 573 } 574 575 void link_set_pe_subsystem(Linker* l, u16 subsystem) { 576 if (!l) return; 577 l->pe_subsystem = subsystem; 578 } 579 580 void link_set_jit_host(Linker* l, const KitJitHost* host) { 581 if (!l) return; 582 l->jit_host = host; 583 } 584 585 void link_set_interp_path(Linker* l, KitSlice path) { 586 if (!l) return; 587 l->interp_path = 588 (path.s && path.len) ? pool_intern_slice(l->c->global, path) : 0; 589 } 590 591 /* ---- debug-input capture ---- 592 * 593 * Called once at the tail of link_resolve. For each LinkInput, record 594 * its ObjBuilder on the LinkImage so the JIT debug view (kit_jit_view) 595 * can read .debug_* sections after the Linker is freed. Two ownership 596 * regimes: 597 * 598 * LINK_INPUT_OBJ_BYTES: linker owns; transfer to the image and null 599 * the LinkInput's obj so linker_release doesn't double-free. 600 * LINK_INPUT_OBJ: caller owns; borrow the pointer (do not free 601 * at image teardown). Caller is responsible for keeping the 602 * builder alive at least as long as the JIT. 603 * 604 * DSO / archive-only inputs carry no source-level debug info worth 605 * surfacing through kit_jit_view, so their slot stays NULL. */ 606 void link_capture_debug_inputs(Linker* l, LinkImage* img) { 607 u32 n; 608 u32 i; 609 Heap* h; 610 if (!l || !img) return; 611 n = LinkInputs_count(&l->inputs); 612 img->dbg_objs_n = n; 613 if (n == 0) { 614 img->dbg_objs = NULL; 615 img->dbg_objs_owned = NULL; 616 return; 617 } 618 h = img->heap; 619 img->dbg_objs = (ObjBuilder**)h->alloc(h, sizeof(*img->dbg_objs) * n, 620 _Alignof(ObjBuilder*)); 621 img->dbg_objs_owned = (u8*)h->alloc(h, sizeof(*img->dbg_objs_owned) * n, 1u); 622 if (!img->dbg_objs || !img->dbg_objs_owned) 623 compiler_panic(img->c, SRCLOC_NONE, 624 "link_capture_debug_inputs: oom on dbg arrays"); 625 memset(img->dbg_objs, 0, sizeof(*img->dbg_objs) * n); 626 memset(img->dbg_objs_owned, 0, sizeof(*img->dbg_objs_owned) * n); 627 for (i = 0; i < n; ++i) { 628 LinkInput* in = LinkInputs_at(&l->inputs, i); 629 if (!in || !in->obj) continue; 630 switch (in->kind) { 631 case LINK_INPUT_OBJ_BYTES: 632 img->dbg_objs[i] = in->obj; 633 img->dbg_objs_owned[i] = 1u; 634 in->obj = NULL; /* transfer: linker_release must not free it */ 635 break; 636 case LINK_INPUT_OBJ: 637 img->dbg_objs[i] = in->obj; 638 img->dbg_objs_owned[i] = 0u; /* borrowed; caller still owns */ 639 break; 640 default: 641 /* DSO / TBD: skip — no user-level debug sections we expose. */ 642 break; 643 } 644 } 645 } 646 647 /* ---- LinkImage accessors ---- */ 648 649 const LinkSymbol* link_symbol(LinkImage* img, LinkSymId id) { 650 if (!img || id == LINK_SYM_NONE || id > LinkSyms_count(&img->syms)) 651 return NULL; 652 return LinkSyms_at(&img->syms, id - 1); 653 } 654 655 LinkSymId link_symbol_lookup(LinkImage* img, Sym name) { 656 if (!img) return LINK_SYM_NONE; 657 return symhash_get(&img->globals, name); 658 } 659 660 u32 link_segment_count(LinkImage* img) { return img ? img->nsegments : 0; } 661 662 const LinkSegment* link_segment_get(LinkImage* img, u32 id) { 663 if (!img || id == LINK_SEG_NONE || id > img->nsegments) return NULL; 664 return &img->segments[id - 1]; 665 } 666 667 const u8* link_segment_bytes(LinkImage* img, LinkSegmentId id, 668 size_t* size_out) { 669 if (size_out) *size_out = 0; 670 if (!img || id == LINK_SEG_NONE || id > img->nsegments) return NULL; 671 if (size_out) *size_out = (size_t)img->segments[id - 1].file_size; 672 return img->segment_bytes[id - 1]; 673 } 674 675 u32 link_section_count(LinkImage* img) { return img ? img->nsections : 0; } 676 677 const LinkSection* link_section_get(LinkImage* img, LinkSectionId id) { 678 if (!img || id == LINK_SEC_NONE || id > img->nsections) return NULL; 679 return &img->sections[id - 1]; 680 } 681 682 u32 link_reloc_apply_count(LinkImage* img) { 683 return img ? LinkRelocs_count(&img->relocs) : 0; 684 } 685 686 const LinkRelocApply* link_reloc_apply_get(LinkImage* img, u32 id) { 687 if (!img || id >= LinkRelocs_count(&img->relocs)) return NULL; 688 return LinkRelocs_at(&img->relocs, id); 689 } 690 691 /* ---- LinkImage free / cleanup ---- */ 692 693 static void link_image_release(LinkImage* img) { 694 u32 i; 695 if (!img) return; 696 if (img->segment_bytes) { 697 for (i = 0; i < img->nsegments; ++i) { 698 if (img->segment_bytes[i]) 699 img->heap->free(img->heap, img->segment_bytes[i], 700 img->segment_bytes_cap[i]); 701 } 702 img->heap->free(img->heap, img->segment_bytes, 703 sizeof(*img->segment_bytes) * img->nsegments); 704 img->heap->free(img->heap, img->segment_bytes_cap, 705 sizeof(*img->segment_bytes_cap) * img->nsegments); 706 } 707 if (img->segments) 708 img->heap->free(img->heap, img->segments, 709 sizeof(*img->segments) * img->nsegments); 710 if (img->sections) 711 img->heap->free(img->heap, img->sections, 712 sizeof(*img->sections) * img->nsections); 713 LinkSyms_fini(&img->syms); 714 LinkRelocs_fini(&img->relocs); 715 if (img->iplt_pairs) 716 img->heap->free(img->heap, img->iplt_pairs, 717 sizeof(*img->iplt_pairs) * img->niplt * 2u); 718 if (img->input_maps) { 719 for (i = 0; i < img->ninput_maps; ++i) { 720 InputMap* m = &img->input_maps[i]; 721 if (m->sym) img->heap->free(img->heap, m->sym, sizeof(*m->sym) * m->nsym); 722 if (m->section) 723 img->heap->free(img->heap, m->section, 724 sizeof(*m->section) * m->nsection); 725 if (m->atom) 726 img->heap->free(img->heap, m->atom, 727 sizeof(*m->atom) * (m->natom ? m->natom : 1u)); 728 if (m->sym_atom) 729 img->heap->free(img->heap, m->sym_atom, 730 sizeof(*m->sym_atom) * (m->nsym ? m->nsym : 1u)); 731 if (m->reloc_atom) 732 img->heap->free(img->heap, m->reloc_atom, 733 sizeof(*m->reloc_atom) * (m->nreloc ? m->nreloc : 1u)); 734 if (m->section_has_atoms) 735 img->heap->free(img->heap, m->section_has_atoms, 736 m->nsection ? m->nsection : 1u); 737 if (m->section_atom_first) 738 img->heap->free( 739 img->heap, m->section_atom_first, 740 sizeof(*m->section_atom_first) * (m->nsection ? m->nsection : 1u)); 741 if (m->section_atom_count) 742 img->heap->free( 743 img->heap, m->section_atom_count, 744 sizeof(*m->section_atom_count) * (m->nsection ? m->nsection : 1u)); 745 if (m->section_atom_ids) 746 img->heap->free(img->heap, m->section_atom_ids, 747 sizeof(*m->section_atom_ids) * m->nsection_atom_ids); 748 if (m->comdat_discarded) 749 img->heap->free(img->heap, m->comdat_discarded, 750 m->nsection ? m->nsection : 1u); 751 } 752 img->heap->free(img->heap, img->input_maps, 753 sizeof(*img->input_maps) * img->ninput_maps); 754 } 755 if (img->dbg_objs) { 756 for (i = 0; i < img->dbg_objs_n; ++i) { 757 if (img->dbg_objs[i] && img->dbg_objs_owned && img->dbg_objs_owned[i]) 758 obj_free(img->dbg_objs[i]); 759 } 760 img->heap->free(img->heap, img->dbg_objs, 761 sizeof(*img->dbg_objs) * img->dbg_objs_n); 762 if (img->dbg_objs_owned) 763 img->heap->free(img->heap, img->dbg_objs_owned, 764 sizeof(*img->dbg_objs_owned) * img->dbg_objs_n); 765 } 766 if (img->dbg_bytes) { 767 for (i = 0; i < img->dbg_count; ++i) 768 if (img->dbg_bytes[i]) 769 img->heap->free(img->heap, img->dbg_bytes[i], (size_t)img->dbg_size[i]); 770 img->heap->free(img->heap, img->dbg_bytes, 771 sizeof(*img->dbg_bytes) * img->dbg_count); 772 } 773 if (img->dbg_size) 774 img->heap->free(img->heap, img->dbg_size, 775 sizeof(*img->dbg_size) * img->dbg_count); 776 symhash_fini(&img->globals); 777 if (img->dyn) { 778 const ObjFormatImpl* fmt = obj_format_lookup(img->c->target.obj); 779 if (fmt && fmt->free_dyn) fmt->free_dyn(img); 780 } 781 img->heap->free(img->heap, img, sizeof(*img)); 782 } 783 784 static void link_image_cleanup(void* arg) { 785 link_image_release((LinkImage*)arg); 786 } 787 788 LinkImage* link_image_alloc(Compiler* c) { 789 Heap* h = (Heap*)c->ctx->heap; 790 LinkImage* img = (LinkImage*)h->alloc(h, sizeof(*img), _Alignof(LinkImage)); 791 if (!img) 792 compiler_panic(c, SRCLOC_NONE, "link: out of memory allocating image"); 793 memset(img, 0, sizeof(*img)); 794 img->c = c; 795 img->heap = h; 796 LinkSyms_init(&img->syms, h); 797 LinkRelocs_init(&img->relocs, h); 798 symhash_init(&img->globals, h); 799 img->deferred = compiler_defer(c, link_image_cleanup, img); 800 return img; 801 } 802 803 void link_image_free(LinkImage* img) { 804 if (!img) return; 805 if (img->deferred) compiler_undefer(img->c, img->deferred); 806 link_image_release(img); 807 } 808 809 /* ---- Incremental resolution (stubs) ---- 810 * Per-block JIT translation in src/emu/ wants to grow a single 811 * LinkImage as cold blocks land (doc/EMU.md §6). The single-shot 812 * link_resolve discipline (link.h header comment) is set up to 813 * support this — inputs are non-destructively consumed, ObjBuilder* 814 * mappings are stable, resolution is functional. The two entries 815 * below are the surface; the implementation lands alongside the 816 * emu lifter cut. */ 817 818 LinkImage* link_resolve_at(Linker* l, uintptr_t base_va) { 819 (void)base_va; 820 if (!l) return NULL; 821 compiler_panic(l->c, SRCLOC_NONE, 822 "link_resolve_at: incremental resolution not yet " 823 "implemented"); 824 return NULL; 825 } 826 827 void link_resolve_extend(Linker* l, LinkImage* img) { 828 (void)img; 829 if (!l) return; 830 compiler_panic(l->c, SRCLOC_NONE, 831 "link_resolve_extend: incremental resolution not " 832 "yet implemented"); 833 } 834 835 /* ---- public emit dispatcher ---- */ 836 837 void link_emit_image_writer(LinkImage* img, Writer* w) { 838 const ObjFormatImpl* fmt; 839 if (!img || !w) return; 840 fmt = obj_format_lookup(img->c->target.obj); 841 if (fmt && fmt->link_emit) { 842 fmt->link_emit(img, w); 843 return; 844 } 845 compiler_panic(img->c, SRCLOC_NONE, 846 "link_emit_image_writer: unsupported obj format %u", 847 (u32)img->c->target.obj); 848 }