link.c (23085B)
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 <string.h> 19 20 #include "core/heap.h" 21 #include "core/pool.h" 22 #include "core/slice.h" 23 #include "core/vec.h" 24 #include "link/link_internal.h" 25 #include "obj/format.h" 26 27 /* ---- SrcLoc helper ---- */ 28 29 /* SymHash is a HASHMAP_DEFINE instance — see link_internal.h. The thin 30 * symhash_* wrappers there preserve the historic insert-if-absent / by- 31 * value get API. */ 32 33 /* ---- Linker lifecycle ---- */ 34 35 static void linker_release(Linker* l) { 36 u32 i, j; 37 if (!l) return; 38 /* Free the ObjBuilders we own (the ones we read from bytes inputs). 39 * link_add_obj inputs are caller-owned and stay alive. */ 40 for (i = 0; i < LinkInputs_count(&l->inputs); ++i) { 41 LinkInput* in = LinkInputs_at(&l->inputs, i); 42 if ((in->kind == LINK_INPUT_OBJ_BYTES || 43 in->kind == LINK_INPUT_DSO_BYTES) && 44 in->obj) 45 obj_free(in->obj); 46 } 47 /* Free archive member ObjBuilders that were never pulled into inputs. 48 * Pulled members had their `obj` pointer transferred and nulled, so 49 * obj_free(NULL) is safe regardless. */ 50 for (i = 0; i < LinkArchives_count(&l->archives); ++i) { 51 LinkArchive* ar = LinkArchives_at(&l->archives, i); 52 for (j = 0; j < ar->nmembers; ++j) { 53 if (ar->members[j].obj) obj_free(ar->members[j].obj); 54 } 55 if (ar->members) 56 l->heap->free(l->heap, ar->members, sizeof(*ar->members) * ar->nmembers); 57 } 58 LinkArchives_fini(&l->archives); 59 LinkInputs_fini(&l->inputs); 60 l->heap->free(l->heap, l, sizeof(*l)); 61 } 62 63 static void linker_cleanup(void* arg) { linker_release((Linker*)arg); } 64 65 Linker* link_new(Compiler* c) { 66 Heap* h = (Heap*)c->ctx->heap; 67 Linker* l = (Linker*)h->alloc(h, sizeof(*l), _Alignof(Linker)); 68 if (!l) return NULL; 69 memset(l, 0, sizeof(*l)); 70 l->c = c; 71 l->heap = h; 72 LinkInputs_init(&l->inputs, h); 73 LinkArchives_init(&l->archives, h); 74 /* Default entry: ELF/static convention uses `_start`. Mach-O's 75 * LC_MAIN names main directly (dyld owns the C runtime startup), 76 * so the on-disk symbol is `_main` (the mangled form of `main`). 77 * Format choice lives in obj_format_default_entry_name. */ 78 l->entry_name = pool_intern_slice( 79 c->global, slice_from_cstr(obj_format_default_entry_name(c))); 80 /* Match the rest of libkit's lifetime story: the new'd Linker is 81 * registered for cleanup in case a panic fires before link_free. */ 82 l->deferred = compiler_defer(c, linker_cleanup, l); 83 return l; 84 } 85 86 void link_free(Linker* l) { 87 Compiler* c; 88 CompilerCleanup* d; 89 if (!l) return; 90 c = l->c; 91 d = l->deferred; 92 linker_release(l); 93 if (d) compiler_undefer(c, d); 94 } 95 96 /* ---- input registration ---- */ 97 98 static LinkInput* inputs_push(Linker* l, LinkInputId* id_out) { 99 u32 idx; 100 LinkInput* in = LinkInputs_push(&l->inputs, &idx); 101 if (!in) compiler_panic(l->c, SRCLOC_NONE, "link: out of memory growing inputs"); 102 *id_out = (LinkInputId)(idx + 1u); 103 in->id = *id_out; 104 return in; 105 } 106 107 LinkInputId link_add_obj(Linker* l, ObjBuilder* ob) { 108 LinkInputId id; 109 LinkInput* in; 110 if (!l || !ob) return LINK_INPUT_NONE; 111 in = inputs_push(l, &id); 112 in->kind = LINK_INPUT_OBJ; 113 in->order = l->next_input_order++; 114 in->obj = ob; 115 return id; 116 } 117 118 LinkInputId link_add_obj_bytes(Linker* l, const char* name, const u8* data, 119 size_t len) { 120 ObjBuilder* ob; 121 LinkInput* in; 122 LinkInputId id; 123 KitBinFmt fmt; 124 const ObjFormatImpl* impl; 125 const char* reader_name; 126 if (!l || !data || !len) return LINK_INPUT_NONE; 127 fmt = kit_detect_fmt(data, len); 128 impl = obj_format_lookup_bin(fmt); 129 if (!impl || !impl->read) 130 compiler_panic( 131 l->c, SRCLOC_NONE, 132 "link_add_obj_bytes: unsupported object format " 133 "(fmt=%u) for '%.*s'", 134 (u32)fmt, 135 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 136 reader_name = impl->read_name; 137 ob = impl->read(l->c, name, data, len); 138 if (!ob) 139 compiler_panic( 140 l->c, SRCLOC_NONE, "link_add_obj_bytes: %.*s returned NULL for '%.*s'", 141 SLICE_ARG(slice_from_cstr(reader_name)), 142 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 143 in = inputs_push(l, &id); 144 in->order = l->next_input_order++; 145 in->obj = ob; /* re-uses the ObjBuilder slot for ownership */ 146 in->name = name ? pool_intern_slice(l->c->global, slice_from_cstr(name)) : 0; 147 { 148 Sym soname = 0; 149 if (impl->classify_obj_input && 150 impl->classify_obj_input(l->c, ob, &soname)) { 151 in->kind = LINK_INPUT_DSO_BYTES; 152 in->soname = soname; 153 } else { 154 in->kind = LINK_INPUT_OBJ_BYTES; 155 } 156 } 157 return id; 158 } 159 160 LinkInputId link_add_dso_bytes(Linker* l, const char* name, const u8* data, 161 size_t len) { 162 ObjBuilder* ob = NULL; 163 LinkInput* in; 164 LinkInputId id; 165 Sym soname = 0; 166 KitBinFmt fmt; 167 ObjFormatDsoReader reader; 168 const char* reader_name; 169 if (!l || !data || !len) return LINK_INPUT_NONE; 170 if (!obj_format_dso_reader_for_bytes(data, len, &fmt, &reader)) 171 compiler_panic( 172 l->c, SRCLOC_NONE, 173 "link_add_dso_bytes: unsupported DSO format " 174 "(fmt=%u) for '%.*s'", 175 (u32)fmt, 176 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 177 reader_name = reader.name; 178 ob = reader.read(l->c, name, data, len, &soname); 179 if (!ob) 180 compiler_panic( 181 l->c, SRCLOC_NONE, "link_add_dso_bytes: %.*s returned NULL for '%.*s'", 182 SLICE_ARG(slice_from_cstr(reader_name)), 183 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 184 in = inputs_push(l, &id); 185 in->kind = LINK_INPUT_DSO_BYTES; 186 in->order = l->next_input_order++; 187 in->obj = ob; 188 in->name = name ? pool_intern_slice(l->c->global, slice_from_cstr(name)) : 0; 189 /* DT_SONAME wins; fall back to the file's basename if the DSO has 190 * no SONAME (matches GNU ld's behaviour for hand-rolled libraries 191 * that forgot to set DT_SONAME). */ 192 if (soname != 0) { 193 in->soname = soname; 194 } else if (name) { 195 const char* base = name; 196 const char* p; 197 for (p = name; *p; ++p) 198 if (*p == '/') base = p + 1; 199 in->soname = pool_intern_slice(l->c->global, slice_from_cstr(base)); 200 } else { 201 in->soname = 0; 202 } 203 return id; 204 } 205 206 LinkInputId link_add_archive_bytes(Linker* l, const char* name, const u8* data, 207 size_t len, u8 whole_archive, u8 link_mode, 208 u8 group_id) { 209 KitSlice in_arc; 210 KitArIter* it = NULL; 211 KitArMember mem; 212 LinkArchive* ar; 213 u32 n; 214 Sym archive_hint = 0; 215 const ObjFormatImpl* target_impl; 216 217 if (!l || !data || !len) return LINK_INPUT_NONE; 218 target_impl = obj_format_lookup(l->c->target.obj); 219 if (target_impl && target_impl->archive_hint) 220 archive_hint = target_impl->archive_hint(l->c, name); 221 222 in_arc.data = data; 223 in_arc.len = len; 224 if (kit_ar_iter_new(kit_compiler_context(l->c), &in_arc, &it) != KIT_OK || 225 !it) 226 compiler_panic( 227 l->c, SRCLOC_NONE, 228 "link_add_archive_bytes: '%.*s' is not a valid ar archive", 229 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 230 231 /* Two-pass: count members so we allocate the member array exactly 232 * once. The linker_release path frees by nmembers, so we need 233 * allocation size to match. */ 234 n = 0; 235 while (kit_ar_iter_next(it, &mem) == KIT_ITER_ITEM) ++n; 236 kit_ar_iter_free(it); 237 it = NULL; 238 239 ar = LinkArchives_push(&l->archives, NULL); 240 if (!ar) 241 compiler_panic(l->c, SRCLOC_NONE, "link: out of memory growing archives"); 242 ar->name = name ? pool_intern_slice(l->c->global, slice_from_cstr(name)) : 0; 243 ar->order = l->next_input_order++; 244 ar->whole_archive = whole_archive; 245 ar->link_mode = link_mode; 246 ar->group_id = group_id; 247 ar->nmembers = n; 248 ar->members = 249 n ? (LinkArchiveMember*)l->heap->alloc(l->heap, sizeof(*ar->members) * n, 250 _Alignof(LinkArchiveMember)) 251 : NULL; 252 if (n && !ar->members) 253 compiler_panic(l->c, SRCLOC_NONE, "link: oom on archive members"); 254 if (n) memset(ar->members, 0, sizeof(*ar->members) * n); 255 256 /* Pass 2: parse each member as object. ar.c's iterator skips the 257 * symbol-index ('/' and '__.SYMDEF') and long-name ('//') members 258 * for us, so every member returned here is a real object file. 259 * Format is detected per-member so a single archive could in 260 * principle hold mixed formats (in practice it never does). */ 261 if (kit_ar_iter_new(kit_compiler_context(l->c), &in_arc, &it) != KIT_OK || 262 !it) 263 compiler_panic( 264 l->c, SRCLOC_NONE, 265 "link_add_archive_bytes: ar_iter_init failed on '%.*s' " 266 "second pass", 267 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 268 n = 0; 269 while (kit_ar_iter_next(it, &mem) == KIT_ITER_ITEM && n < ar->nmembers) { 270 ObjBuilder* ob = NULL; 271 KitBinFmt mfmt = kit_detect_fmt(mem.data, mem.size); 272 const ObjFormatImpl* member_impl = obj_format_lookup_bin(mfmt); 273 if (target_impl && target_impl->archive_member) { 274 ObjFormatArchiveMember desc; 275 ObjFormatArchiveAction action; 276 memset(&desc, 0, sizeof(desc)); 277 desc.archive_name = name; 278 desc.member_name = mem.name.s; 279 desc.data = mem.data; 280 desc.len = mem.size; 281 desc.bin_fmt = mfmt; 282 desc.archive_hint = archive_hint; 283 action = target_impl->archive_member(l->c, &desc, &ob); 284 if (action != OBJ_FORMAT_ARCHIVE_KEEP) { 285 ar->members[n].name = 286 mem.name.len ? pool_intern_slice(l->c->global, mem.name) : 0; 287 ar->members[n].obj = ob; 288 ++n; 289 continue; 290 } 291 } 292 if (!member_impl || !member_impl->read) 293 compiler_panic( 294 l->c, SRCLOC_NONE, 295 "link_add_archive_bytes: unsupported member " 296 "format (fmt=%u) for '%.*s' in archive '%.*s'", 297 (u32)mfmt, 298 SLICE_ARG(mem.name.len ? mem.name : SLICE_LIT("(unnamed)")), 299 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 300 ob = member_impl->read(l->c, mem.name.s, mem.data, mem.size); 301 if (!ob) 302 compiler_panic( 303 l->c, SRCLOC_NONE, 304 "link_add_archive_bytes: object read failed for " 305 "member '%.*s' of archive '%.*s'", 306 SLICE_ARG(mem.name.len ? mem.name : SLICE_LIT("(unnamed)")), 307 SLICE_ARG(name ? slice_from_cstr(name) : SLICE_LIT("(unnamed)"))); 308 ar->members[n].name = 309 mem.name.len ? pool_intern_slice(l->c->global, mem.name) : 0; 310 ar->members[n].obj = ob; 311 ++n; 312 } 313 kit_ar_iter_free(it); 314 return (LinkInputId)LinkArchives_count( 315 &l->archives); /* opaque non-zero handle */ 316 } 317 318 /* Intern a C-source-level symbol name in the format the input objects 319 * use on the wire. Format-specific mangling (Mach-O `_` prefix, 320 * verbatim everywhere else) lives in obj_format_c_mangle. */ 321 Sym link_intern_c_name(Linker* l, const char* name) { 322 if (!l || !name) return 0; 323 return obj_format_c_mangle(l->c, name); 324 } 325 326 void link_set_entry(Linker* l, KitSlice name) { 327 if (!l || !name.s || name.len == 0) return; 328 /* entry names from the API/script are interned arena/pool slices and 329 * thus NUL-terminated; the mangler scans a C string. */ 330 l->entry_name = link_intern_c_name(l, name.s); 331 } 332 333 void link_clear_entry(Linker* l) { 334 if (!l) return; 335 l->entry_name = 0; 336 } 337 338 void link_set_script(Linker* l, const KitLinkScript* script) { 339 if (!l || !script) return; 340 l->script = script; 341 if (script->entry.s && script->entry.len) 342 l->entry_name = link_intern_c_name(l, script->entry.s); 343 } 344 345 void link_set_extern_resolver(Linker* l, LinkExternResolver fn, void* user) { 346 if (!l) return; 347 l->resolver = fn; 348 l->resolver_user = user; 349 } 350 351 void link_set_gc_sections(Linker* l, int enable) { 352 if (!l) return; 353 l->gc_sections = enable; 354 /* Accepted but ignored this cut. Quiet by design — driver/ld.c may 355 * pass 0 unconditionally and we don't want to noise that. */ 356 } 357 358 void link_set_strip_debug(Linker* l, int enable) { 359 if (!l) return; 360 l->strip_debug = enable; 361 /* Executable layouts already omit non-alloc debug sections. Keep the flag 362 * recorded so driver -S/--strip-debug flows through the linker surface. */ 363 } 364 365 void link_set_emit_static_exe(Linker* l, int enable) { 366 if (!l) return; 367 l->emit_static_exe = enable ? 1 : 0; 368 } 369 370 void link_set_jit_mode(Linker* l, int enable) { 371 if (!l) return; 372 l->jit_mode = enable ? 1 : 0; 373 } 374 375 void link_set_pie(Linker* l, int enable) { 376 if (!l) return; 377 l->emit_pie = enable ? 1 : 0; 378 } 379 380 void link_set_text_base(Linker* l, u64 base) { 381 if (!l) return; 382 l->text_base_set = 1; 383 l->text_base = base; 384 } 385 386 void link_set_pe_subsystem(Linker* l, u16 subsystem) { 387 if (!l) return; 388 l->pe_subsystem = subsystem; 389 } 390 391 void link_set_jit_host(Linker* l, const KitJitHost* host) { 392 if (!l) return; 393 l->jit_host = host; 394 } 395 396 void link_set_interp_path(Linker* l, KitSlice path) { 397 if (!l) return; 398 l->interp_path = 399 (path.s && path.len) ? pool_intern_slice(l->c->global, path) : 0; 400 } 401 402 /* ---- debug-input capture ---- 403 * 404 * Called once at the tail of link_resolve. For each LinkInput, record 405 * its ObjBuilder on the LinkImage so the JIT debug view (kit_jit_view) 406 * can read .debug_* sections after the Linker is freed. Two ownership 407 * regimes: 408 * 409 * LINK_INPUT_OBJ_BYTES: linker owns; transfer to the image and null 410 * the LinkInput's obj so linker_release doesn't double-free. 411 * LINK_INPUT_OBJ: caller owns; borrow the pointer (do not free 412 * at image teardown). Caller is responsible for keeping the 413 * builder alive at least as long as the JIT. 414 * 415 * DSO / archive-only inputs carry no source-level debug info worth 416 * surfacing through kit_jit_view, so their slot stays NULL. */ 417 void link_capture_debug_inputs(Linker* l, LinkImage* img) { 418 u32 n; 419 u32 i; 420 Heap* h; 421 if (!l || !img) return; 422 n = LinkInputs_count(&l->inputs); 423 img->dbg_objs_n = n; 424 if (n == 0) { 425 img->dbg_objs = NULL; 426 img->dbg_objs_owned = NULL; 427 return; 428 } 429 h = img->heap; 430 img->dbg_objs = (ObjBuilder**)h->alloc(h, sizeof(*img->dbg_objs) * n, 431 _Alignof(ObjBuilder*)); 432 img->dbg_objs_owned = (u8*)h->alloc(h, sizeof(*img->dbg_objs_owned) * n, 1u); 433 if (!img->dbg_objs || !img->dbg_objs_owned) 434 compiler_panic(img->c, SRCLOC_NONE, 435 "link_capture_debug_inputs: oom on dbg arrays"); 436 memset(img->dbg_objs, 0, sizeof(*img->dbg_objs) * n); 437 memset(img->dbg_objs_owned, 0, sizeof(*img->dbg_objs_owned) * n); 438 for (i = 0; i < n; ++i) { 439 LinkInput* in = LinkInputs_at(&l->inputs, i); 440 if (!in || !in->obj) continue; 441 switch (in->kind) { 442 case LINK_INPUT_OBJ_BYTES: 443 img->dbg_objs[i] = in->obj; 444 img->dbg_objs_owned[i] = 1u; 445 in->obj = NULL; /* transfer: linker_release must not free it */ 446 break; 447 case LINK_INPUT_OBJ: 448 img->dbg_objs[i] = in->obj; 449 img->dbg_objs_owned[i] = 0u; /* borrowed; caller still owns */ 450 break; 451 default: 452 /* DSO / TBD: skip — no user-level debug sections we expose. */ 453 break; 454 } 455 } 456 } 457 458 /* ---- LinkImage accessors ---- */ 459 460 const LinkSymbol* link_symbol(LinkImage* img, LinkSymId id) { 461 if (!img || id == LINK_SYM_NONE || id > LinkSyms_count(&img->syms)) 462 return NULL; 463 return LinkSyms_at(&img->syms, id - 1); 464 } 465 466 LinkSymId link_symbol_lookup(LinkImage* img, Sym name) { 467 if (!img) return LINK_SYM_NONE; 468 return symhash_get(&img->globals, name); 469 } 470 471 u32 link_segment_count(LinkImage* img) { return img ? img->nsegments : 0; } 472 473 const LinkSegment* link_segment_get(LinkImage* img, u32 id) { 474 if (!img || id == LINK_SEG_NONE || id > img->nsegments) return NULL; 475 return &img->segments[id - 1]; 476 } 477 478 const u8* link_segment_bytes(LinkImage* img, LinkSegmentId id, 479 size_t* size_out) { 480 if (size_out) *size_out = 0; 481 if (!img || id == LINK_SEG_NONE || id > img->nsegments) return NULL; 482 if (size_out) *size_out = (size_t)img->segments[id - 1].file_size; 483 return img->segment_bytes[id - 1]; 484 } 485 486 u32 link_section_count(LinkImage* img) { return img ? img->nsections : 0; } 487 488 const LinkSection* link_section_get(LinkImage* img, LinkSectionId id) { 489 if (!img || id == LINK_SEC_NONE || id > img->nsections) return NULL; 490 return &img->sections[id - 1]; 491 } 492 493 u32 link_reloc_apply_count(LinkImage* img) { 494 return img ? LinkRelocs_count(&img->relocs) : 0; 495 } 496 497 const LinkRelocApply* link_reloc_apply_get(LinkImage* img, u32 id) { 498 if (!img || id >= LinkRelocs_count(&img->relocs)) return NULL; 499 return LinkRelocs_at(&img->relocs, id); 500 } 501 502 /* ---- LinkImage free / cleanup ---- */ 503 504 static void link_image_release(LinkImage* img) { 505 u32 i; 506 if (!img) return; 507 if (img->segment_bytes) { 508 for (i = 0; i < img->nsegments; ++i) { 509 if (img->segment_bytes[i]) 510 img->heap->free(img->heap, img->segment_bytes[i], 511 img->segment_bytes_cap[i]); 512 } 513 img->heap->free(img->heap, img->segment_bytes, 514 sizeof(*img->segment_bytes) * img->nsegments); 515 img->heap->free(img->heap, img->segment_bytes_cap, 516 sizeof(*img->segment_bytes_cap) * img->nsegments); 517 } 518 if (img->segments) 519 img->heap->free(img->heap, img->segments, 520 sizeof(*img->segments) * img->nsegments); 521 if (img->sections) 522 img->heap->free(img->heap, img->sections, 523 sizeof(*img->sections) * img->nsections); 524 LinkSyms_fini(&img->syms); 525 LinkRelocs_fini(&img->relocs); 526 if (img->iplt_pairs) 527 img->heap->free(img->heap, img->iplt_pairs, 528 sizeof(*img->iplt_pairs) * img->niplt * 2u); 529 if (img->input_maps) { 530 for (i = 0; i < img->ninput_maps; ++i) { 531 InputMap* m = &img->input_maps[i]; 532 if (m->sym) img->heap->free(img->heap, m->sym, sizeof(*m->sym) * m->nsym); 533 if (m->section) 534 img->heap->free(img->heap, m->section, 535 sizeof(*m->section) * m->nsection); 536 if (m->atom) 537 img->heap->free(img->heap, m->atom, 538 sizeof(*m->atom) * (m->natom ? m->natom : 1u)); 539 if (m->sym_atom) 540 img->heap->free(img->heap, m->sym_atom, 541 sizeof(*m->sym_atom) * (m->nsym ? m->nsym : 1u)); 542 if (m->reloc_atom) 543 img->heap->free(img->heap, m->reloc_atom, 544 sizeof(*m->reloc_atom) * (m->nreloc ? m->nreloc : 1u)); 545 if (m->section_has_atoms) 546 img->heap->free(img->heap, m->section_has_atoms, 547 m->nsection ? m->nsection : 1u); 548 if (m->section_atom_first) 549 img->heap->free( 550 img->heap, m->section_atom_first, 551 sizeof(*m->section_atom_first) * (m->nsection ? m->nsection : 1u)); 552 if (m->section_atom_count) 553 img->heap->free( 554 img->heap, m->section_atom_count, 555 sizeof(*m->section_atom_count) * (m->nsection ? m->nsection : 1u)); 556 if (m->section_atom_ids) 557 img->heap->free(img->heap, m->section_atom_ids, 558 sizeof(*m->section_atom_ids) * m->nsection_atom_ids); 559 if (m->comdat_discarded) 560 img->heap->free(img->heap, m->comdat_discarded, 561 m->nsection ? m->nsection : 1u); 562 } 563 img->heap->free(img->heap, img->input_maps, 564 sizeof(*img->input_maps) * img->ninput_maps); 565 } 566 if (img->dbg_objs) { 567 for (i = 0; i < img->dbg_objs_n; ++i) { 568 if (img->dbg_objs[i] && img->dbg_objs_owned && img->dbg_objs_owned[i]) 569 obj_free(img->dbg_objs[i]); 570 } 571 img->heap->free(img->heap, img->dbg_objs, 572 sizeof(*img->dbg_objs) * img->dbg_objs_n); 573 if (img->dbg_objs_owned) 574 img->heap->free(img->heap, img->dbg_objs_owned, 575 sizeof(*img->dbg_objs_owned) * img->dbg_objs_n); 576 } 577 if (img->dbg_bytes) { 578 for (i = 0; i < img->dbg_count; ++i) 579 if (img->dbg_bytes[i]) 580 img->heap->free(img->heap, img->dbg_bytes[i], (size_t)img->dbg_size[i]); 581 img->heap->free(img->heap, img->dbg_bytes, 582 sizeof(*img->dbg_bytes) * img->dbg_count); 583 } 584 if (img->dbg_size) 585 img->heap->free(img->heap, img->dbg_size, 586 sizeof(*img->dbg_size) * img->dbg_count); 587 symhash_fini(&img->globals); 588 if (img->dyn) { 589 const ObjFormatImpl* fmt = obj_format_lookup(img->c->target.obj); 590 if (fmt && fmt->free_dyn) fmt->free_dyn(img); 591 } 592 img->heap->free(img->heap, img, sizeof(*img)); 593 } 594 595 static void link_image_cleanup(void* arg) { 596 link_image_release((LinkImage*)arg); 597 } 598 599 LinkImage* link_image_alloc(Compiler* c) { 600 Heap* h = (Heap*)c->ctx->heap; 601 LinkImage* img = (LinkImage*)h->alloc(h, sizeof(*img), _Alignof(LinkImage)); 602 if (!img) compiler_panic(c, SRCLOC_NONE, "link: out of memory allocating image"); 603 memset(img, 0, sizeof(*img)); 604 img->c = c; 605 img->heap = h; 606 LinkSyms_init(&img->syms, h); 607 LinkRelocs_init(&img->relocs, h); 608 symhash_init(&img->globals, h); 609 img->deferred = compiler_defer(c, link_image_cleanup, img); 610 return img; 611 } 612 613 void link_image_free(LinkImage* img) { 614 if (!img) return; 615 if (img->deferred) compiler_undefer(img->c, img->deferred); 616 link_image_release(img); 617 } 618 619 /* ---- Incremental resolution (stubs) ---- 620 * Per-block JIT translation in src/emu/ wants to grow a single 621 * LinkImage as cold blocks land (doc/EMU.md §6). The single-shot 622 * link_resolve discipline (link.h header comment) is set up to 623 * support this — inputs are non-destructively consumed, ObjBuilder* 624 * mappings are stable, resolution is functional. The two entries 625 * below are the surface; the implementation lands alongside the 626 * emu lifter cut. */ 627 628 LinkImage* link_resolve_at(Linker* l, uintptr_t base_va) { 629 (void)base_va; 630 if (!l) return NULL; 631 compiler_panic(l->c, SRCLOC_NONE, 632 "link_resolve_at: incremental resolution not yet " 633 "implemented"); 634 return NULL; 635 } 636 637 void link_resolve_extend(Linker* l, LinkImage* img) { 638 (void)img; 639 if (!l) return; 640 compiler_panic(l->c, SRCLOC_NONE, 641 "link_resolve_extend: incremental resolution not " 642 "yet implemented"); 643 } 644 645 /* ---- public emit dispatcher ---- */ 646 647 void link_emit_image_writer(LinkImage* img, Writer* w) { 648 const ObjFormatImpl* fmt; 649 if (!img || !w) return; 650 fmt = obj_format_lookup(img->c->target.obj); 651 if (fmt && fmt->link_emit) { 652 fmt->link_emit(img, w); 653 return; 654 } 655 compiler_panic(img->c, SRCLOC_NONE, 656 "link_emit_image_writer: unsupported obj format %u", 657 (u32)img->c->target.obj); 658 }