link.c (18037B)
1 /* Public link API entries. 2 * 3 * Thin orchestrators over the Linker primitives in link.c / link_resolve.c / 4 * link_layout.c / link_jit.c. Each entry: 5 * - allocates a Linker against the caller's Compiler, 6 * - feeds in the KitLinkInputs, 7 * - configures lane-specific flags (pie, shared, jit), 8 * - calls link_resolve, 9 * - dispatches to the emit (writer) or JIT-map (kit_jit_from_image) tail. 10 * 11 * The driver's job ends at populating KitLinkInputs; everything below this 12 * line is libkit-internal. */ 13 14 #include "link/link.h" 15 16 #include <kit/core.h> 17 #include <kit/jit.h> 18 #include <kit/link.h> 19 #include <setjmp.h> 20 #include <string.h> 21 22 #include "cg/internal.h" 23 #include "cg/ir_recorder.h" 24 #include "core/core.h" 25 #include "link/link_internal.h" 26 27 KitJit* kit_jit_from_image(LinkImage*); 28 29 static KitStatus link_session_guard(KitLinkSession* s, 30 void (*fn)(KitLinkSession*, void*), 31 void* arg) { 32 PanicFrame panic; 33 if (!s || !s->c || !s->linker || !fn) return KIT_INVALID; 34 compiler_panic_push(s->c, &panic); 35 if (setjmp(panic.env)) { 36 compiler_run_cleanups(s->c); 37 s->linker = NULL; 38 s->image = NULL; 39 compiler_panic_pop(s->c, &panic); 40 return KIT_ERR; 41 } 42 fn(s, arg); 43 compiler_panic_pop(s->c, &panic); 44 return KIT_OK; 45 } 46 47 static KitStatus link_session_remember_publish_obj(KitLinkSession* s, 48 KitObjBuilder* ob) { 49 Heap* h; 50 KitObjBuilder** nb; 51 u32 new_cap; 52 if (!s || !ob) return KIT_INVALID; 53 if (s->npublish_objs < s->publish_objs_cap) { 54 s->publish_objs[s->npublish_objs++] = ob; 55 return KIT_OK; 56 } 57 h = s->c->ctx->heap; 58 new_cap = s->publish_objs_cap ? s->publish_objs_cap * 2u : 8u; 59 nb = (KitObjBuilder**)h->realloc( 60 h, s->publish_objs, sizeof(*s->publish_objs) * s->publish_objs_cap, 61 sizeof(*s->publish_objs) * new_cap, _Alignof(KitObjBuilder*)); 62 if (!nb) return KIT_NOMEM; 63 s->publish_objs = nb; 64 s->publish_objs_cap = new_cap; 65 s->publish_objs[s->npublish_objs++] = ob; 66 return KIT_OK; 67 } 68 69 KitStatus kit_link_session_new(KitCompiler* c, 70 const KitLinkSessionOptions* opts, 71 KitLinkSession** out) { 72 Heap* h; 73 KitLinkSession* s; 74 Linker* l; 75 if (!out) return KIT_INVALID; 76 *out = NULL; 77 if (!c || !opts) return KIT_INVALID; 78 h = c->ctx->heap; 79 l = link_new(c); 80 if (!l) return KIT_NOMEM; 81 s = (KitLinkSession*)h->alloc(h, sizeof(*s), _Alignof(KitLinkSession)); 82 if (!s) { 83 link_free(l); 84 return KIT_NOMEM; 85 } 86 memset(s, 0, sizeof(*s)); 87 s->c = (Compiler*)c; 88 s->linker = l; 89 s->opts = *opts; 90 if (opts->output_kind > KIT_LINK_OUTPUT_JIT) { 91 h->free(h, s, sizeof(*s)); 92 link_free(l); 93 return KIT_INVALID; 94 } 95 if (opts->pe_subsystem != KIT_PE_SUBSYSTEM_DEFAULT && 96 opts->pe_subsystem != KIT_PE_SUBSYSTEM_WINDOWS_GUI && 97 opts->pe_subsystem != KIT_PE_SUBSYSTEM_WINDOWS_CUI) { 98 h->free(h, s, sizeof(*s)); 99 link_free(l); 100 return KIT_INVALID; 101 } 102 link_set_pe_subsystem(l, opts->pe_subsystem); 103 104 switch ((KitLinkOutputKind)opts->output_kind) { 105 case KIT_LINK_OUTPUT_EXE: 106 link_set_emit_static_exe(l, 1); 107 link_set_gc_sections(l, opts->gc_sections); 108 link_set_strip_debug(l, opts->strip_debug); 109 link_set_pie(l, opts->pie); 110 link_set_interp_path(l, opts->interp_path); 111 break; 112 case KIT_LINK_OUTPUT_SHARED: 113 link_set_gc_sections(l, opts->gc_sections); 114 link_set_strip_debug(l, opts->strip_debug); 115 link_set_pie(l, 1); 116 (void)opts->soname; 117 (void)opts->rpaths; 118 (void)opts->nrpaths; 119 (void)opts->runpaths; 120 (void)opts->nrunpaths; 121 (void)opts->exports; 122 (void)opts->nexports; 123 (void)opts->allow_undefined; 124 break; 125 case KIT_LINK_OUTPUT_RELOCATABLE: 126 break; 127 case KIT_LINK_OUTPUT_JIT: 128 if (!opts->jit_host) { 129 h->free(h, s, sizeof(*s)); 130 link_free(l); 131 return KIT_INVALID; 132 } 133 link_set_jit_host(l, opts->jit_host); 134 link_set_jit_mode(l, 1); 135 link_set_gc_sections(l, opts->gc_sections); 136 if (!opts->entry.s || opts->entry.len == 0) link_clear_entry(l); 137 if (opts->extern_resolver) { 138 link_set_extern_resolver(l, opts->extern_resolver, 139 opts->extern_resolver_user); 140 } 141 break; 142 } 143 if (opts->linker_script) link_set_script(l, opts->linker_script); 144 if (opts->text_base_set) link_set_text_base(l, opts->text_base); 145 if (opts->entry.s && opts->entry.len) { 146 link_set_entry(l, opts->entry); 147 } else if (opts->pe_subsystem == KIT_PE_SUBSYSTEM_WINDOWS_GUI && 148 !(opts->linker_script && opts->linker_script->entry.s && 149 opts->linker_script->entry.len)) { 150 link_set_entry(l, KIT_SLICE_LIT("WinMainCRTStartup")); 151 } 152 (void)opts->build_id_mode; 153 (void)opts->build_id_bytes; 154 (void)opts->build_id_len; 155 *out = s; 156 return KIT_OK; 157 } 158 159 typedef struct LinkAddObjArg { 160 KitObjBuilder* ob; 161 } LinkAddObjArg; 162 163 static void link_session_add_obj_inner(KitLinkSession* s, void* arg) { 164 LinkAddObjArg* a = (LinkAddObjArg*)arg; 165 link_add_obj(s->linker, (ObjBuilder*)a->ob); 166 } 167 168 KitStatus kit_link_session_add_obj(KitLinkSession* s, KitObjBuilder* ob) { 169 LinkAddObjArg arg; 170 KitStatus st; 171 if (!s || !ob || s->resolved) return KIT_INVALID; 172 arg.ob = ob; 173 st = link_session_guard(s, link_session_add_obj_inner, &arg); 174 if (st != KIT_OK) return st; 175 return link_session_remember_publish_obj(s, ob); 176 } 177 178 typedef struct LinkAddBytesArg { 179 KitSlice name; 180 const KitSlice* bytes; 181 const KitLinkArchiveInput* archive; 182 } LinkAddBytesArg; 183 184 static void link_session_add_obj_bytes_inner(KitLinkSession* s, void* arg) { 185 LinkAddBytesArg* a = (LinkAddBytesArg*)arg; 186 link_add_obj_bytes(s->linker, a->name.s, a->bytes->data, a->bytes->len); 187 } 188 189 KitStatus kit_link_session_add_obj_bytes(KitLinkSession* s, KitSlice name, 190 const KitSlice* bytes) { 191 LinkAddBytesArg arg; 192 if (!s || !bytes || s->resolved) return KIT_INVALID; 193 arg.name = name; 194 arg.bytes = bytes; 195 arg.archive = NULL; 196 s->non_obj_inputs++; 197 return link_session_guard(s, link_session_add_obj_bytes_inner, &arg); 198 } 199 200 static void link_session_add_archive_bytes_inner(KitLinkSession* s, void* arg) { 201 const KitLinkArchiveInput* a = ((LinkAddBytesArg*)arg)->archive; 202 link_add_archive_bytes(s->linker, a->name.s, a->bytes.data, a->bytes.len, 203 a->whole_archive, a->link_mode, a->group_id); 204 } 205 206 KitStatus kit_link_session_add_archive_bytes( 207 KitLinkSession* s, const KitLinkArchiveInput* archive) { 208 LinkAddBytesArg arg; 209 if (!s || !archive || s->resolved) return KIT_INVALID; 210 arg.bytes = NULL; 211 arg.archive = archive; 212 s->non_obj_inputs++; 213 return link_session_guard(s, link_session_add_archive_bytes_inner, &arg); 214 } 215 216 static void link_session_add_dso_bytes_inner(KitLinkSession* s, void* arg) { 217 LinkAddBytesArg* a = (LinkAddBytesArg*)arg; 218 link_add_dso_bytes(s->linker, a->name.s, a->bytes->data, a->bytes->len); 219 } 220 221 KitStatus kit_link_session_add_dso_bytes(KitLinkSession* s, KitSlice name, 222 const KitSlice* bytes) { 223 LinkAddBytesArg arg; 224 if (!s || !bytes || s->resolved) return KIT_INVALID; 225 arg.name = name; 226 arg.bytes = bytes; 227 arg.archive = NULL; 228 s->non_obj_inputs++; 229 return link_session_guard(s, link_session_add_dso_bytes_inner, &arg); 230 } 231 232 typedef struct LinkLtoPreserveArg { 233 KitObjBuilder* lto_obj; 234 KitCg* lto_cg; 235 KitLinkLtoPreservedCallback cb; 236 void* user; 237 } LinkLtoPreserveArg; 238 239 typedef struct LinkLtoRefMark { 240 ObjSymId sym; 241 u8 referenced; 242 u8 pad[3]; 243 } LinkLtoRefMark; 244 245 typedef struct LinkLtoRefMarks { 246 Compiler* c; 247 ObjBuilder* ob; 248 LinkLtoRefMark* marks; 249 u32 nmarks; 250 u32 cap; 251 } LinkLtoRefMarks; 252 253 static int link_lto_sym_is_logical_undef(const ObjSym* s) { 254 return s && s->section_id == OBJ_SEC_NONE && s->kind != SK_ABS && 255 s->kind != SK_COMMON; 256 } 257 258 static int link_lto_sym_is_preservable_def(const ObjSym* s) { 259 return s && !s->removed && s->name != 0 && s->bind != SB_LOCAL && 260 link_sym_is_def(s); 261 } 262 263 static void link_lto_preserve_name(LinkLtoPreserveArg* a, Sym name) { 264 ObjSymIter* it; 265 ObjSymEntry e; 266 if (!a || !name) return; 267 it = obj_symiter_new((ObjBuilder*)a->lto_obj); 268 while (it && obj_symiter_next(it, &e)) { 269 const ObjSym* s = e.sym; 270 if (!s || s->name != name) continue; 271 if (link_lto_sym_is_preservable_def(s)) a->cb(a->user, (KitCgSym)e.id); 272 } 273 if (it) obj_symiter_free(it); 274 } 275 276 static int link_lto_sym_in_preserved_section(ObjBuilder* ob, ObjSymId sym, 277 const ObjSym* s) { 278 const Section* sec; 279 const ObjAtom* atom; 280 ObjAtomId aid; 281 if (!ob || !s) return 0; 282 if (s->section_id == OBJ_SEC_NONE) return 0; 283 sec = obj_section_get(ob, s->section_id); 284 if (sec && ((sec->flags & SF_RETAIN) || sec->sem == SSEM_INIT_ARRAY || 285 sec->sem == SSEM_FINI_ARRAY || sec->sem == SSEM_PREINIT_ARRAY)) 286 return 1; 287 aid = obj_atom_find_symbol(ob, sym); 288 atom = obj_atom_get(ob, aid); 289 return atom && (atom->flags & OBJ_ATOM_RETAIN); 290 } 291 292 static void link_lto_refmarks_add(LinkLtoRefMarks* marks, ObjSymId sym, 293 const ObjSym* s) { 294 Heap* h; 295 LinkLtoRefMark* nm; 296 u32 ncap; 297 if (!marks || sym == OBJ_SYM_NONE || !s) return; 298 for (u32 i = 0; i < marks->nmarks; ++i) 299 if (marks->marks[i].sym == sym) return; 300 if (marks->nmarks == marks->cap) { 301 h = marks->c->ctx->heap; 302 ncap = marks->cap ? marks->cap * 2u : 32u; 303 nm = (LinkLtoRefMark*)h->realloc(h, marks->marks, 304 sizeof(*marks->marks) * marks->cap, 305 sizeof(*marks->marks) * ncap, 306 _Alignof(LinkLtoRefMark)); 307 if (!nm) 308 compiler_panic(marks->c, SRCLOC_NONE, 309 "link: oom on LTO semantic-ref marks"); 310 marks->marks = nm; 311 marks->cap = ncap; 312 } 313 marks->marks[marks->nmarks].sym = sym; 314 marks->marks[marks->nmarks].referenced = s->referenced ? 1u : 0u; 315 marks->nmarks++; 316 } 317 318 static void link_lto_mark_refset(ObjBuilder* ob, const ObjSymSet* refs, 319 LinkLtoRefMarks* marks) { 320 if (!ob || !refs || !refs->cap) return; 321 for (u32 i = 0; i < refs->cap; ++i) { 322 ObjSymId sym = refs->slots[i].k; 323 const ObjSym* s; 324 if (sym == OBJ_SYM_NONE) continue; 325 s = obj_symbol_get(ob, sym); 326 if (link_lto_sym_is_logical_undef(s)) { 327 link_lto_refmarks_add(marks, sym, s); 328 obj_sym_mark_referenced(ob, sym); 329 } 330 } 331 } 332 333 static int link_lto_module_has_asm(const CgIrModule* module) { 334 if (!module) return 0; 335 if (module->nfile_scope_asms) return 1; 336 for (u32 i = 0; i < module->nfuncs; ++i) { 337 const CgIrFunc* f = module->funcs[i]; 338 if (!f || f->removed) continue; 339 for (u32 k = 0; k < f->ninsts; ++k) 340 if (f->insts[k].op == CG_IR_ASM_BLOCK) return 1; 341 } 342 return 0; 343 } 344 345 static void link_lto_mark_semantic_refs(LinkLtoPreserveArg* a, 346 LinkLtoRefMarks* marks) { 347 ObjBuilder* ob = (ObjBuilder*)a->lto_obj; 348 const CgIrModule* module; 349 if (!a->lto_cg || !a->lto_cg->target) return; 350 module = cg_ir_recorder_module(a->lto_cg->target); 351 if (!module) return; 352 for (u32 i = 0; i < module->nfuncs; ++i) { 353 const CgIrFunc* f = module->funcs[i]; 354 if (!f || f->removed) continue; 355 link_lto_mark_refset(ob, &f->call_refs, marks); 356 link_lto_mark_refset(ob, &f->global_refs, marks); 357 } 358 } 359 360 static void link_lto_refmarks_restore(LinkLtoRefMarks* marks) { 361 if (!marks || !marks->ob) return; 362 for (u32 i = 0; i < marks->nmarks; ++i) { 363 obj_sym_set_referenced(marks->ob, marks->marks[i].sym, 364 marks->marks[i].referenced); 365 } 366 } 367 368 static void link_lto_refmarks_fini(LinkLtoRefMarks* marks) { 369 Heap* h; 370 if (!marks || !marks->marks) return; 371 h = marks->c->ctx->heap; 372 h->free(h, marks->marks, sizeof(*marks->marks) * marks->cap); 373 memset(marks, 0, sizeof(*marks)); 374 } 375 376 static void link_lto_preserve_intrinsic_roots(KitLinkSession* s, 377 LinkLtoPreserveArg* a) { 378 ObjBuilder* ob = (ObjBuilder*)a->lto_obj; 379 const CgIrModule* module = NULL; 380 int preserve_all_nonlocal = 0; 381 ObjSymIter* it; 382 ObjSymEntry e; 383 384 if (a->lto_cg && a->lto_cg->target) 385 module = cg_ir_recorder_module(a->lto_cg->target); 386 387 preserve_all_nonlocal = s->opts.output_kind != KIT_LINK_OUTPUT_EXE || 388 link_lto_module_has_asm(module); 389 if (s->opts.output_kind == KIT_LINK_OUTPUT_SHARED) preserve_all_nonlocal = 1; 390 391 it = obj_symiter_new(ob); 392 while (it && obj_symiter_next(it, &e)) { 393 const ObjSym* os = e.sym; 394 if (!link_lto_sym_is_preservable_def(os)) continue; 395 if (preserve_all_nonlocal || os->bind == SB_WEAK || os->kind == SK_IFUNC || 396 (os->flags & KIT_CG_SYM_USED) || 397 link_lto_sym_in_preserved_section(ob, e.id, os)) { 398 a->cb(a->user, (KitCgSym)e.id); 399 } 400 } 401 if (it) obj_symiter_free(it); 402 403 if (s->linker->entry_name) link_lto_preserve_name(a, s->linker->entry_name); 404 for (u32 i = 0; i < s->opts.nexports; ++i) { 405 const KitSlice* ex = &s->opts.exports[i]; 406 if (ex->s && ex->len) 407 link_lto_preserve_name( 408 a, 409 pool_intern_slice(s->c->global, (Slice){.s = ex->s, .len = ex->len})); 410 } 411 } 412 413 static void link_lto_preserve_opaque_undef_refs(KitLinkSession* s, 414 LinkLtoPreserveArg* a) { 415 u32 ninputs = LinkInputs_count(&s->linker->inputs); 416 for (u32 ii = 0; ii < ninputs; ++ii) { 417 LinkInput* in = LinkInputs_at(&s->linker->inputs, ii); 418 ObjSymIter* it; 419 ObjSymEntry e; 420 if (!in || !in->obj || in->obj == (ObjBuilder*)a->lto_obj) continue; 421 it = obj_symiter_new(in->obj); 422 while (it && obj_symiter_next(it, &e)) { 423 const ObjSym* os = e.sym; 424 if (!os || os->name == 0 || os->bind == SB_LOCAL) continue; 425 if (link_sym_is_spurious_undef(os)) continue; 426 if (!link_lto_sym_is_logical_undef(os)) continue; 427 link_lto_preserve_name(a, os->name); 428 } 429 if (it) obj_symiter_free(it); 430 } 431 } 432 433 static void link_session_visit_lto_preserved_inner(KitLinkSession* s, 434 void* arg) { 435 LinkLtoPreserveArg* a = (LinkLtoPreserveArg*)arg; 436 LinkLtoRefMarks marks; 437 memset(&marks, 0, sizeof marks); 438 marks.c = s->c; 439 marks.ob = (ObjBuilder*)a->lto_obj; 440 if (s->opts.output_kind != KIT_LINK_OUTPUT_RELOCATABLE) { 441 /* Archive selection needs pre-finish semantic refs, but those refs may 442 * disappear after LTO internalization/DCE. Borrow ObjSym::referenced only 443 * for archive ingestion, then restore it before CG finish. */ 444 link_lto_mark_semantic_refs(a, &marks); 445 link_ingest_archives(s->linker); 446 link_lto_refmarks_restore(&marks); 447 link_lto_refmarks_fini(&marks); 448 } 449 link_lto_preserve_intrinsic_roots(s, a); 450 link_lto_preserve_opaque_undef_refs(s, a); 451 } 452 453 KitStatus kit_link_session_visit_lto_preserved(KitLinkSession* s, 454 KitObjBuilder* lto_obj, 455 KitCg* lto_cg, 456 KitLinkLtoPreservedCallback cb, 457 void* user) { 458 LinkLtoPreserveArg arg; 459 if (!s || !lto_obj || !lto_cg || !cb || s->resolved) return KIT_INVALID; 460 memset(&arg, 0, sizeof arg); 461 arg.lto_obj = lto_obj; 462 arg.lto_cg = lto_cg; 463 arg.cb = cb; 464 arg.user = user; 465 return link_session_guard(s, link_session_visit_lto_preserved_inner, &arg); 466 } 467 468 static void link_session_resolve_inner(KitLinkSession* s, void* arg) { 469 (void)arg; 470 if ((KitLinkOutputKind)s->opts.output_kind == KIT_LINK_OUTPUT_RELOCATABLE) { 471 s->resolved = 1; 472 return; 473 } 474 s->image = link_resolve(s->linker); 475 s->resolved = 1; 476 } 477 478 KitStatus kit_link_session_resolve(KitLinkSession* s) { 479 if (!s || s->resolved) return KIT_INVALID; 480 return link_session_guard(s, link_session_resolve_inner, NULL); 481 } 482 483 typedef struct LinkEmitArg { 484 KitWriter* out; 485 } LinkEmitArg; 486 487 static void link_session_emit_inner(KitLinkSession* s, void* arg) { 488 KitWriter* out = ((LinkEmitArg*)arg)->out; 489 if ((KitLinkOutputKind)s->opts.output_kind == KIT_LINK_OUTPUT_RELOCATABLE) { 490 link_emit_relocatable_writer(s->linker, out); 491 } else { 492 link_emit_image_writer(s->image, out); 493 } 494 } 495 496 KitStatus kit_link_session_emit(KitLinkSession* s, KitWriter* out) { 497 LinkEmitArg arg; 498 KitStatus st; 499 if (!s || !out) return KIT_INVALID; 500 if (!s->resolved) { 501 st = kit_link_session_resolve(s); 502 if (st != KIT_OK) return st; 503 } 504 if ((KitLinkOutputKind)s->opts.output_kind == KIT_LINK_OUTPUT_JIT) 505 return KIT_INVALID; 506 arg.out = out; 507 return link_session_guard(s, link_session_emit_inner, &arg); 508 } 509 510 typedef struct LinkJitArg { 511 KitJit* jit; 512 } LinkJitArg; 513 514 static void link_session_jit_inner(KitLinkSession* s, void* arg) { 515 LinkJitArg* a = (LinkJitArg*)arg; 516 a->jit = kit_jit_from_image(s->image); 517 if (a->jit) { 518 s->image = NULL; 519 s->linker_transferred = 1; 520 s->linker = NULL; 521 } 522 } 523 524 KitStatus kit_link_session_jit(KitLinkSession* s, KitJit** out_jit) { 525 LinkJitArg arg; 526 KitStatus st; 527 if (!out_jit) return KIT_INVALID; 528 *out_jit = NULL; 529 if (!s || (KitLinkOutputKind)s->opts.output_kind != KIT_LINK_OUTPUT_JIT) 530 return KIT_INVALID; 531 if (!s->resolved) { 532 st = kit_link_session_resolve(s); 533 if (st != KIT_OK) return st; 534 } 535 arg.jit = NULL; 536 st = link_session_guard(s, link_session_jit_inner, &arg); 537 if (st != KIT_OK) return st; 538 if (!arg.jit) return KIT_ERR; 539 *out_jit = arg.jit; 540 return KIT_OK; 541 } 542 543 void kit_link_session_free(KitLinkSession* s) { 544 Heap* h; 545 if (!s) return; 546 h = s->c->ctx->heap; 547 if (s->image) link_image_free(s->image); 548 if (s->linker) link_free(s->linker); 549 if (s->publish_objs) { 550 h->free(h, s->publish_objs, sizeof(*s->publish_objs) * s->publish_objs_cap); 551 } 552 h->free(h, s, sizeof(*s)); 553 }