ld.c (64367B)
1 #include <kit/core.h> 2 #include <kit/link.h> 3 #include <kit/object.h> 4 #include <stdint.h> 5 #include <string.h> 6 7 #include "driver.h" 8 #include "hosted.h" 9 #include "lib_resolve.h" 10 #include "runtime.h" 11 12 /* `kit ld` — link object/archive inputs into an executable, shared 13 * library, or relocatable object. The driver loads each input via 14 * env.file_io, optionally parses a `-T` linker script into the structured 15 * form, and calls the public link APIs directly so the full link surface 16 * (per-archive flags, group cycling, build-id, soname/rpath/exports) is 17 * reachable without thickening the convenience KitOptions struct. 18 * 19 * Supported flags: 20 * -o out output path (required, exactly one) 21 * -e symbol entry symbol 22 * -T script.ld linker script (parsed, not raw) 23 * --support-dir DIR kit support root for compiler rt 24 * --sysroot DIR hosted C runtime/sysroot root 25 * -L dir library search path (-l targets) 26 * -l c enable hosted CRT/libc expansion 27 * -l name resolves via -L (.so preferred unless 28 * -Bstatic/-static) 29 * -static / -pie / -no-pie target.pic 30 * -shared emit a shared library / dylib 31 * -r / --relocatable emit a relocatable partial-link object 32 * -soname NAME DT_SONAME / LC_ID_DYLIB 33 * -rpath DIR DT_RPATH/DT_RUNPATH entry (repeatable) 34 * -rpath-link DIR shared-lib search at link time 35 * (repeatable; accepted, currently advisory) 36 * --enable-new-dtags rpath entries emit as DT_RUNPATH 37 * (default) 38 * --disable-new-dtags rpath entries emit as DT_RPATH 39 * -E / --export-dynamic promote all defined globals to the 40 * dynamic symbol table 41 * --whole-archive / --no-whole-archive 42 * positional state for following .a 43 * --gc-sections / --no-gc-sections drop unreferenced sections 44 * -Bstatic / -Bdynamic positional link-mode for following .a 45 * --as-needed / --no-as-needed positional link-mode for following .a 46 * --start-group / --end-group cyclic-resolution group of archives 47 * --build-id={none|sha256|uuid|0xHEX} 48 */ 49 50 #define LD_TOOL "ld" 51 52 /* Per-archive metadata mirroring the relevant subset of 53 * KitLinkArchiveInput plus driver-side ownership info. */ 54 typedef struct LdArchive { 55 const char* path; /* path used for both open and KitSliceInput.name */ 56 int owned; /* 1 if `path` was alloc'd by lib_resolve */ 57 size_t owned_size; /* allocation size (for driver_free) */ 58 uint8_t whole_archive; /* nonzero == --whole-archive */ 59 uint8_t link_mode; /* KitLinkMode (-Bstatic/-Bdynamic/--as-needed) */ 60 uint8_t group_id; /* cyclic resolution group id; 0 = single-pass */ 61 } LdArchive; 62 63 /* Per-DSO ownership info. The DSO bytes are loaded straight off disk 64 * via env->file_io into the KitSlice passed to libkit; only 65 * the path itself may need to be free'd if it came from -l<name> 66 * resolution. */ 67 typedef struct LdDso { 68 const char* path; /* path used for both open and KitSliceInput.name */ 69 int owned; /* 1 if `path` was alloc'd by lib_resolve */ 70 size_t owned_size; /* allocation size (for driver_free) */ 71 } LdDso; 72 73 typedef struct LdOptions { 74 DriverEnv* env; 75 const char* driver_path; 76 size_t argv_bound; 77 78 KitTargetSpec target; 79 80 const char* output_path; /* -o */ 81 int output_seen; 82 const char* entry; /* -e */ 83 const char* script_path; /* -T */ 84 int text_base_set; /* -Ttext seen */ 85 uint64_t text_base; /* -Ttext ADDR: static ET_EXEC image base */ 86 int no_default_libs; /* -nostdlib / --no-default-libs */ 87 int pic_explicit; /* -static / -pie / -no-pie / -shared seen */ 88 const char* support_dir; /* --support-dir */ 89 const char* sysroot; /* --sysroot / KIT_SYSROOT */ 90 uint16_t pe_subsystem; /* KitPeSubsystem */ 91 /* PT_INTERP path. NULL means "let libkit pick the target default 92 * (e.g. /lib/ld-musl-aarch64.so.1)". Set by -dynamic-linker / 93 * --dynamic-linker. */ 94 const char* interp_path; 95 int pie; /* -pie was requested */ 96 97 const char** object_files; 98 uint32_t nobject_files; 99 100 LdArchive* archives; 101 uint32_t narchives; 102 103 /* Shared-object inputs (positional .so / .so.N or `-l<name>` under 104 * -Bdynamic). The runtime loader resolves these by SONAME at link 105 * time → DT_NEEDED entries. */ 106 LdDso* dsos; 107 uint32_t ndsos; 108 KitLinkInputOrder* order; 109 uint32_t norder; 110 111 const char** lib_dirs; /* -L */ 112 uint32_t nlib_dirs; 113 char** owned_paths; /* sysroot-expanded argv/search paths */ 114 size_t* owned_path_sizes; 115 uint32_t nowned_paths; 116 117 /* Shared-library output state. */ 118 int shared; /* -shared */ 119 int relocatable; /* -r / --relocatable */ 120 const char* soname; /* -soname NAME */ 121 const char** rpaths; /* -rpath DIR (repeatable) */ 122 uint32_t nrpaths; 123 const char** rpath_links; /* -rpath-link DIR (advisory) */ 124 uint32_t nrpath_links; 125 int new_dtags; /* 1=DT_RUNPATH (default), 0=DT_RPATH */ 126 int export_dynamic; /* -E / --export-dynamic */ 127 int gc_sections; /* --gc-sections / --no-gc-sections */ 128 int strip_debug; /* -S / --strip-debug */ 129 int allow_undefined; /* shared output undefined-symbol policy */ 130 int static_link; /* -static: hosted libc should pick static profile */ 131 int wants_hosted_libc; /* -lc: expand crt + libc through hosted resolver */ 132 DriverHostedPlan hosted; 133 134 /* --build-id state */ 135 uint8_t build_id_mode; /* KitBuildIdMode */ 136 uint8_t* build_id_bytes; /* USER mode: parsed hex, owned */ 137 uint32_t build_id_len; 138 size_t build_id_alloc; /* allocation size for free */ 139 140 /* Mutable parse state for positional archive flags / groups. */ 141 uint8_t cur_whole_archive; /* pending --whole-archive flag */ 142 uint8_t cur_link_mode; /* KitLinkMode for following inputs */ 143 uint8_t cur_group_id; /* 0 outside any --start-group */ 144 uint8_t next_group_id; /* increments on --start-group */ 145 146 /* Opt-in: treat `/...` arguments as MSVC link.exe flags. Off by 147 * default so legacy paths like `/usr/lib/foo.o` remain inputs. */ 148 int ms_link_driver; 149 } LdOptions; 150 151 static void ld_usage(void) { 152 driver_errf(LD_TOOL, "%.*s", 153 KIT_SLICE_ARG(KIT_SLICE_LIT( 154 "usage: kit ld -o out [options...] inputs.o|inputs.a...\n" 155 " kit ld --help for full option reference"))); 156 } 157 158 void driver_help_ld(void) { 159 driver_printf( 160 "%.*s", 161 KIT_SLICE_ARG(KIT_SLICE_LIT( 162 "kit ld — link objects/archives into an executable or shared " 163 "library\n" 164 "\n" 165 "USAGE\n" 166 " kit ld -o OUT [options] inputs.o ... inputs.a ...\n" 167 " kit ld -shared -o libfoo.so [options] inputs.o ...\n" 168 " kit ld -r -o partial.o inputs.o ...\n" 169 "\n" 170 "DESCRIPTION\n" 171 " Loads each input via host file I/O, optionally parses a -T " 172 "linker\n" 173 " script, and emits an executable (default) or shared library\n" 174 " (-shared). The full link surface is exposed: per-archive flags,\n" 175 " cyclic-resolution groups, build-id, soname/rpath/exports.\n" 176 "\n" 177 "OUTPUT\n" 178 " -o PATH Output path (required, exactly one)\n" 179 " -shared Emit a position-independent shared " 180 "library " 181 "/\n" 182 " dylib instead of an executable\n" 183 " -r, --relocatable Emit a relocatable partial-link object\n" 184 "\n" 185 "ENTRY / SCRIPT\n" 186 " -e SYMBOL Entry symbol\n" 187 " --subsystem NAME PE subsystem: console or windows\n" 188 " -T SCRIPT.ld Use a linker script (parsed, not raw)\n" 189 "\n" 190 "TARGET\n" 191 " -static Non-PIC, non-PIE\n" 192 " -pie Position-independent executable\n" 193 " -no-pie Disable PIE\n" 194 " --support-dir DIR kit support root for compiler " 195 "runtime\n" 196 " --sysroot DIR hosted C runtime/sysroot root\n" 197 " (target is otherwise auto-detected from the first object input)\n" 198 "\n" 199 "LIBRARY RESOLUTION\n" 200 " -L DIR Add library search path\n" 201 " -l c Add hosted CRT objects and libc\n" 202 " -l NAME Resolve via -L (.so preferred unless " 203 "static)\n" 204 "\n" 205 "POSITIONAL ARCHIVE STATE (apply to following .a inputs)\n" 206 " --whole-archive Pull every member of following " 207 "archives\n" 208 " --no-whole-archive Reset (default behaviour)\n" 209 " -Bstatic Force static link mode\n" 210 " -Bdynamic Force dynamic link mode\n" 211 " --as-needed Link only if a real reference exists\n" 212 " --no-as-needed Reset to dynamic\n" 213 " --start-group ...\n" 214 " --end-group Cyclic-resolution archive group\n" 215 "\n" 216 "SHARED-LIBRARY OPTIONS (require -shared)\n" 217 " -soname NAME DT_SONAME / LC_ID_DYLIB\n" 218 " -soname=NAME equivalent attached form\n" 219 " -rpath DIR DT_RPATH/DT_RUNPATH entry (repeatable)\n" 220 " -rpath=DIR attached form\n" 221 " -rpath-link DIR Link-time-only search path (advisory)\n" 222 " --enable-new-dtags rpaths land in DT_RUNPATH (default)\n" 223 " --disable-new-dtags rpaths land in DT_RPATH\n" 224 "\n" 225 "SECTION GC\n" 226 " --gc-sections Drop sections unreferenced from the " 227 "entry\n" 228 " symbol, init/fini arrays, " 229 "SHF_GNU_RETAIN,\n" 230 " and __start_/__stop_ section " 231 "references\n" 232 " --no-gc-sections Disable section GC (default)\n" 233 " -E, --export-dynamic Promote defined globals into dynsym\n" 234 " (no-op for -shared; recorded for exe)\n" 235 " -S, --strip-debug Omit debug info from linked output\n" 236 " --no-undefined Reject unresolved symbols in -shared " 237 "output\n" 238 " -z defs Same as --no-undefined\n" 239 "\n" 240 "BUILD ID\n" 241 " --build-id Same as --build-id=sha256\n" 242 " --build-id=MODE none | sha256 | uuid | 0xHEX\n" 243 "\n" 244 "GETTING HELP\n" 245 " -h, --help Show this help and exit\n" 246 "\n" 247 "EXIT CODES\n" 248 " 0 success 1 link error 2 bad usage\n"))); 249 } 250 251 /* ---------- argv-sized scratch arrays ---------- */ 252 253 static int ld_alloc_arrays(LdOptions* o, int argc) { 254 size_t bound = (size_t)argc + 32u; 255 o->argv_bound = bound; 256 o->object_files = 257 driver_alloc_zeroed(o->env, bound * sizeof(*o->object_files)); 258 o->archives = driver_alloc_zeroed(o->env, bound * sizeof(*o->archives)); 259 o->dsos = driver_alloc_zeroed(o->env, bound * sizeof(*o->dsos)); 260 o->order = driver_alloc_zeroed(o->env, bound * sizeof(*o->order)); 261 o->lib_dirs = driver_alloc_zeroed(o->env, bound * sizeof(*o->lib_dirs)); 262 o->owned_paths = driver_alloc_zeroed(o->env, bound * sizeof(*o->owned_paths)); 263 o->owned_path_sizes = 264 driver_alloc_zeroed(o->env, bound * sizeof(*o->owned_path_sizes)); 265 o->rpaths = driver_alloc_zeroed(o->env, bound * sizeof(*o->rpaths)); 266 o->rpath_links = driver_alloc_zeroed(o->env, bound * sizeof(*o->rpath_links)); 267 if (!o->object_files || !o->archives || !o->dsos || !o->order || 268 !o->lib_dirs || !o->owned_paths || !o->owned_path_sizes || !o->rpaths || 269 !o->rpath_links) { 270 driver_errf(LD_TOOL, "out of memory"); 271 return 1; 272 } 273 o->new_dtags = 1; 274 o->allow_undefined = 1; 275 return 0; 276 } 277 278 /* ---------- positional archive bookkeeping ---------- */ 279 280 static void ld_push_order(LdOptions* o, uint8_t kind, uint32_t index) { 281 KitLinkInputOrder* slot = &o->order[o->norder++]; 282 slot->kind = kind; 283 slot->index = index; 284 } 285 286 static void ld_insert_order(LdOptions* o, uint32_t pos, uint8_t kind, 287 uint32_t index) { 288 uint32_t i; 289 if (pos > o->norder) pos = o->norder; 290 for (i = o->norder; i > pos; --i) o->order[i] = o->order[i - 1u]; 291 o->order[pos].kind = kind; 292 o->order[pos].index = index; 293 o->norder++; 294 } 295 296 static void ld_push_object(LdOptions* o, const char* path) { 297 o->object_files[o->nobject_files++] = path; 298 ld_push_order(o, KIT_LINK_INPUT_OBJ_BYTES, o->nobject_files - 1u); 299 } 300 301 static void ld_insert_object(LdOptions* o, const char* path, uint32_t pos) { 302 o->object_files[o->nobject_files++] = path; 303 ld_insert_order(o, pos, KIT_LINK_INPUT_OBJ_BYTES, o->nobject_files - 1u); 304 } 305 306 static void ld_push_archive(LdOptions* o, const char* path, int owned, 307 size_t owned_size) { 308 LdArchive* a = &o->archives[o->narchives++]; 309 a->path = path; 310 a->owned = owned; 311 a->owned_size = owned_size; 312 a->whole_archive = o->cur_whole_archive; 313 a->link_mode = o->cur_link_mode; 314 a->group_id = o->cur_group_id; 315 ld_push_order(o, KIT_LINK_INPUT_ARCHIVE, o->narchives - 1u); 316 } 317 318 static void ld_push_runtime_archive(LdOptions* o, DriverRuntimeArchive* rt) { 319 LdArchive* a = &o->archives[o->narchives++]; 320 a->path = rt->path; 321 a->owned = 1; 322 a->owned_size = rt->path_size; 323 a->whole_archive = rt->whole_archive; 324 a->link_mode = rt->link_mode; 325 a->group_id = rt->group_id; 326 rt->path = NULL; 327 rt->path_size = 0; 328 ld_push_order(o, KIT_LINK_INPUT_ARCHIVE, o->narchives - 1u); 329 } 330 331 static void ld_push_dso(LdOptions* o, const char* path, int owned, 332 size_t owned_size) { 333 LdDso* d = &o->dsos[o->ndsos++]; 334 d->path = path; 335 d->owned = owned; 336 d->owned_size = owned_size; 337 ld_push_order(o, KIT_LINK_INPUT_DSO, o->ndsos - 1u); 338 } 339 340 /* Filename ends in `.so` (with no further extension) or in `.so.N` 341 * for some run of digits and dots. */ 342 static int driver_is_so_filename(const char* path) { 343 size_t n = driver_strlen(path); 344 size_t i; 345 /* Walk from the end: trim trailing ".N" / ".N.N" sequences if any, 346 * then check that we land on ".so". */ 347 i = n; 348 while (i > 0) { 349 /* Strip a trailing ".<digits>" cluster (e.g. ".1", ".26"). */ 350 size_t end = i; 351 size_t j = i; 352 while (j > 0) { 353 char c = path[j - 1]; 354 if (c >= '0' && c <= '9') { 355 --j; 356 continue; 357 } 358 break; 359 } 360 if (j < end && j > 0 && path[j - 1] == '.') { 361 i = j - 1; 362 continue; 363 } 364 break; 365 } 366 if (i >= 3 && path[i - 3] == '.' && path[i - 2] == 's' && path[i - 1] == 'o') 367 return 1; 368 return 0; 369 } 370 371 static char* ld_join2(DriverEnv* env, const char* a, const char* b, 372 size_t* out_size) { 373 size_t alen = driver_strlen(a); 374 size_t blen = driver_strlen(b); 375 size_t slash = (alen > 0 && a[alen - 1] != '/') ? 1u : 0u; 376 size_t bytes = alen + slash + blen + 1u; 377 char* out = driver_alloc(env, bytes); 378 size_t off = 0; 379 if (!out) return NULL; 380 if (alen) { 381 driver_memcpy(out + off, a, alen); 382 off += alen; 383 } 384 if (slash) out[off++] = '/'; 385 if (blen) { 386 driver_memcpy(out + off, b, blen); 387 off += blen; 388 } 389 out[off] = '\0'; 390 if (out_size) *out_size = bytes; 391 return out; 392 } 393 394 static int ld_own_path(LdOptions* o, char* path, size_t size, 395 const char** out) { 396 if (!path) { 397 driver_errf(LD_TOOL, "out of memory"); 398 return 1; 399 } 400 if (o->nowned_paths >= o->argv_bound) { 401 driver_free(o->env, path, size); 402 driver_errf(LD_TOOL, "too many sysroot-expanded paths"); 403 return 1; 404 } 405 o->owned_paths[o->nowned_paths] = path; 406 o->owned_path_sizes[o->nowned_paths] = size; 407 o->nowned_paths++; 408 if (out) *out = path; 409 return 0; 410 } 411 412 static int ld_add_sysroot_libdir(LdOptions* o) { 413 char* path; 414 size_t size; 415 const char* owned; 416 if (!o->sysroot || !o->sysroot[0]) return 0; 417 path = ld_join2(o->env, o->sysroot, "lib", &size); 418 if (ld_own_path(o, path, size, &owned) != 0) return 1; 419 o->lib_dirs[o->nlib_dirs++] = owned; 420 return 0; 421 } 422 423 static int ld_sysroot_rewrite_path(LdOptions* o, const char* path, 424 const char** out) { 425 const char* tail; 426 char* joined; 427 size_t size; 428 if (!path || path[0] != '=' || !o->sysroot || !o->sysroot[0]) { 429 *out = path; 430 return 0; 431 } 432 tail = path + 1; 433 if (tail[0] == '/') tail++; 434 joined = ld_join2(o->env, o->sysroot, tail, &size); 435 return ld_own_path(o, joined, size, out); 436 } 437 438 static int ld_note_library_request(LdOptions* o, const char* name) { 439 if (driver_streq(name, "c") && !o->no_default_libs) { 440 o->wants_hosted_libc = 1; 441 return 1; 442 } 443 return 0; 444 } 445 446 /* ---------- --build-id parsing ---------- */ 447 448 static int hex_nibble(char c) { 449 if (c >= '0' && c <= '9') return c - '0'; 450 if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); 451 if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); 452 return -1; 453 } 454 455 /* Parse a -Ttext address: 0x<hex> or decimal. Returns 0 on success. */ 456 static int ld_parse_addr(const char* s, uint64_t* out) { 457 uint64_t v = 0; 458 const char* p; 459 if (!s || !s[0]) return 1; 460 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { 461 p = s + 2; 462 if (!*p) return 1; 463 for (; *p; ++p) { 464 int n = hex_nibble(*p); 465 if (n < 0) return 1; 466 v = (v << 4) | (uint64_t)n; 467 } 468 } else { 469 for (p = s; *p; ++p) { 470 if (*p < '0' || *p > '9') return 1; 471 v = v * 10u + (uint64_t)(*p - '0'); 472 } 473 } 474 *out = v; 475 return 0; 476 } 477 478 /* Parse `--build-id=...` argument into options. Accepts "none", "sha256", 479 * "uuid", or "0x<even-hex>". Returns 0 on success, 1 on bad value. */ 480 static int ld_parse_build_id(LdOptions* o, const char* val) { 481 if (driver_streq(val, "none")) { 482 o->build_id_mode = KIT_BUILDID_NONE; 483 return 0; 484 } 485 if (driver_streq(val, "sha256")) { 486 o->build_id_mode = KIT_BUILDID_SHA256; 487 return 0; 488 } 489 if (driver_streq(val, "uuid")) { 490 o->build_id_mode = KIT_BUILDID_UUID; 491 return 0; 492 } 493 494 /* "0x<hex>" — must be even number of hex digits, at least one byte. */ 495 if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) { 496 const char* hex = val + 2; 497 size_t hex_len = driver_strlen(hex); 498 size_t nbytes; 499 size_t i; 500 uint8_t* buf; 501 if (hex_len == 0 || (hex_len & 1u)) { 502 driver_errf(LD_TOOL, 503 "--build-id=0xHEX requires an even number of hex digits"); 504 return 1; 505 } 506 nbytes = hex_len / 2; 507 buf = driver_alloc(o->env, nbytes); 508 if (!buf) { 509 driver_errf(LD_TOOL, "out of memory"); 510 return 1; 511 } 512 for (i = 0; i < nbytes; ++i) { 513 int hi = hex_nibble(hex[2 * i]); 514 int lo = hex_nibble(hex[2 * i + 1]); 515 if (hi < 0 || lo < 0) { 516 driver_errf(LD_TOOL, "--build-id: invalid hex digit"); 517 driver_free(o->env, buf, nbytes); 518 return 1; 519 } 520 buf[i] = (uint8_t)((hi << 4) | lo); 521 } 522 o->build_id_mode = KIT_BUILDID_USER; 523 o->build_id_bytes = buf; 524 o->build_id_len = (uint32_t)nbytes; 525 o->build_id_alloc = nbytes; 526 return 0; 527 } 528 529 driver_errf(LD_TOOL, "--build-id: unknown value: %.*s", 530 KIT_SLICE_ARG(kit_slice_cstr(val))); 531 return 1; 532 } 533 534 /* ---------- argv parser ---------- */ 535 536 /* If `arg` starts with `prefix` followed by '=', returns the tail past the 537 * '='; otherwise returns NULL. */ 538 static const char* arg_eq_value(const char* arg, const char* prefix) { 539 size_t n = driver_strlen(prefix); 540 if (!driver_strneq(arg, prefix, n)) return NULL; 541 if (arg[n] != '=') return NULL; 542 return arg + n + 1; 543 } 544 545 /* Compare an MSVC-style flag against `arg`, case-insensitive on the 546 * key. MSVC accepts both `/` and `-` as the lead char and is 547 * case-insensitive in the key part — we accept `/KEY:val`, `/key:val`, 548 * `-KEY:val`. Returns the tail past the colon, or NULL on mismatch. */ 549 static const char* ms_flag_value(const char* arg, const char* key) { 550 size_t klen = driver_strlen(key); 551 size_t i; 552 if (arg[0] != '/' && arg[0] != '-') return NULL; 553 for (i = 0; i < klen; ++i) { 554 char a = arg[1 + i]; 555 char k = key[i]; 556 if (a >= 'a' && a <= 'z') a = (char)(a - 'a' + 'A'); 557 if (k >= 'a' && k <= 'z') k = (char)(k - 'a' + 'A'); 558 if (a != k) return NULL; 559 } 560 if (arg[1 + klen] != ':') return NULL; 561 return arg + 1 + klen + 1; 562 } 563 564 /* Same shape as ms_flag_value but for bare flags (no `:value`). */ 565 static int ms_flag_match(const char* arg, const char* key) { 566 size_t klen = driver_strlen(key); 567 size_t i; 568 if (arg[0] != '/' && arg[0] != '-') return 0; 569 for (i = 0; i < klen; ++i) { 570 char a = arg[1 + i]; 571 char k = key[i]; 572 if (a >= 'a' && a <= 'z') a = (char)(a - 'a' + 'A'); 573 if (k >= 'a' && k <= 'z') k = (char)(k - 'a' + 'A'); 574 if (a != k) return 0; 575 } 576 return arg[1 + klen] == '\0'; 577 } 578 579 static int ld_subsystem_value_eq(const char* val, const char* want) { 580 size_t i; 581 for (i = 0; want[i]; ++i) { 582 char a = val[i]; 583 char b = want[i]; 584 if (a >= 'a' && a <= 'z') a = (char)(a - 'a' + 'A'); 585 if (b >= 'a' && b <= 'z') b = (char)(b - 'a' + 'A'); 586 if (a != b) return 0; 587 } 588 return val[i] == '\0' || val[i] == ','; 589 } 590 591 static int ld_parse_pe_subsystem(LdOptions* o, const char* val) { 592 if (ld_subsystem_value_eq(val, "CONSOLE") || 593 ld_subsystem_value_eq(val, "CUI")) { 594 o->pe_subsystem = KIT_PE_SUBSYSTEM_WINDOWS_CUI; 595 return 0; 596 } 597 if (ld_subsystem_value_eq(val, "WINDOWS") || 598 ld_subsystem_value_eq(val, "GUI")) { 599 o->pe_subsystem = KIT_PE_SUBSYSTEM_WINDOWS_GUI; 600 return 0; 601 } 602 driver_errf(LD_TOOL, "unsupported subsystem: %.*s", 603 KIT_SLICE_ARG(kit_slice_cstr(val))); 604 return 1; 605 } 606 607 /* Parse one MSVC-style argument. Recognized subset (others warn and 608 * skip — match-but-no-op so legacy build scripts pass cleanly): 609 * /OUT:path → o->output_path 610 * /ENTRY:sym → o->entry 611 * /SUBSYSTEM:CONSOLE|WINDOWS → PE optional-header subsystem; WINDOWS 612 * also defaults entry to WinMainCRTStartup. 613 * /DEFAULTLIB:name → equivalent to -l<name>; resolved 614 * lazily in the same path as -l. 615 * /LIBPATH:dir → equivalent to -L dir 616 * 617 * Returns 1 if consumed, 0 if not a recognized MS flag (caller falls 618 * through to its existing behaviour), -1 on hard error. */ 619 static int ld_try_ms_flag(LdOptions* o, const char* a) { 620 const char* val; 621 if (!o->ms_link_driver) return 0; 622 if (a[0] != '/' && a[0] != '-') return 0; 623 624 if ((val = ms_flag_value(a, "OUT")) != NULL) { 625 if (o->output_seen) { 626 driver_errf(LD_TOOL, "/OUT specified after -o"); 627 return -1; 628 } 629 o->output_path = val; 630 o->output_seen = 1; 631 return 1; 632 } 633 if ((val = ms_flag_value(a, "ENTRY")) != NULL) { 634 o->entry = val; 635 return 1; 636 } 637 if ((val = ms_flag_value(a, "LIBPATH")) != NULL) { 638 o->lib_dirs[o->nlib_dirs++] = val; 639 return 1; 640 } 641 if ((val = ms_flag_value(a, "DEFAULTLIB")) != NULL) { 642 /* Resolve eagerly like -l does, using whatever current link-mode 643 * state is in effect. Windows mode triggers the .lib/.dll.a/.a 644 * suffix list. */ 645 char* resolved; 646 size_t resolved_size; 647 LibResolveKind kind; 648 LibResolveMode mode = (o->cur_link_mode == KIT_LM_STATIC) 649 ? LIB_RESOLVE_STATIC_ONLY 650 : LIB_RESOLVE_DYNAMIC_PREFER; 651 if (driver_lib_resolve_for_os(o->env, val, mode, LIB_RESOLVE_OS_WINDOWS, 652 o->lib_dirs, o->nlib_dirs, &resolved, 653 &resolved_size, &kind) != 0) { 654 driver_errf(LD_TOOL, "/DEFAULTLIB: cannot find %.*s", 655 KIT_SLICE_ARG(kit_slice_cstr(val))); 656 return -1; 657 } 658 if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { 659 ld_push_dso(o, resolved, 1, resolved_size); 660 } else { 661 ld_push_archive(o, resolved, 1, resolved_size); 662 } 663 return 1; 664 } 665 if ((val = ms_flag_value(a, "SUBSYSTEM")) != NULL) { 666 if (ld_parse_pe_subsystem(o, val) != 0) return -1; 667 return 1; 668 } 669 if (ms_flag_match(a, "NOLOGO") || ms_flag_match(a, "VERBOSE") || 670 ms_flag_match(a, "INCREMENTAL") || ms_flag_match(a, "DEBUG") || 671 ms_flag_match(a, "DYNAMICBASE") || ms_flag_match(a, "NXCOMPAT")) { 672 /* Common flags every Windows build script sets; silently accept. */ 673 return 1; 674 } 675 676 /* Any other `/key[:val]` shape under --ms-link-driver: warn + skip. 677 * We treat the entire arg as consumed so it doesn't fall through to 678 * the positional path and try to open a file. */ 679 driver_errf(LD_TOOL, "ignoring unsupported MS-style flag: %.*s", 680 KIT_SLICE_ARG(kit_slice_cstr(a))); 681 return 1; 682 } 683 684 static int ld_parse(int argc, char** argv, LdOptions* o) { 685 int i; 686 if (ld_alloc_arrays(o, argc) != 0) return 1; 687 688 o->target = driver_host_target(); 689 690 /* First pass: detect --ms-link-driver up front so the option can 691 * appear anywhere on the command line and still affect earlier 692 * `/...` tokens. Also capture --sysroot before resolving any -l 693 * entries; GNU ld treats the sysroot as a global search-prefix 694 * setting, not positional state. Also detect -lc so the hosted lib 695 * dirs can be pre-populated before -lm / -lpthread etc. are resolved. */ 696 { 697 int has_lc = 0; 698 for (i = 1; i < argc; ++i) { 699 if (driver_streq(argv[i], "--ms-link-driver")) { 700 o->ms_link_driver = 1; 701 continue; 702 } 703 if (driver_streq(argv[i], "--sysroot")) { 704 if (i + 1 < argc) { 705 o->sysroot = argv[i + 1]; 706 i++; 707 } 708 continue; 709 } 710 if (driver_strneq(argv[i], "--sysroot=", 10)) { 711 o->sysroot = argv[i] + 10; 712 continue; 713 } 714 /* Detect -lc / -l c so hosted lib dirs are available for later -l 715 * flags regardless of where -lc appears on the command line. */ 716 if (driver_streq(argv[i], "-lc")) { 717 has_lc = 1; 718 continue; 719 } 720 if ((driver_streq(argv[i], "-l") || driver_streq(argv[i], "--library")) && 721 i + 1 < argc && driver_streq(argv[i + 1], "c")) { 722 has_lc = 1; 723 i++; 724 continue; 725 } 726 } 727 if (!o->sysroot || !o->sysroot[0]) { 728 const char* env_sysroot = driver_getenv("KIT_SYSROOT"); 729 if (env_sysroot && env_sysroot[0]) o->sysroot = env_sysroot; 730 } 731 if (ld_add_sysroot_libdir(o) != 0) return 1; 732 /* Pre-populate the hosted lib dirs so user -l flags are resolved 733 * against the correct sysroot even when they appear before -lc. */ 734 if (has_lc) { 735 DriverHostedRequest req; 736 DriverHostedDirs dirs; 737 uint32_t j; 738 memset(&req, 0, sizeof req); 739 req.env = o->env; 740 req.tool = LD_TOOL; 741 req.target = o->target; 742 req.sysroot = o->sysroot; 743 if (driver_hosted_dirs_resolve(&req, &dirs) == 0) { 744 for (j = 0; j < dirs.nlibdirs; ++j) { 745 /* Transfer ownership of each dir string to o->owned_paths so 746 * it is freed in ld_options_release; then point lib_dirs at it. */ 747 const char* p; 748 if (ld_own_path(o, dirs.libdirs[j], dirs.libdir_sizes[j], &p) == 0) { 749 dirs.libdirs[j] = NULL; 750 dirs.libdir_sizes[j] = 0; 751 o->lib_dirs[o->nlib_dirs++] = p; 752 } 753 } 754 driver_hosted_dirs_fini(&dirs); 755 } 756 } 757 } 758 759 for (i = 1; i < argc; ++i) { 760 const char* a = argv[i]; 761 const char* val; 762 int ms_rc; 763 764 if (driver_streq(a, "--ms-link-driver")) { 765 o->ms_link_driver = 1; 766 continue; 767 } 768 ms_rc = ld_try_ms_flag(o, a); 769 if (ms_rc < 0) return 1; 770 if (ms_rc > 0) continue; 771 772 if (driver_streq(a, "-o")) { 773 if (++i >= argc) { 774 driver_errf(LD_TOOL, "-o requires an argument"); 775 return 1; 776 } 777 if (o->output_seen) { 778 driver_errf(LD_TOOL, "-o specified more than once"); 779 return 1; 780 } 781 o->output_path = argv[i]; 782 o->output_seen = 1; 783 continue; 784 } 785 if ((val = arg_eq_value(a, "--output")) != NULL) { 786 if (o->output_seen) { 787 driver_errf(LD_TOOL, "-o specified more than once"); 788 return 1; 789 } 790 o->output_path = val; 791 o->output_seen = 1; 792 continue; 793 } 794 if (driver_streq(a, "--output")) { 795 if (++i >= argc) { 796 driver_errf(LD_TOOL, "--output requires an argument"); 797 return 1; 798 } 799 if (o->output_seen) { 800 driver_errf(LD_TOOL, "-o specified more than once"); 801 return 1; 802 } 803 o->output_path = argv[i]; 804 o->output_seen = 1; 805 continue; 806 } 807 if (driver_streq(a, "-e")) { 808 if (++i >= argc) { 809 driver_errf(LD_TOOL, "-e requires an argument"); 810 return 1; 811 } 812 o->entry = argv[i]; 813 continue; 814 } 815 if ((val = arg_eq_value(a, "--entry")) != NULL) { 816 o->entry = val; 817 continue; 818 } 819 if (driver_streq(a, "--entry")) { 820 if (++i >= argc) { 821 driver_errf(LD_TOOL, "--entry requires an argument"); 822 return 1; 823 } 824 o->entry = argv[i]; 825 continue; 826 } 827 if ((val = arg_eq_value(a, "--subsystem")) != NULL) { 828 if (ld_parse_pe_subsystem(o, val) != 0) return 1; 829 continue; 830 } 831 if (driver_streq(a, "--subsystem")) { 832 if (++i >= argc) { 833 driver_errf(LD_TOOL, "--subsystem requires an argument"); 834 return 1; 835 } 836 if (ld_parse_pe_subsystem(o, argv[i]) != 0) return 1; 837 continue; 838 } 839 if (driver_streq(a, "-T")) { 840 if (++i >= argc) { 841 driver_errf(LD_TOOL, "-T requires an argument"); 842 return 1; 843 } 844 o->script_path = argv[i]; 845 continue; 846 } 847 if ((val = arg_eq_value(a, "--script")) != NULL) { 848 o->script_path = val; 849 continue; 850 } 851 if (driver_streq(a, "--script")) { 852 if (++i >= argc) { 853 driver_errf(LD_TOOL, "--script requires an argument"); 854 return 1; 855 } 856 o->script_path = argv[i]; 857 continue; 858 } 859 /* -Ttext ADDR / -Ttext=ADDR: set the static ET_EXEC image (text) base, for 860 * freestanding images that must load at a fixed address (e.g. the qemu 861 * `virt` RAM base 0x80000000). Matched here; the bare "-T" above is an exact 862 * match, so it never swallows -Ttext. No effect on PIE/scripted layouts. */ 863 { 864 const char* tval = NULL; 865 if (driver_streq(a, "-Ttext")) { 866 if (++i >= argc) { 867 driver_errf(LD_TOOL, "-Ttext requires an argument"); 868 return 1; 869 } 870 tval = argv[i]; 871 } else if ((tval = arg_eq_value(a, "-Ttext")) != NULL) { 872 /* -Ttext=ADDR */ 873 } 874 if (tval) { 875 uint64_t v; 876 if (ld_parse_addr(tval, &v) != 0) { 877 driver_errf(LD_TOOL, "-Ttext: invalid address: %s", tval); 878 return 1; 879 } 880 o->text_base = v; 881 o->text_base_set = 1; 882 continue; 883 } 884 } 885 /* -nostdlib / --no-default-libs: do not auto-resolve and link kit's 886 * compiler runtime. A freestanding image (e.g. riscv32-none-elf) supplies 887 * its own libkit_rt.a on the command line, and a pure-linker invocation 888 * should not require a per-target runtime archive to exist. */ 889 if (driver_streq(a, "-nostdlib") || driver_streq(a, "--no-default-libs") || 890 driver_streq(a, "-nodefaultlibs")) { 891 o->no_default_libs = 1; 892 continue; 893 } 894 if (driver_streq(a, "--support-dir")) { 895 if (++i >= argc) { 896 driver_errf(LD_TOOL, "--support-dir requires an argument"); 897 return 1; 898 } 899 o->support_dir = argv[i]; 900 continue; 901 } 902 if (driver_strneq(a, "--support-dir=", 14)) { 903 o->support_dir = a + 14; 904 continue; 905 } 906 if (driver_streq(a, "--sysroot")) { 907 if (++i >= argc) { 908 driver_errf(LD_TOOL, "--sysroot requires an argument"); 909 return 1; 910 } 911 o->sysroot = argv[i]; 912 continue; 913 } 914 if (driver_strneq(a, "--sysroot=", 10)) { 915 o->sysroot = a + 10; 916 continue; 917 } 918 919 if (driver_strneq(a, "-L", 2)) { 920 const char* dir = a[2] ? a + 2 : (++i < argc ? argv[i] : NULL); 921 const char* rewritten; 922 if (!dir) { 923 driver_errf(LD_TOOL, "-L requires an argument"); 924 return 1; 925 } 926 if (ld_sysroot_rewrite_path(o, dir, &rewritten) != 0) return 1; 927 o->lib_dirs[o->nlib_dirs++] = rewritten; 928 continue; 929 } 930 if ((val = arg_eq_value(a, "--library-path")) != NULL) { 931 const char* rewritten; 932 if (ld_sysroot_rewrite_path(o, val, &rewritten) != 0) return 1; 933 o->lib_dirs[o->nlib_dirs++] = rewritten; 934 continue; 935 } 936 if (driver_streq(a, "--library-path")) { 937 const char* rewritten; 938 if (++i >= argc) { 939 driver_errf(LD_TOOL, "--library-path requires an argument"); 940 return 1; 941 } 942 if (ld_sysroot_rewrite_path(o, argv[i], &rewritten) != 0) return 1; 943 o->lib_dirs[o->nlib_dirs++] = rewritten; 944 continue; 945 } 946 947 if (driver_strneq(a, "-l", 2)) { 948 const char* name = a[2] ? a + 2 : (++i < argc ? argv[i] : NULL); 949 char* resolved; 950 size_t resolved_size; 951 LibResolveKind kind; 952 LibResolveMode mode; 953 LibResolveOS resolve_os; 954 if (!name) { 955 driver_errf(LD_TOOL, "-l requires an argument"); 956 return 1; 957 } 958 if (ld_note_library_request(o, name)) continue; 959 /* -Bstatic forces .a only; everything else (default, 960 * -Bdynamic, --as-needed) prefers .so but falls back to .a. */ 961 mode = (o->cur_link_mode == KIT_LM_STATIC) ? LIB_RESOLVE_STATIC_ONLY 962 : LIB_RESOLVE_DYNAMIC_PREFER; 963 resolve_os = (o->target.os == KIT_OS_WINDOWS) ? LIB_RESOLVE_OS_WINDOWS 964 : LIB_RESOLVE_OS_POSIX; 965 if (driver_lib_resolve_for_os(o->env, name, mode, resolve_os, o->lib_dirs, 966 o->nlib_dirs, &resolved, &resolved_size, 967 &kind) != 0) { 968 driver_errf(LD_TOOL, "cannot find -l%.*s", 969 KIT_SLICE_ARG(kit_slice_cstr(name))); 970 return 1; 971 } 972 if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { 973 ld_push_dso(o, resolved, 1, resolved_size); 974 } else { 975 ld_push_archive(o, resolved, 1, resolved_size); 976 } 977 continue; 978 } 979 if ((val = arg_eq_value(a, "--library")) != NULL) { 980 char* resolved; 981 size_t resolved_size; 982 LibResolveKind kind; 983 LibResolveMode mode = (o->cur_link_mode == KIT_LM_STATIC) 984 ? LIB_RESOLVE_STATIC_ONLY 985 : LIB_RESOLVE_DYNAMIC_PREFER; 986 LibResolveOS resolve_os = (o->target.os == KIT_OS_WINDOWS) 987 ? LIB_RESOLVE_OS_WINDOWS 988 : LIB_RESOLVE_OS_POSIX; 989 if (ld_note_library_request(o, val)) continue; 990 if (driver_lib_resolve_for_os(o->env, val, mode, resolve_os, o->lib_dirs, 991 o->nlib_dirs, &resolved, &resolved_size, 992 &kind) != 0) { 993 driver_errf(LD_TOOL, "cannot find -l%.*s", 994 KIT_SLICE_ARG(kit_slice_cstr(val))); 995 return 1; 996 } 997 if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { 998 ld_push_dso(o, resolved, 1, resolved_size); 999 } else { 1000 ld_push_archive(o, resolved, 1, resolved_size); 1001 } 1002 continue; 1003 } 1004 if (driver_streq(a, "--library")) { 1005 char* resolved; 1006 size_t resolved_size; 1007 LibResolveKind kind; 1008 LibResolveMode mode; 1009 LibResolveOS resolve_os; 1010 if (++i >= argc) { 1011 driver_errf(LD_TOOL, "--library requires an argument"); 1012 return 1; 1013 } 1014 if (ld_note_library_request(o, argv[i])) continue; 1015 mode = (o->cur_link_mode == KIT_LM_STATIC) ? LIB_RESOLVE_STATIC_ONLY 1016 : LIB_RESOLVE_DYNAMIC_PREFER; 1017 resolve_os = (o->target.os == KIT_OS_WINDOWS) ? LIB_RESOLVE_OS_WINDOWS 1018 : LIB_RESOLVE_OS_POSIX; 1019 if (driver_lib_resolve_for_os(o->env, argv[i], mode, resolve_os, 1020 o->lib_dirs, o->nlib_dirs, &resolved, 1021 &resolved_size, &kind) != 0) { 1022 driver_errf(LD_TOOL, "cannot find -l%.*s", 1023 KIT_SLICE_ARG(kit_slice_cstr(argv[i]))); 1024 return 1; 1025 } 1026 if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { 1027 ld_push_dso(o, resolved, 1, resolved_size); 1028 } else { 1029 ld_push_archive(o, resolved, 1, resolved_size); 1030 } 1031 continue; 1032 } 1033 1034 if (driver_streq(a, "-static")) { 1035 o->target.pic = KIT_PIC_NONE; 1036 o->static_link = 1; 1037 o->cur_link_mode = KIT_LM_STATIC; 1038 o->pic_explicit = 1; 1039 continue; 1040 } 1041 if (driver_streq(a, "-pie")) { 1042 o->target.pic = KIT_PIC_PIE; 1043 o->pie = 1; 1044 o->pic_explicit = 1; 1045 continue; 1046 } 1047 if (driver_streq(a, "-dynamic-linker") || 1048 driver_streq(a, "--dynamic-linker")) { 1049 if (++i >= argc) { 1050 driver_errf(LD_TOOL, "-dynamic-linker requires an argument"); 1051 return 1; 1052 } 1053 o->interp_path = argv[i]; 1054 continue; 1055 } 1056 if ((val = arg_eq_value(a, "--dynamic-linker")) != NULL) { 1057 o->interp_path = val; 1058 continue; 1059 } 1060 if (driver_streq(a, "-no-pie")) { 1061 o->target.pic = KIT_PIC_NONE; 1062 o->pie = 0; 1063 o->pic_explicit = 1; 1064 continue; 1065 } 1066 1067 if (driver_streq(a, "-shared")) { 1068 o->shared = 1; 1069 /* Shared objects must be position-independent. Force PIC unless 1070 * the caller has explicitly chosen PIE (which is also fine). */ 1071 if (o->target.pic == KIT_PIC_NONE) o->target.pic = KIT_PIC_PIC; 1072 o->pic_explicit = 1; 1073 continue; 1074 } 1075 if (driver_streq(a, "-r") || driver_streq(a, "--relocatable")) { 1076 o->relocatable = 1; 1077 continue; 1078 } 1079 if (driver_streq(a, "-soname")) { 1080 if (++i >= argc) { 1081 driver_errf(LD_TOOL, "-soname requires an argument"); 1082 return 1; 1083 } 1084 o->soname = argv[i]; 1085 continue; 1086 } 1087 if ((val = arg_eq_value(a, "-soname")) != NULL) { 1088 o->soname = val; 1089 continue; 1090 } 1091 if (driver_streq(a, "-rpath")) { 1092 if (++i >= argc) { 1093 driver_errf(LD_TOOL, "-rpath requires an argument"); 1094 return 1; 1095 } 1096 o->rpaths[o->nrpaths++] = argv[i]; 1097 continue; 1098 } 1099 if ((val = arg_eq_value(a, "-rpath")) != NULL) { 1100 o->rpaths[o->nrpaths++] = val; 1101 continue; 1102 } 1103 if (driver_streq(a, "-rpath-link")) { 1104 if (++i >= argc) { 1105 driver_errf(LD_TOOL, "-rpath-link requires an argument"); 1106 return 1; 1107 } 1108 o->rpath_links[o->nrpath_links++] = argv[i]; 1109 continue; 1110 } 1111 if ((val = arg_eq_value(a, "-rpath-link")) != NULL) { 1112 o->rpath_links[o->nrpath_links++] = val; 1113 continue; 1114 } 1115 if (driver_streq(a, "--enable-new-dtags")) { 1116 o->new_dtags = 1; 1117 continue; 1118 } 1119 if (driver_streq(a, "--disable-new-dtags")) { 1120 o->new_dtags = 0; 1121 continue; 1122 } 1123 if (driver_streq(a, "--gc-sections")) { 1124 o->gc_sections = 1; 1125 continue; 1126 } 1127 if (driver_streq(a, "--no-gc-sections")) { 1128 o->gc_sections = 0; 1129 continue; 1130 } 1131 if (driver_streq(a, "-S") || driver_streq(a, "--strip-debug")) { 1132 o->strip_debug = 1; 1133 continue; 1134 } 1135 if (driver_streq(a, "-E") || driver_streq(a, "--export-dynamic")) { 1136 o->export_dynamic = 1; 1137 continue; 1138 } 1139 if (driver_streq(a, "--no-undefined")) { 1140 o->allow_undefined = 0; 1141 continue; 1142 } 1143 if (driver_streq(a, "--allow-shlib-undefined")) { 1144 o->allow_undefined = 1; 1145 continue; 1146 } 1147 if (driver_streq(a, "-z")) { 1148 if (++i >= argc) { 1149 driver_errf(LD_TOOL, "-z requires an argument"); 1150 return 1; 1151 } 1152 if (driver_streq(argv[i], "defs")) { 1153 o->allow_undefined = 0; 1154 continue; 1155 } 1156 driver_errf(LD_TOOL, "unsupported -z option: %.*s", 1157 KIT_SLICE_ARG(kit_slice_cstr(argv[i]))); 1158 return 1; 1159 } 1160 1161 if (driver_streq(a, "--whole-archive")) { 1162 o->cur_whole_archive = 1; 1163 continue; 1164 } 1165 if (driver_streq(a, "--no-whole-archive")) { 1166 o->cur_whole_archive = 0; 1167 continue; 1168 } 1169 if (driver_streq(a, "-Bstatic")) { 1170 o->cur_link_mode = KIT_LM_STATIC; 1171 continue; 1172 } 1173 if (driver_streq(a, "-Bdynamic")) { 1174 o->cur_link_mode = KIT_LM_DYNAMIC; 1175 continue; 1176 } 1177 if (driver_streq(a, "--as-needed")) { 1178 o->cur_link_mode = KIT_LM_AS_NEEDED; 1179 continue; 1180 } 1181 if (driver_streq(a, "--no-as-needed")) { 1182 o->cur_link_mode = KIT_LM_DYNAMIC; 1183 continue; 1184 } 1185 if (driver_streq(a, "--start-group")) { 1186 if (o->cur_group_id != 0) { 1187 driver_errf(LD_TOOL, "nested --start-group is not supported"); 1188 return 1; 1189 } 1190 if (o->next_group_id == UINT8_MAX) { 1191 driver_errf(LD_TOOL, "too many --start-group occurrences"); 1192 return 1; 1193 } 1194 o->next_group_id++; 1195 o->cur_group_id = o->next_group_id; 1196 continue; 1197 } 1198 if (driver_streq(a, "--end-group")) { 1199 if (o->cur_group_id == 0) { 1200 driver_errf(LD_TOOL, "--end-group without --start-group"); 1201 return 1; 1202 } 1203 o->cur_group_id = 0; 1204 continue; 1205 } 1206 1207 if ((val = arg_eq_value(a, "--build-id")) != NULL) { 1208 if (ld_parse_build_id(o, val) != 0) return 1; 1209 continue; 1210 } 1211 if (driver_streq(a, "--build-id")) { 1212 /* Bareword form defaults to sha256, matching GNU ld. */ 1213 o->build_id_mode = KIT_BUILDID_SHA256; 1214 continue; 1215 } 1216 1217 if (a[0] == '-' && a[1] != '\0') { 1218 driver_errf(LD_TOOL, "unknown flag: %.*s", 1219 KIT_SLICE_ARG(kit_slice_cstr(a))); 1220 return 1; 1221 } 1222 1223 { 1224 const char* path; 1225 if (ld_sysroot_rewrite_path(o, a, &path) != 0) return 1; 1226 if (driver_has_suffix(path, ".a")) { 1227 ld_push_archive(o, path, 0, 0); 1228 } else if (driver_is_so_filename(path)) { 1229 ld_push_dso(o, path, 0, 0); 1230 } else { 1231 ld_push_object(o, path); 1232 } 1233 } 1234 } 1235 1236 if (!o->output_path) { 1237 driver_errf(LD_TOOL, "-o is required"); 1238 return 1; 1239 } 1240 if (o->cur_group_id != 0) { 1241 driver_errf(LD_TOOL, "missing --end-group"); 1242 return 1; 1243 } 1244 if (o->nobject_files == 0 && o->narchives == 0 && o->ndsos == 0) { 1245 driver_errf(LD_TOOL, "no input files"); 1246 ld_usage(); 1247 return 1; 1248 } 1249 if (o->wants_hosted_libc && o->no_default_libs) { 1250 driver_errf(LD_TOOL, 1251 "-lc hosted expansion is disabled by -nostdlib/" 1252 "--no-default-libs"); 1253 return 1; 1254 } 1255 if (o->shared) { 1256 driver_errf(LD_TOOL, 1257 "creating dynamic/shared libraries is not yet supported"); 1258 return 1; 1259 } 1260 if (o->relocatable) { 1261 if (o->shared) { 1262 driver_errf(LD_TOOL, "-r and -shared are incompatible"); 1263 return 1; 1264 } 1265 if (o->wants_hosted_libc) { 1266 driver_errf(LD_TOOL, "-lc hosted expansion requires executable output"); 1267 return 1; 1268 } 1269 /* Only an explicit -pie conflicts; a default PIE target.pic is simply 1270 * overridden by -r (driver_link_pie suppresses pie when relocatable). */ 1271 if (o->pie) { 1272 driver_errf(LD_TOOL, "-r and -pie are incompatible"); 1273 return 1; 1274 } 1275 if (o->interp_path) { 1276 driver_errf(LD_TOOL, "-dynamic-linker requires executable output"); 1277 return 1; 1278 } 1279 if (o->soname || o->nrpaths || o->nrpath_links) { 1280 driver_errf(LD_TOOL, "-soname/-rpath/-rpath-link require -shared"); 1281 return 1; 1282 } 1283 if (o->ndsos) { 1284 driver_errf(LD_TOOL, "-r does not support shared-object inputs"); 1285 return 1; 1286 } 1287 if (o->script_path) { 1288 driver_errf(LD_TOOL, "-r does not support linker scripts yet"); 1289 return 1; 1290 } 1291 } 1292 return 0; 1293 } 1294 1295 /* ---------- options teardown ---------- */ 1296 1297 static void ld_options_release(LdOptions* o) { 1298 size_t bound = o->argv_bound; 1299 uint32_t i; 1300 for (i = 0; i < o->narchives; ++i) { 1301 LdArchive* a = &o->archives[i]; 1302 if (a->owned && a->path) { 1303 driver_free(o->env, (void*)a->path, a->owned_size); 1304 } 1305 } 1306 for (i = 0; i < o->ndsos; ++i) { 1307 LdDso* d = &o->dsos[i]; 1308 if (d->owned && d->path) { 1309 driver_free(o->env, (void*)d->path, d->owned_size); 1310 } 1311 } 1312 for (i = 0; i < o->nowned_paths; ++i) { 1313 if (o->owned_paths[i]) 1314 driver_free(o->env, o->owned_paths[i], o->owned_path_sizes[i]); 1315 } 1316 if (o->build_id_bytes) { 1317 driver_free(o->env, o->build_id_bytes, o->build_id_alloc); 1318 } 1319 driver_hosted_plan_fini(o->env, &o->hosted); 1320 driver_free(o->env, o->object_files, bound * sizeof(*o->object_files)); 1321 driver_free(o->env, o->archives, bound * sizeof(*o->archives)); 1322 driver_free(o->env, o->dsos, bound * sizeof(*o->dsos)); 1323 driver_free(o->env, o->order, bound * sizeof(*o->order)); 1324 driver_free(o->env, o->lib_dirs, bound * sizeof(*o->lib_dirs)); 1325 driver_free(o->env, o->owned_paths, bound * sizeof(*o->owned_paths)); 1326 driver_free(o->env, o->owned_path_sizes, 1327 bound * sizeof(*o->owned_path_sizes)); 1328 driver_free(o->env, o->rpaths, bound * sizeof(*o->rpaths)); 1329 driver_free(o->env, o->rpath_links, bound * sizeof(*o->rpath_links)); 1330 } 1331 1332 /* ---------- input loading ---------- */ 1333 1334 typedef struct LoadedFile { 1335 const KitFileIO* io; 1336 KitFileData data; 1337 int loaded; 1338 } LoadedFile; 1339 1340 static int load_file(const KitFileIO* io, const char* path, LoadedFile* out) { 1341 out->io = io; 1342 out->loaded = 0; 1343 out->data.data = NULL; 1344 out->data.size = 0; 1345 out->data.token = NULL; 1346 if (io->read_all(io->user, path, &out->data) != KIT_OK) return 1; 1347 out->loaded = 1; 1348 return 0; 1349 } 1350 1351 static void release_file(LoadedFile* lf) { 1352 if (lf->loaded && lf->io && lf->io->release) { 1353 lf->io->release(lf->io->user, &lf->data); 1354 } 1355 lf->loaded = 0; 1356 } 1357 1358 static void release_all(LoadedFile* arr, uint32_t n) { 1359 uint32_t i; 1360 if (!arr) return; 1361 for (i = 0; i < n; ++i) release_file(&arr[i]); 1362 } 1363 1364 static int ld_append_hosted_input(LdOptions* o, const DriverHostedInput* in, 1365 uint32_t insert_pos, int insert) { 1366 switch ((DriverHostedInputKind)in->kind) { 1367 case DRIVER_HOSTED_INPUT_OBJECT: 1368 if (insert) 1369 ld_insert_object(o, in->path, insert_pos); 1370 else 1371 ld_push_object(o, in->path); 1372 return 0; 1373 case DRIVER_HOSTED_INPUT_ARCHIVE: { 1374 LdArchive* a = &o->archives[o->narchives++]; 1375 a->path = in->path; 1376 a->owned = 0; 1377 a->owned_size = 0; 1378 a->whole_archive = 0; 1379 a->link_mode = KIT_LM_DEFAULT; 1380 a->group_id = 0; 1381 if (insert) 1382 ld_insert_order(o, insert_pos, KIT_LINK_INPUT_ARCHIVE, 1383 o->narchives - 1u); 1384 else 1385 ld_push_order(o, KIT_LINK_INPUT_ARCHIVE, o->narchives - 1u); 1386 return 0; 1387 } 1388 case DRIVER_HOSTED_INPUT_DSO: { 1389 LdDso* d = &o->dsos[o->ndsos++]; 1390 d->path = in->path; 1391 d->owned = 0; 1392 d->owned_size = 0; 1393 if (insert) 1394 ld_insert_order(o, insert_pos, KIT_LINK_INPUT_DSO, o->ndsos - 1u); 1395 else 1396 ld_push_order(o, KIT_LINK_INPUT_DSO, o->ndsos - 1u); 1397 return 0; 1398 } 1399 default: 1400 driver_errf(LD_TOOL, "internal error: unknown hosted input kind"); 1401 return 1; 1402 } 1403 } 1404 1405 static int ld_apply_hosted_before_after(LdOptions* o) { 1406 DriverHostedRequest req; 1407 uint32_t i; 1408 uint32_t insert_pos = 0; 1409 if (!o->wants_hosted_libc || o->shared) return 0; 1410 memset(&req, 0, sizeof req); 1411 req.env = o->env; 1412 req.tool = LD_TOOL; 1413 req.target = o->target; 1414 req.sysroot = o->sysroot; 1415 req.static_link = o->static_link; 1416 req.link_inputs = 1; 1417 if (driver_hosted_resolve(&req, &o->hosted) != 0) return 1; 1418 /* Add hosted lib search dirs so user -l flags resolve against the sysroot. */ 1419 for (i = 0; i < o->hosted.nlib_search_dirs; ++i) 1420 o->lib_dirs[o->nlib_dirs++] = o->hosted.lib_search_dirs[i]; 1421 for (i = 0; i < o->hosted.nbefore; ++i) { 1422 if (ld_append_hosted_input(o, &o->hosted.before[i], insert_pos, 1) != 0) 1423 return 1; 1424 insert_pos++; 1425 } 1426 for (i = 0; i < o->hosted.nafter; ++i) { 1427 if (ld_append_hosted_input(o, &o->hosted.after[i], 0, 0) != 0) return 1; 1428 } 1429 if (!o->interp_path && o->hosted.interp_path) 1430 o->interp_path = o->hosted.interp_path; 1431 return 0; 1432 } 1433 1434 static int ld_apply_hosted_final(LdOptions* o) { 1435 uint32_t i; 1436 if (!o->hosted.profile_name) return 0; 1437 for (i = 0; i < o->hosted.nfinal; ++i) { 1438 if (ld_append_hosted_input(o, &o->hosted.final[i], 0, 0) != 0) return 1; 1439 } 1440 return 0; 1441 } 1442 1443 /* ---------- link execution ---------- */ 1444 1445 /* Run the link. Returns 0 on success, nonzero on error. The caller owns 1446 * `o` and any allocations within; this function only owns transient 1447 * loaded-file buffers and the writer/compiler it constructs. */ 1448 static int ld_run_link(LdOptions* o) { 1449 KitContext ctx = driver_env_to_context(o->env); 1450 const KitFileIO* io = ctx.file_io; 1451 KitTarget* target = NULL; 1452 KitCompiler* compiler = NULL; 1453 KitWriter* writer = NULL; 1454 LoadedFile* obj_lf = NULL; 1455 LoadedFile* arch_lf = NULL; 1456 LoadedFile* dso_lf = NULL; 1457 LoadedFile script_lf = {0}; 1458 KitSlice* obj_in = NULL; 1459 KitLinkArchiveInput* arch_in = NULL; 1460 KitSlice* dso_in = NULL; 1461 KitLinkScript* script = NULL; 1462 KitLinkSession* link = NULL; 1463 DriverRuntimeSupport runtime = {0}; 1464 DriverRuntimeArchive rt_archive = {0}; 1465 uint32_t i; 1466 uint32_t initial_nobject_files; 1467 int runtime_resolved = 0; 1468 int rc = 1; 1469 1470 if (!io || !io->read_all || !io->open_writer) { 1471 driver_errf(LD_TOOL, "host file I/O unavailable"); 1472 return 1; 1473 } 1474 1475 /* Load the caller's object files first so the final target is known before 1476 * deciding which hosted CRT/libc profile and compiler-runtime archive to 1477 * add. The arrays are sized to the argv bound because hosted expansion may 1478 * append start files after target detection. */ 1479 initial_nobject_files = o->nobject_files; 1480 if (o->argv_bound) { 1481 obj_lf = driver_alloc_zeroed(o->env, o->argv_bound * sizeof(*obj_lf)); 1482 obj_in = driver_alloc_zeroed(o->env, o->argv_bound * sizeof(*obj_in)); 1483 if (!obj_lf || !obj_in) { 1484 driver_errf(LD_TOOL, "out of memory"); 1485 goto out; 1486 } 1487 } 1488 for (i = 0; i < initial_nobject_files; ++i) { 1489 const char* path = o->object_files[i]; 1490 if (load_file(io, path, &obj_lf[i]) != 0) { 1491 driver_errf(LD_TOOL, "failed to read: %.*s", 1492 KIT_SLICE_ARG(kit_slice_cstr(path))); 1493 goto out; 1494 } 1495 obj_in[i].data = obj_lf[i].data.data; 1496 obj_in[i].len = obj_lf[i].data.size; 1497 } 1498 1499 /* Auto-detect target from the object inputs, falling back to the host target. 1500 * The PIC default is a property of the *target*, not the host: hosted targets 1501 * default to PIE, freestanding ones to no-PIE (driver_default_pic). The host's 1502 * default PIC must never leak onto a detected cross target; only an EXPLICIT 1503 * -static/-pie/-no-pie/-shared wins. 1504 * 1505 * Detection takes the arch from the first object, but the OS from any object: 1506 * a freestanding (`*-none-elf`, EI_OSABI=STANDALONE) object means a freestanding 1507 * link even if a foreign object (e.g. a clang-assembled startup stub, which 1508 * stamps EI_OSABI=SysV and so decodes as Linux) appears first. */ 1509 if (initial_nobject_files > 0) { 1510 KitTargetSpec detected; 1511 if (kit_detect_target(obj_lf[0].data.data, obj_lf[0].data.size, 1512 &detected) == KIT_OK) { 1513 uint8_t pic = o->target.pic; 1514 uint32_t oi; 1515 for (oi = 1; oi < initial_nobject_files; ++oi) { 1516 KitTargetSpec t; 1517 if (kit_detect_target(obj_lf[oi].data.data, obj_lf[oi].data.size, &t) == 1518 KIT_OK) { 1519 if (t.os == KIT_OS_FREESTANDING) detected.os = KIT_OS_FREESTANDING; 1520 /* Reconcile the float ABI across inputs. A foreign startup stub (e.g. 1521 * a clang-assembled .S) may not carry the float-ABI e_flags that the 1522 * kit-compiled objects do, so prefer any object's hardware ABI 1523 * (single/double) over a soft/unset reading. This picks the runtime 1524 * variant (rv32 ilp32 vs ilp32f) the real code was compiled for even 1525 * when obj[0] is the stub. */ 1526 if (detected.float_abi != KIT_FLOAT_ABI_SINGLE && 1527 detected.float_abi != KIT_FLOAT_ABI_DOUBLE && 1528 (t.float_abi == KIT_FLOAT_ABI_SINGLE || 1529 t.float_abi == KIT_FLOAT_ABI_DOUBLE)) 1530 detected.float_abi = t.float_abi; 1531 } 1532 } 1533 o->target = detected; 1534 if (o->pic_explicit) 1535 o->target.pic = pic; 1536 else 1537 o->target.pic = driver_default_pic(o->target.obj, o->target.os); 1538 } 1539 } 1540 1541 if (ld_apply_hosted_before_after(o) != 0) goto out; 1542 1543 /* Hosted dynamic link: default to PIE, matching what `kit cc` does. 1544 * Without PIE the link_dyn path (PLT/GOT/.rela.plt) is not entered and 1545 * any CALL26/PLT32 reloc against an imported symbol faults at apply time. 1546 * Only override when the user has not made an explicit PIC choice. 1547 * Non-PIE (ET_EXEC) dynamic linking is not yet supported; reject early. */ 1548 if (o->wants_hosted_libc && !o->static_link && !o->shared && 1549 !o->relocatable) { 1550 if (o->pic_explicit && !o->pie) { 1551 driver_errf(LD_TOOL, 1552 "-lc with -no-pie is not supported; use -pie (default) " 1553 "or -static for a static link"); 1554 goto out; 1555 } 1556 if (!o->pic_explicit) 1557 o->pie = 1; 1558 } 1559 1560 /* Auto-link kit's compiler runtime for any target that has a variant — 1561 * including the freestanding riscv32-none-elf / riscv64-none-elf targets, 1562 * whose runtime (and, for rv32, the float-ABI it was detected with) is 1563 * resolved like every other target's. A target with no variant is implicitly 1564 * -nostdlib and supplies its own libkit_rt.a on the command line, so skip 1565 * resolution rather than erroring. -nostdlib forces the skip for any target. */ 1566 if (!o->relocatable && !o->no_default_libs && 1567 driver_runtime_has_variant(o->target)) { 1568 if (driver_runtime_resolve(o->env, o->support_dir, o->driver_path, 1569 &runtime) != 0) { 1570 driver_errf(LD_TOOL, "support dir not found"); 1571 goto out; 1572 } 1573 runtime_resolved = 1; 1574 if (driver_runtime_prepare_archive(o->env, LD_TOOL, &runtime, o->target, 0, 1575 &rt_archive) != 0) 1576 goto out; 1577 ld_push_runtime_archive(o, &rt_archive); 1578 } 1579 1580 if (ld_apply_hosted_final(o) != 0) goto out; 1581 1582 for (i = initial_nobject_files; i < o->nobject_files; ++i) { 1583 const char* path = o->object_files[i]; 1584 if (load_file(io, path, &obj_lf[i]) != 0) { 1585 driver_errf(LD_TOOL, "failed to read: %.*s", 1586 KIT_SLICE_ARG(kit_slice_cstr(path))); 1587 goto out; 1588 } 1589 obj_in[i].data = obj_lf[i].data.data; 1590 obj_in[i].len = obj_lf[i].data.size; 1591 } 1592 1593 if (o->narchives) { 1594 arch_lf = driver_alloc_zeroed(o->env, o->narchives * sizeof(*arch_lf)); 1595 arch_in = driver_alloc_zeroed(o->env, o->narchives * sizeof(*arch_in)); 1596 if (!arch_lf || !arch_in) { 1597 driver_errf(LD_TOOL, "out of memory"); 1598 goto out; 1599 } 1600 } 1601 if (o->ndsos) { 1602 dso_lf = driver_alloc_zeroed(o->env, o->ndsos * sizeof(*dso_lf)); 1603 dso_in = driver_alloc_zeroed(o->env, o->ndsos * sizeof(*dso_in)); 1604 if (!dso_lf || !dso_in) { 1605 driver_errf(LD_TOOL, "out of memory"); 1606 goto out; 1607 } 1608 } 1609 1610 /* Load archives. */ 1611 for (i = 0; i < o->narchives; ++i) { 1612 const LdArchive* a = &o->archives[i]; 1613 if (load_file(io, a->path, &arch_lf[i]) != 0) { 1614 driver_errf(LD_TOOL, "failed to read: %.*s", 1615 KIT_SLICE_ARG(kit_slice_cstr(a->path))); 1616 goto out; 1617 } 1618 arch_in[i].name = kit_slice_cstr(a->path); 1619 arch_in[i].bytes.data = arch_lf[i].data.data; 1620 arch_in[i].bytes.len = arch_lf[i].data.size; 1621 arch_in[i].whole_archive = a->whole_archive; 1622 arch_in[i].link_mode = a->link_mode; 1623 arch_in[i].group_id = a->group_id; 1624 } 1625 /* Load shared objects. */ 1626 for (i = 0; i < o->ndsos; ++i) { 1627 const LdDso* d = &o->dsos[i]; 1628 if (load_file(io, d->path, &dso_lf[i]) != 0) { 1629 driver_errf(LD_TOOL, "failed to read: %.*s", 1630 KIT_SLICE_ARG(kit_slice_cstr(d->path))); 1631 goto out; 1632 } 1633 dso_in[i].data = dso_lf[i].data.data; 1634 dso_in[i].len = dso_lf[i].data.size; 1635 } 1636 1637 /* Load and parse the linker script (if any). The structured script is 1638 * arena-owned by the compiler; we free it explicitly before the 1639 * compiler is destroyed. */ 1640 if (o->script_path) { 1641 if (load_file(io, o->script_path, &script_lf) != 0) { 1642 driver_errf(LD_TOOL, "failed to read: %.*s", 1643 KIT_SLICE_ARG(kit_slice_cstr(o->script_path))); 1644 goto out; 1645 } 1646 } 1647 1648 { 1649 KitTargetOptions topts; 1650 memset(&topts, 0, sizeof topts); 1651 topts.spec = o->target; 1652 if (kit_target_new(&ctx, &topts, &target) != KIT_OK || 1653 driver_compiler_new(target, &ctx, &compiler) != KIT_OK) { 1654 driver_errf(LD_TOOL, "failed to initialize compiler"); 1655 goto out; 1656 } 1657 } 1658 1659 if (script_lf.loaded) { 1660 KitSlice script_text = {.s = (const char*)script_lf.data.data, 1661 .len = script_lf.data.size}; 1662 if (kit_link_script_parse(&ctx, script_text, &script) != KIT_OK) { 1663 /* The parser reports a diagnostic via env.diag. */ 1664 goto out; 1665 } 1666 } 1667 1668 if (io->open_writer(io->user, o->output_path, &writer) != KIT_OK) { 1669 driver_errf(LD_TOOL, "failed to open output: %.*s", 1670 KIT_SLICE_ARG(kit_slice_cstr(o->output_path))); 1671 goto out; 1672 } 1673 1674 if (o->soname || o->nrpaths || o->nrpath_links) { 1675 if (!o->shared) { 1676 driver_errf(LD_TOOL, "-soname/-rpath/-rpath-link require -shared"); 1677 goto out; 1678 } 1679 } 1680 1681 { 1682 KitLinkSessionOptions lopts; 1683 KitStatus st; 1684 KitSlice* rpath_slices = NULL; 1685 /* Lift the argv-derived -rpath dirs into slices for the linker. */ 1686 if (o->nrpaths) { 1687 rpath_slices = 1688 driver_alloc_zeroed(o->env, o->nrpaths * sizeof(*rpath_slices)); 1689 if (!rpath_slices) { 1690 driver_errf(LD_TOOL, "out of memory"); 1691 goto out; 1692 } 1693 for (i = 0; i < o->nrpaths; ++i) 1694 rpath_slices[i] = kit_slice_cstr(o->rpaths[i]); 1695 } 1696 memset(&lopts, 0, sizeof(lopts)); 1697 lopts.output_kind = o->relocatable ? KIT_LINK_OUTPUT_RELOCATABLE 1698 : o->shared ? KIT_LINK_OUTPUT_SHARED 1699 : KIT_LINK_OUTPUT_EXE; 1700 lopts.entry = kit_slice_cstr(o->entry); 1701 lopts.text_base_set = o->text_base_set; 1702 lopts.text_base = o->text_base; 1703 lopts.linker_script = script; 1704 lopts.build_id_mode = o->build_id_mode; 1705 lopts.build_id_bytes = o->build_id_bytes; 1706 lopts.build_id_len = o->build_id_len; 1707 lopts.gc_sections = o->gc_sections; 1708 lopts.strip_debug = o->strip_debug; 1709 /* GNU ld and lld default to a non-PIE ET_EXEC; PIE is opt-in via -pie. 1710 * The linker imposes no hosted-PIE default the way a compiler driver 1711 * does (kit cc still defaults hosted executables to PIE through the link 1712 * API) — a freestanding or static link has no dynamic loader to apply a 1713 * PIE image's relocations or choose its base, so a PIE default produces a 1714 * binary that faults under a direct/qemu loader (its writable segments 1715 * sit below mmap_min_addr at the vaddr-0 PIE base). -shared/-r never PIE. 1716 * Callers that want a hosted PIE executable pass -pie explicitly (as the 1717 * musl dynamic lane and real compiler drivers do). */ 1718 lopts.pie = o->pie && !o->shared && !o->relocatable; 1719 lopts.pe_subsystem = o->pe_subsystem; 1720 lopts.interp_path = kit_slice_cstr(o->interp_path); 1721 lopts.soname = kit_slice_cstr(o->soname); 1722 /* Per --enable-new-dtags / --disable-new-dtags: when new_dtags is 1723 * set (the default), -rpath entries land in DT_RUNPATH; otherwise 1724 * in DT_RPATH. -rpath-link is link-time-only and is forwarded as 1725 * runpaths so the library has a record of the search paths used 1726 * (advisory; ELF runtime ignores DT_RUNPATH entries it didn't 1727 * write itself, so this matches GNU-ld behaviour where rpath-link 1728 * does not appear in DT_*PATH). */ 1729 if (o->new_dtags) { 1730 lopts.runpaths = rpath_slices; 1731 lopts.nrunpaths = o->nrpaths; 1732 } else { 1733 lopts.rpaths = rpath_slices; 1734 lopts.nrpaths = o->nrpaths; 1735 } 1736 /* By default shared output may resolve symbols against its loader at 1737 * runtime; --no-undefined / -z defs tightens that policy. */ 1738 lopts.allow_undefined = o->allow_undefined ? 1 : 0; 1739 (void)o->export_dynamic; 1740 1741 st = kit_link_session_new(compiler, &lopts, &link); 1742 if (o->order && o->norder) { 1743 for (i = 0; i < o->norder && st == KIT_OK; ++i) { 1744 const KitLinkInputOrder* ord = &o->order[i]; 1745 switch ((KitLinkInputOrderKind)ord->kind) { 1746 case KIT_LINK_INPUT_OBJ: 1747 case KIT_LINK_INPUT_OBJ_BYTES: 1748 st = kit_link_session_add_obj_bytes( 1749 link, kit_slice_cstr(o->object_files[ord->index]), 1750 &obj_in[ord->index]); 1751 break; 1752 case KIT_LINK_INPUT_ARCHIVE: 1753 st = kit_link_session_add_archive_bytes(link, &arch_in[ord->index]); 1754 break; 1755 case KIT_LINK_INPUT_DSO: 1756 st = kit_link_session_add_dso_bytes( 1757 link, kit_slice_cstr(o->dsos[ord->index].path), 1758 &dso_in[ord->index]); 1759 break; 1760 } 1761 } 1762 } else { 1763 for (i = 0; i < o->nobject_files && st == KIT_OK; ++i) 1764 st = kit_link_session_add_obj_bytes( 1765 link, kit_slice_cstr(o->object_files[i]), &obj_in[i]); 1766 for (i = 0; i < o->narchives && st == KIT_OK; ++i) 1767 st = kit_link_session_add_archive_bytes(link, &arch_in[i]); 1768 for (i = 0; i < o->ndsos && st == KIT_OK; ++i) 1769 st = kit_link_session_add_dso_bytes( 1770 link, kit_slice_cstr(o->dsos[i].path), &dso_in[i]); 1771 } 1772 if (st == KIT_OK) st = kit_link_session_emit(link, writer); 1773 rc = st == KIT_OK ? 0 : 1; 1774 } 1775 1776 out: 1777 if (writer) kit_writer_close(writer); 1778 kit_link_session_free(link); 1779 /* Match compiler/linker drivers: successful link outputs get executable 1780 * file modes while still respecting the process umask. Done after closing 1781 * the writer so the bits are stable on disk. */ 1782 if (rc == 0 && o->output_path && !o->relocatable) { 1783 if (driver_mark_executable_output(o->output_path) != 0) { 1784 driver_errf(LD_TOOL, "failed to set executable mode: %.*s", 1785 KIT_SLICE_ARG(kit_slice_cstr(o->output_path))); 1786 rc = 1; 1787 } 1788 } 1789 if (script) kit_link_script_free(&ctx, script); 1790 if (compiler) driver_compiler_free(compiler); 1791 kit_target_free(target); 1792 driver_runtime_archive_fini(o->env, &rt_archive); 1793 if (runtime_resolved) driver_runtime_support_fini(o->env, &runtime); 1794 release_file(&script_lf); 1795 release_all(arch_lf, o->narchives); 1796 release_all(obj_lf, o->nobject_files); 1797 release_all(dso_lf, o->ndsos); 1798 if (arch_in) driver_free(o->env, arch_in, o->narchives * sizeof(*arch_in)); 1799 if (arch_lf) driver_free(o->env, arch_lf, o->narchives * sizeof(*arch_lf)); 1800 if (obj_in) driver_free(o->env, obj_in, o->argv_bound * sizeof(*obj_in)); 1801 if (obj_lf) driver_free(o->env, obj_lf, o->argv_bound * sizeof(*obj_lf)); 1802 if (dso_in) driver_free(o->env, dso_in, o->ndsos * sizeof(*dso_in)); 1803 if (dso_lf) driver_free(o->env, dso_lf, o->ndsos * sizeof(*dso_lf)); 1804 return rc; 1805 } 1806 1807 int driver_ld(int argc, char** argv) { 1808 DriverEnv env; 1809 LdOptions lo = {0}; 1810 int rc; 1811 1812 if (argc < 2 || driver_argv_wants_help(argc, argv, 1)) { 1813 driver_help_ld(); 1814 return 0; 1815 } 1816 1817 driver_env_init(&env); 1818 lo.env = &env; 1819 lo.driver_path = argv[0]; 1820 1821 if (ld_parse(argc, argv, &lo) != 0) { 1822 ld_options_release(&lo); 1823 driver_env_fini(&env); 1824 return 2; 1825 } 1826 1827 rc = ld_run_link(&lo); 1828 1829 ld_options_release(&lo); 1830 driver_env_fini(&env); 1831 return rc; 1832 }