link_flags.c (30220B)
1 #include "link_flags.h" 2 3 #include <string.h> 4 5 static int lf_tok_eq(const char* tok, size_t n, const char* lit) { 6 size_t ln = driver_strlen(lit); 7 return n == ln && driver_strneq(tok, lit, ln); 8 } 9 10 static int lf_tok_prefix(const char* tok, size_t n, const char* lit) { 11 size_t ln = driver_strlen(lit); 12 return n >= ln && driver_strneq(tok, lit, ln); 13 } 14 15 static int lf_grow_rpaths(DriverLinkFlags* lf) { 16 uint32_t old_cap = lf->cap_rpaths; 17 uint32_t new_cap = old_cap ? old_cap * 2u : 8u; 18 const char** nr; 19 if (new_cap <= old_cap) return 1; 20 nr = 21 (const char**)driver_alloc_zeroed(lf->env, (size_t)new_cap * sizeof(*nr)); 22 if (!nr) return 1; 23 if (lf->rpaths) { 24 driver_memcpy(nr, lf->rpaths, (size_t)lf->nrpaths * sizeof(*lf->rpaths)); 25 driver_free(lf->env, lf->rpaths, (size_t)old_cap * sizeof(*lf->rpaths)); 26 } 27 lf->rpaths = nr; 28 lf->cap_rpaths = new_cap; 29 return 0; 30 } 31 32 static int lf_grow_owned(DriverLinkFlags* lf) { 33 uint32_t old_cap = lf->cap_owned_strings; 34 uint32_t new_cap = old_cap ? old_cap * 2u : 8u; 35 char** ns; 36 size_t* nsz; 37 if (new_cap <= old_cap) return 1; 38 ns = (char**)driver_alloc_zeroed(lf->env, (size_t)new_cap * sizeof(*ns)); 39 nsz = (size_t*)driver_alloc_zeroed(lf->env, (size_t)new_cap * sizeof(*nsz)); 40 if (!ns || !nsz) { 41 if (ns) driver_free(lf->env, ns, (size_t)new_cap * sizeof(*ns)); 42 if (nsz) driver_free(lf->env, nsz, (size_t)new_cap * sizeof(*nsz)); 43 return 1; 44 } 45 if (lf->owned_strings) { 46 driver_memcpy(ns, lf->owned_strings, 47 (size_t)lf->nowned_strings * sizeof(*lf->owned_strings)); 48 driver_free(lf->env, lf->owned_strings, 49 (size_t)old_cap * sizeof(*lf->owned_strings)); 50 } 51 if (lf->owned_string_sizes) { 52 driver_memcpy(nsz, lf->owned_string_sizes, 53 (size_t)lf->nowned_strings * sizeof(*lf->owned_string_sizes)); 54 driver_free(lf->env, lf->owned_string_sizes, 55 (size_t)old_cap * sizeof(*lf->owned_string_sizes)); 56 } 57 lf->owned_strings = ns; 58 lf->owned_string_sizes = nsz; 59 lf->cap_owned_strings = new_cap; 60 return 0; 61 } 62 63 static int lf_take_owned(DriverLinkFlags* lf, char* s, size_t n) { 64 if (lf->nowned_strings >= lf->cap_owned_strings && lf_grow_owned(lf) != 0) 65 return 1; 66 lf->owned_strings[lf->nowned_strings] = s; 67 lf->owned_string_sizes[lf->nowned_strings] = n; 68 lf->nowned_strings++; 69 return 0; 70 } 71 72 static char* lf_dup_owned(DriverLinkFlags* lf, const char* s, size_t n) { 73 size_t bytes = n + 1u; 74 char* buf; 75 if (bytes == 0) return NULL; 76 buf = (char*)driver_alloc(lf->env, bytes); 77 if (!buf) return NULL; 78 driver_memcpy(buf, s, n); 79 buf[n] = '\0'; 80 if (lf_take_owned(lf, buf, bytes) != 0) { 81 driver_free(lf->env, buf, bytes); 82 return NULL; 83 } 84 return buf; 85 } 86 87 static void lf_free_build_id(DriverLinkFlags* lf) { 88 if (lf->build_id_bytes) { 89 driver_free(lf->env, lf->build_id_bytes, lf->build_id_size); 90 lf->build_id_bytes = NULL; 91 lf->build_id_len = 0; 92 lf->build_id_size = 0; 93 } 94 } 95 96 static int lf_parse_hex_bytes(DriverLinkFlags* lf, const char* s, size_t n, 97 uint8_t** out_bytes, uint32_t* out_len, 98 size_t* out_size) { 99 uint8_t* bs; 100 size_t i; 101 if (n == 0 || (n & 1u) || n / 2u > UINT32_MAX) return 1; 102 bs = (uint8_t*)driver_alloc(lf->env, n / 2u); 103 if (!bs) return 1; 104 for (i = 0; i < n; i += 2u) { 105 int hi = driver_hex_nibble(s[i]); 106 int lo = driver_hex_nibble(s[i + 1u]); 107 if (hi < 0 || lo < 0) { 108 driver_free(lf->env, bs, n / 2u); 109 return 1; 110 } 111 bs[i / 2u] = (uint8_t)((hi << 4) | lo); 112 } 113 *out_bytes = bs; 114 *out_len = (uint32_t)(n / 2u); 115 *out_size = n / 2u; 116 return 0; 117 } 118 119 static int lf_record_build_id_span(DriverLinkFlags* lf, const char* val, 120 size_t n) { 121 if (n == 4 && driver_strneq(val, "none", 4)) { 122 lf_free_build_id(lf); 123 lf->build_id_mode = KIT_BUILDID_NONE; 124 return 0; 125 } 126 if (n == 6 && driver_strneq(val, "sha256", 6)) { 127 lf_free_build_id(lf); 128 lf->build_id_mode = KIT_BUILDID_SHA256; 129 return 0; 130 } 131 if (n == 4 && driver_strneq(val, "uuid", 4)) { 132 lf_free_build_id(lf); 133 lf->build_id_mode = KIT_BUILDID_UUID; 134 return 0; 135 } 136 if (n >= 2 && driver_strneq(val, "0x", 2)) { 137 uint8_t* bytes = NULL; 138 uint32_t len = 0; 139 size_t size = 0; 140 if (lf_parse_hex_bytes(lf, val + 2, n - 2u, &bytes, &len, &size) != 0) { 141 driver_errf(lf->tool, 142 "--build-id=0x... requires an even-length hex string"); 143 return 1; 144 } 145 lf_free_build_id(lf); 146 lf->build_id_bytes = bytes; 147 lf->build_id_len = len; 148 lf->build_id_size = size; 149 lf->build_id_mode = KIT_BUILDID_USER; 150 return 0; 151 } 152 driver_errf(lf->tool, "unknown --build-id value: %.*s", (int)n, val); 153 return 1; 154 } 155 156 static int lf_record_rpath(DriverLinkFlags* lf, const char* s, size_t n) { 157 char* buf; 158 if (lf->nrpaths >= lf->cap_rpaths && lf_grow_rpaths(lf) != 0) { 159 driver_errf(lf->tool, "out of memory"); 160 return 1; 161 } 162 buf = lf_dup_owned(lf, s, n); 163 if (!buf) { 164 driver_errf(lf->tool, "out of memory"); 165 return 1; 166 } 167 lf->rpaths[lf->nrpaths++] = buf; 168 return 0; 169 } 170 171 static int lf_record_soname(DriverLinkFlags* lf, const char* s, size_t n) { 172 char* buf = lf_dup_owned(lf, s, n); 173 if (!buf) { 174 driver_errf(lf->tool, "out of memory"); 175 return 1; 176 } 177 lf->soname = buf; 178 return 0; 179 } 180 181 static int lf_record_interp(DriverLinkFlags* lf, const char* s, size_t n) { 182 char* buf = lf_dup_owned(lf, s, n); 183 if (!buf) { 184 driver_errf(lf->tool, "out of memory"); 185 return 1; 186 } 187 lf->interp_path = buf; 188 return 0; 189 } 190 191 int driver_link_flags_record_entry(DriverLinkFlags* lf, const char* val, 192 size_t n) { 193 char* buf; 194 if (!val || n == 0) { 195 driver_errf(lf->tool, "--entry requires a non-empty symbol"); 196 return 1; 197 } 198 buf = lf_dup_owned(lf, val, n); 199 if (!buf) { 200 driver_errf(lf->tool, "out of memory"); 201 return 1; 202 } 203 lf->entry = buf; 204 return 0; 205 } 206 207 int driver_link_flags_record_script(DriverLinkFlags* lf, const char* val, 208 size_t n) { 209 char* buf; 210 if (!val || n == 0) { 211 driver_errf(lf->tool, "--script requires a non-empty path"); 212 return 1; 213 } 214 buf = lf_dup_owned(lf, val, n); 215 if (!buf) { 216 driver_errf(lf->tool, "out of memory"); 217 return 1; 218 } 219 lf->linker_script = buf; 220 return 0; 221 } 222 223 int driver_link_flags_record_map(DriverLinkFlags* lf, const char* val, 224 size_t n) { 225 char* buf; 226 if (!val || n == 0) { 227 driver_errf(lf->tool, "--map requires a non-empty path"); 228 return 1; 229 } 230 buf = lf_dup_owned(lf, val, n); 231 if (!buf) { 232 driver_errf(lf->tool, "out of memory"); 233 return 1; 234 } 235 lf->map_path = buf; 236 return 0; 237 } 238 239 int driver_link_flags_record_symbols(DriverLinkFlags* lf, const char* val, 240 size_t n) { 241 char* buf; 242 if (!val || n == 0) { 243 driver_errf(lf->tool, "--symbols requires a non-empty path"); 244 return 1; 245 } 246 buf = lf_dup_owned(lf, val, n); 247 if (!buf) { 248 driver_errf(lf->tool, "out of memory"); 249 return 1; 250 } 251 lf->symbols_path = buf; 252 return 0; 253 } 254 255 int driver_link_flags_record_symbols_format(DriverLinkFlags* lf, 256 const char* val, size_t n) { 257 if (n == 2 && driver_strneq(val, "nm", 2)) { 258 lf->symbols_format = KIT_LINK_SYMBOLS_NM; 259 return 0; 260 } 261 driver_errf(lf->tool, "unsupported --symbols-format: %.*s", (int)n, val); 262 return 1; 263 } 264 265 int driver_link_flags_record_text_base(DriverLinkFlags* lf, const char* val) { 266 uint64_t v; 267 if (!val || driver_parse_u64(val, &v) != 0) { 268 driver_errf(lf->tool, "-Ttext: invalid address: %s", val ? val : ""); 269 return 1; 270 } 271 lf->text_base = v; 272 lf->text_base_set = 1; 273 return 0; 274 } 275 276 /* Is this span a numeric (hex/dec) literal, or a symbol name? Used to decide 277 * the --defsym RHS form. A literal starts with a digit (0x.. or decimal). */ 278 static int lf_span_is_number(const char* s, size_t n) { 279 if (n == 0) return 0; 280 return s[0] >= '0' && s[0] <= '9'; 281 } 282 283 /* Parse a possibly-NUL-unterminated numeric span as u64. */ 284 static int lf_parse_u64_span(DriverLinkFlags* lf, const char* s, size_t n, 285 uint64_t* out) { 286 char* buf = lf_dup_owned(lf, s, n); 287 if (!buf) { 288 driver_errf(lf->tool, "out of memory"); 289 return 1; 290 } 291 return driver_parse_u64(buf, out); 292 } 293 294 static int lf_grow_defsyms(DriverLinkFlags* lf) { 295 uint32_t old_cap = lf->cap_defsyms; 296 uint32_t new_cap = old_cap ? old_cap * 2u : 4u; 297 KitLinkDefsym* nd; 298 if (new_cap <= old_cap) return 1; 299 nd = (KitLinkDefsym*)driver_alloc_zeroed(lf->env, 300 (size_t)new_cap * sizeof(*nd)); 301 if (!nd) return 1; 302 if (lf->defsyms) { 303 driver_memcpy(nd, lf->defsyms, (size_t)lf->ndefsyms * sizeof(*lf->defsyms)); 304 driver_free(lf->env, lf->defsyms, (size_t)old_cap * sizeof(*lf->defsyms)); 305 } 306 lf->defsyms = nd; 307 lf->cap_defsyms = new_cap; 308 return 0; 309 } 310 311 static int lf_grow_section_starts(DriverLinkFlags* lf) { 312 uint32_t old_cap = lf->cap_section_starts; 313 uint32_t new_cap = old_cap ? old_cap * 2u : 4u; 314 KitLinkSectionStart* ns; 315 if (new_cap <= old_cap) return 1; 316 ns = (KitLinkSectionStart*)driver_alloc_zeroed( 317 lf->env, (size_t)new_cap * sizeof(*ns)); 318 if (!ns) return 1; 319 if (lf->section_starts) { 320 driver_memcpy(ns, lf->section_starts, 321 (size_t)lf->nsection_starts * sizeof(*lf->section_starts)); 322 driver_free(lf->env, lf->section_starts, 323 (size_t)old_cap * sizeof(*lf->section_starts)); 324 } 325 lf->section_starts = ns; 326 lf->cap_section_starts = new_cap; 327 return 0; 328 } 329 330 int driver_link_flags_record_defsym(DriverLinkFlags* lf, const char* val, 331 size_t n) { 332 size_t eq = 0; 333 const char* name; 334 size_t name_len; 335 const char* rhs; 336 size_t rhs_len; 337 KitLinkDefsym* d; 338 char* name_buf; 339 while (eq < n && val[eq] != '=') ++eq; 340 if (eq == 0 || eq >= n) { 341 driver_errf(lf->tool, "--defsym requires NAME=EXPR: %.*s", (int)n, val); 342 return 1; 343 } 344 name = val; 345 name_len = eq; 346 rhs = val + eq + 1u; 347 rhs_len = n - eq - 1u; 348 if (rhs_len == 0) { 349 driver_errf(lf->tool, "--defsym requires a value: %.*s", (int)n, val); 350 return 1; 351 } 352 if (lf->ndefsyms >= lf->cap_defsyms && lf_grow_defsyms(lf) != 0) { 353 driver_errf(lf->tool, "out of memory"); 354 return 1; 355 } 356 name_buf = lf_dup_owned(lf, name, name_len); 357 if (!name_buf) { 358 driver_errf(lf->tool, "out of memory"); 359 return 1; 360 } 361 d = &lf->defsyms[lf->ndefsyms]; 362 memset(d, 0, sizeof(*d)); 363 d->name = kit_slice_cstr(name_buf); 364 if (lf_span_is_number(rhs, rhs_len)) { 365 uint64_t v; 366 if (lf_parse_u64_span(lf, rhs, rhs_len, &v) != 0) { 367 driver_errf(lf->tool, "--defsym: invalid value: %.*s", (int)rhs_len, rhs); 368 return 1; 369 } 370 d->value = v; 371 } else { 372 char* alias_buf = lf_dup_owned(lf, rhs, rhs_len); 373 if (!alias_buf) { 374 driver_errf(lf->tool, "out of memory"); 375 return 1; 376 } 377 d->alias = kit_slice_cstr(alias_buf); 378 d->value = 0; 379 } 380 lf->ndefsyms++; 381 return 0; 382 } 383 384 int driver_link_flags_record_section_addr(DriverLinkFlags* lf, 385 const char* secname, 386 const char* addr) { 387 uint64_t v; 388 KitLinkSectionStart* ss; 389 char* name_buf; 390 if (!secname || !*secname || !addr || !*addr) { 391 driver_errf(lf->tool, "--section-start requires .NAME=ADDR"); 392 return 1; 393 } 394 if (driver_parse_u64(addr, &v) != 0) { 395 driver_errf(lf->tool, "--section-start: invalid address: %s", addr); 396 return 1; 397 } 398 if (lf->nsection_starts >= lf->cap_section_starts && 399 lf_grow_section_starts(lf) != 0) { 400 driver_errf(lf->tool, "out of memory"); 401 return 1; 402 } 403 name_buf = lf_dup_owned(lf, secname, driver_strlen(secname)); 404 if (!name_buf) { 405 driver_errf(lf->tool, "out of memory"); 406 return 1; 407 } 408 ss = &lf->section_starts[lf->nsection_starts]; 409 memset(ss, 0, sizeof(*ss)); 410 ss->name = kit_slice_cstr(name_buf); 411 ss->addr = v; 412 lf->nsection_starts++; 413 return 0; 414 } 415 416 int driver_link_flags_record_section_start(DriverLinkFlags* lf, const char* val, 417 size_t n) { 418 /* --section-start=.NAME=ADDR — split on the LAST '='. */ 419 size_t eq = n; 420 size_t i; 421 char* name_buf; 422 char* addr_buf; 423 int rc; 424 for (i = 0; i < n; ++i) 425 if (val[i] == '=') eq = i; 426 if (eq == n || eq == 0) { 427 driver_errf(lf->tool, "--section-start requires .NAME=ADDR: %.*s", (int)n, 428 val); 429 return 1; 430 } 431 name_buf = lf_dup_owned(lf, val, eq); 432 addr_buf = lf_dup_owned(lf, val + eq + 1u, n - eq - 1u); 433 if (!name_buf || !addr_buf) { 434 driver_errf(lf->tool, "out of memory"); 435 return 1; 436 } 437 rc = driver_link_flags_record_section_addr(lf, name_buf, addr_buf); 438 return rc; 439 } 440 441 int driver_link_flags_record_orphan_handling(DriverLinkFlags* lf, 442 const char* val, size_t n) { 443 if (lf_tok_eq(val, n, "place")) { 444 lf->orphan_handling = KIT_LINK_ORPHAN_PLACE; 445 return 0; 446 } 447 if (lf_tok_eq(val, n, "warn")) { 448 lf->orphan_handling = KIT_LINK_ORPHAN_WARN; 449 return 0; 450 } 451 if (lf_tok_eq(val, n, "error")) { 452 lf->orphan_handling = KIT_LINK_ORPHAN_ERROR; 453 return 0; 454 } 455 if (lf_tok_eq(val, n, "discard")) { 456 lf->orphan_handling = KIT_LINK_ORPHAN_DISCARD; 457 return 0; 458 } 459 driver_errf(lf->tool, "unsupported --orphan-handling: %.*s", (int)n, val); 460 return 1; 461 } 462 463 int driver_link_flags_record_cref(DriverLinkFlags* lf, const char* val, 464 size_t n) { 465 char* buf; 466 if (!val || n == 0) { 467 driver_errf(lf->tool, "--cref requires a non-empty path"); 468 return 1; 469 } 470 buf = lf_dup_owned(lf, val, n); 471 if (!buf) { 472 driver_errf(lf->tool, "out of memory"); 473 return 1; 474 } 475 lf->cref_path = buf; 476 return 0; 477 } 478 479 int driver_link_flags_record_z(DriverLinkFlags* lf, const char* val, size_t n) { 480 if (lf_tok_eq(val, n, "defs")) { 481 lf->allow_undefined = 0; 482 return 0; 483 } 484 if (lf_tok_eq(val, n, "nodefs")) { 485 lf->allow_undefined = 1; 486 return 0; 487 } 488 if (lf_tok_eq(val, n, "noexecstack") || lf_tok_eq(val, n, "relro") || 489 lf_tok_eq(val, n, "now") || lf_tok_eq(val, n, "text")) { 490 return 0; 491 } 492 driver_errf(lf->tool, "unsupported -z option: %.*s", (int)n, val); 493 return 1; 494 } 495 496 static int lf_subsystem_eq(const char* val, size_t n, const char* want) { 497 size_t i; 498 for (i = 0; want[i]; ++i) { 499 char a; 500 char b; 501 if (i >= n) return 0; 502 a = val[i]; 503 b = want[i]; 504 if (a >= 'a' && a <= 'z') a = (char)(a - 'a' + 'A'); 505 if (b >= 'a' && b <= 'z') b = (char)(b - 'a' + 'A'); 506 if (a != b) return 0; 507 } 508 return i == n || val[i] == ','; 509 } 510 511 int driver_link_flags_init(DriverLinkFlags* lf, DriverEnv* env, 512 const char* tool, uint32_t initial_cap) { 513 uint32_t cap = initial_cap ? initial_cap : 8u; 514 memset(lf, 0, sizeof(*lf)); 515 lf->env = env; 516 lf->tool = tool; 517 lf->new_dtags = 1; 518 lf->cap_rpaths = cap; 519 lf->cap_owned_strings = cap; 520 lf->rpaths = 521 (const char**)driver_alloc_zeroed(env, (size_t)cap * sizeof(*lf->rpaths)); 522 lf->owned_strings = (char**)driver_alloc_zeroed( 523 env, (size_t)cap * sizeof(*lf->owned_strings)); 524 lf->owned_string_sizes = (size_t*)driver_alloc_zeroed( 525 env, (size_t)cap * sizeof(*lf->owned_string_sizes)); 526 if (!lf->rpaths || !lf->owned_strings || !lf->owned_string_sizes) { 527 driver_link_flags_fini(lf); 528 return 1; 529 } 530 return 0; 531 } 532 533 void driver_link_flags_fini(DriverLinkFlags* lf) { 534 uint32_t i; 535 if (!lf || !lf->env) return; 536 for (i = 0; i < lf->nowned_strings; ++i) { 537 if (lf->owned_strings[i]) 538 driver_free(lf->env, lf->owned_strings[i], lf->owned_string_sizes[i]); 539 } 540 lf_free_build_id(lf); 541 if (lf->rpaths) 542 driver_free(lf->env, lf->rpaths, 543 (size_t)lf->cap_rpaths * sizeof(*lf->rpaths)); 544 if (lf->owned_strings) 545 driver_free(lf->env, lf->owned_strings, 546 (size_t)lf->cap_owned_strings * sizeof(*lf->owned_strings)); 547 if (lf->owned_string_sizes) 548 driver_free( 549 lf->env, lf->owned_string_sizes, 550 (size_t)lf->cap_owned_strings * sizeof(*lf->owned_string_sizes)); 551 if (lf->defsyms) 552 driver_free(lf->env, lf->defsyms, 553 (size_t)lf->cap_defsyms * sizeof(*lf->defsyms)); 554 if (lf->section_starts) 555 driver_free(lf->env, lf->section_starts, 556 (size_t)lf->cap_section_starts * sizeof(*lf->section_starts)); 557 memset(lf, 0, sizeof(*lf)); 558 } 559 560 int driver_link_flags_record_build_id(DriverLinkFlags* lf, const char* val) { 561 return lf_record_build_id_span(lf, val, driver_strlen(val)); 562 } 563 564 int driver_link_flags_record_pe_subsystem(DriverLinkFlags* lf, const char* val, 565 size_t n) { 566 if (lf_subsystem_eq(val, n, "CONSOLE") || lf_subsystem_eq(val, n, "CUI")) { 567 lf->pe_subsystem = KIT_PE_SUBSYSTEM_WINDOWS_CUI; 568 return 0; 569 } 570 if (lf_subsystem_eq(val, n, "WINDOWS") || lf_subsystem_eq(val, n, "GUI")) { 571 lf->pe_subsystem = KIT_PE_SUBSYSTEM_WINDOWS_GUI; 572 return 0; 573 } 574 driver_errf(lf->tool, "unsupported subsystem: %.*s", (int)n, val); 575 return 1; 576 } 577 578 int driver_link_flags_record_wl(DriverLinkFlags* lf, const char* arg) { 579 const char* p = arg; 580 int expect_rpath = 0; 581 int expect_soname = 0; 582 int expect_interp = 0; 583 int expect_subsystem = 0; 584 int expect_z = 0; 585 int expect_map = 0; 586 int expect_symbols = 0; 587 int expect_ttext = 0; 588 int expect_defsym = 0; 589 int expect_section_start = 0; 590 int expect_cref = 0; 591 int expect_orphan = 0; 592 int expect_entry = 0; 593 int expect_script = 0; 594 while (*p) { 595 const char* tok = p; 596 size_t n = 0; 597 while (p[n] && p[n] != ',') ++n; 598 p = tok + n + (tok[n] == ',' ? 1u : 0u); 599 600 if (expect_rpath || expect_soname || expect_interp || expect_subsystem || 601 expect_z || expect_map || expect_symbols || expect_ttext || 602 expect_defsym || expect_section_start || expect_cref || expect_orphan || 603 expect_entry || expect_script) { 604 int rc = 0; 605 if (expect_rpath) 606 rc = lf_record_rpath(lf, tok, n); 607 else if (expect_soname) 608 rc = lf_record_soname(lf, tok, n); 609 else if (expect_interp) 610 rc = lf_record_interp(lf, tok, n); 611 else if (expect_subsystem) 612 rc = driver_link_flags_record_pe_subsystem(lf, tok, n); 613 else if (expect_z) 614 rc = driver_link_flags_record_z(lf, tok, n); 615 else if (expect_map) 616 rc = driver_link_flags_record_map(lf, tok, n); 617 else if (expect_symbols) 618 rc = driver_link_flags_record_symbols(lf, tok, n); 619 else if (expect_defsym) 620 rc = driver_link_flags_record_defsym(lf, tok, n); 621 else if (expect_section_start) 622 rc = driver_link_flags_record_section_start(lf, tok, n); 623 else if (expect_cref) 624 rc = driver_link_flags_record_cref(lf, tok, n); 625 else if (expect_orphan) 626 rc = driver_link_flags_record_orphan_handling(lf, tok, n); 627 else if (expect_entry) 628 rc = driver_link_flags_record_entry(lf, tok, n); 629 else if (expect_script) 630 rc = driver_link_flags_record_script(lf, tok, n); 631 else if (expect_ttext) { 632 char* buf = lf_dup_owned(lf, tok, n); 633 if (!buf) { 634 driver_errf(lf->tool, "out of memory"); 635 return 1; 636 } 637 rc = driver_link_flags_record_text_base(lf, buf); 638 } 639 if (rc != 0) return 1; 640 expect_rpath = expect_soname = expect_interp = expect_subsystem = 641 expect_z = expect_map = expect_symbols = expect_ttext = 642 expect_defsym = expect_section_start = expect_cref = 643 expect_orphan = expect_entry = expect_script = 0; 644 continue; 645 } 646 647 if (lf_tok_eq(tok, n, "-e") || lf_tok_eq(tok, n, "--entry")) { 648 expect_entry = 1; 649 continue; 650 } 651 if (lf_tok_prefix(tok, n, "--entry=")) { 652 if (driver_link_flags_record_entry(lf, tok + 8, n - 8u) != 0) return 1; 653 continue; 654 } 655 if (n > 2 && tok[0] == '-' && tok[1] == 'e') { 656 if (driver_link_flags_record_entry(lf, tok + 2, n - 2u) != 0) return 1; 657 continue; 658 } 659 if (lf_tok_eq(tok, n, "-T") || lf_tok_eq(tok, n, "--script")) { 660 expect_script = 1; 661 continue; 662 } 663 if (lf_tok_prefix(tok, n, "--script=")) { 664 if (driver_link_flags_record_script(lf, tok + 9, n - 9u) != 0) return 1; 665 continue; 666 } 667 if (n > 2 && tok[0] == '-' && tok[1] == 'T' && 668 !lf_tok_prefix(tok, n, "-Ttext") && 669 !lf_tok_prefix(tok, n, "-Tdata") && 670 !lf_tok_prefix(tok, n, "-Tbss")) { 671 if (driver_link_flags_record_script(lf, tok + 2, n - 2u) != 0) return 1; 672 continue; 673 } 674 675 if (lf_tok_prefix(tok, n, "-soname=")) { 676 if (lf_record_soname(lf, tok + 8, n - 8u) != 0) return 1; 677 continue; 678 } 679 if (lf_tok_eq(tok, n, "-soname")) { 680 expect_soname = 1; 681 continue; 682 } 683 if (lf_tok_prefix(tok, n, "-rpath=")) { 684 if (lf_record_rpath(lf, tok + 7, n - 7u) != 0) return 1; 685 continue; 686 } 687 if (lf_tok_eq(tok, n, "-rpath")) { 688 expect_rpath = 1; 689 continue; 690 } 691 if (lf_tok_prefix(tok, n, "-dynamic-linker=")) { 692 if (lf_record_interp(lf, tok + 16, n - 16u) != 0) return 1; 693 continue; 694 } 695 if (lf_tok_eq(tok, n, "-dynamic-linker")) { 696 expect_interp = 1; 697 continue; 698 } 699 if (lf_tok_eq(tok, n, "--enable-new-dtags")) { 700 lf->new_dtags = 1; 701 continue; 702 } 703 if (lf_tok_eq(tok, n, "--disable-new-dtags")) { 704 lf->new_dtags = 0; 705 continue; 706 } 707 if (lf_tok_eq(tok, n, "--gc-sections")) { 708 lf->gc_sections = 1; 709 continue; 710 } 711 if (lf_tok_eq(tok, n, "--no-gc-sections")) { 712 lf->gc_sections = 0; 713 continue; 714 } 715 if (lf_tok_eq(tok, n, "-S") || lf_tok_eq(tok, n, "--strip-debug")) { 716 lf->strip_debug = 1; 717 continue; 718 } 719 if (lf_tok_eq(tok, n, "--no-undefined")) { 720 lf->allow_undefined = 0; 721 continue; 722 } 723 if (lf_tok_eq(tok, n, "--allow-undefined") || 724 lf_tok_eq(tok, n, "--allow-shlib-undefined")) { 725 lf->allow_undefined = 1; 726 continue; 727 } 728 if (lf_tok_eq(tok, n, "-z")) { 729 expect_z = 1; 730 continue; 731 } 732 if (n > 2 && tok[0] == '-' && tok[1] == 'z') { 733 if (driver_link_flags_record_z(lf, tok + 2, n - 2u) != 0) return 1; 734 continue; 735 } 736 if (lf_tok_eq(tok, n, "-Ttext")) { 737 expect_ttext = 1; 738 continue; 739 } 740 if (lf_tok_prefix(tok, n, "-Ttext=")) { 741 char* buf = lf_dup_owned(lf, tok + 7, n - 7u); 742 if (!buf) { 743 driver_errf(lf->tool, "out of memory"); 744 return 1; 745 } 746 if (driver_link_flags_record_text_base(lf, buf) != 0) return 1; 747 continue; 748 } 749 if (lf_tok_eq(tok, n, "--map") || lf_tok_eq(tok, n, "-Map")) { 750 expect_map = 1; 751 continue; 752 } 753 if (lf_tok_prefix(tok, n, "--map=")) { 754 if (driver_link_flags_record_map(lf, tok + 6, n - 6u) != 0) return 1; 755 continue; 756 } 757 if (lf_tok_prefix(tok, n, "-Map=")) { 758 if (driver_link_flags_record_map(lf, tok + 5, n - 5u) != 0) return 1; 759 continue; 760 } 761 if (lf_tok_eq(tok, n, "--symbols")) { 762 expect_symbols = 1; 763 continue; 764 } 765 if (lf_tok_prefix(tok, n, "--symbols=")) { 766 if (driver_link_flags_record_symbols(lf, tok + 10, n - 10u) != 0) 767 return 1; 768 continue; 769 } 770 if (lf_tok_prefix(tok, n, "--symbols-format=")) { 771 if (driver_link_flags_record_symbols_format(lf, tok + 17, n - 17u) != 0) 772 return 1; 773 continue; 774 } 775 if (lf_tok_prefix(tok, n, "--build-id=")) { 776 if (lf_record_build_id_span(lf, tok + 11, n - 11u) != 0) return 1; 777 continue; 778 } 779 if (lf_tok_eq(tok, n, "--build-id")) { 780 lf_free_build_id(lf); 781 lf->build_id_mode = KIT_BUILDID_SHA256; 782 continue; 783 } 784 if (lf_tok_prefix(tok, n, "--subsystem=")) { 785 if (driver_link_flags_record_pe_subsystem(lf, tok + 12, n - 12u) != 0) 786 return 1; 787 continue; 788 } 789 if (lf_tok_eq(tok, n, "--subsystem")) { 790 expect_subsystem = 1; 791 continue; 792 } 793 if (lf_tok_prefix(tok, n, "/SUBSYSTEM:")) { 794 if (driver_link_flags_record_pe_subsystem(lf, tok + 11, n - 11u) != 0) 795 return 1; 796 continue; 797 } 798 /* -Tdata / -Tbss: section base overrides, folded into section_starts. */ 799 if (lf_tok_eq(tok, n, "-Tdata") || lf_tok_eq(tok, n, "-Tbss")) { 800 /* The next comma token is the address. Reuse the section-start consume 801 * via a synthesized ".data=ADDR" / ".bss=ADDR" on the following token; 802 * simplest is a dedicated tiny state, but section_start expects NAME=ADDR. 803 * Stash the chosen section name and read the address as a fresh token. */ 804 const char* secname = lf_tok_eq(tok, n, "-Tdata") ? ".data" : ".bss"; 805 const char* atok = p; 806 size_t an = 0; 807 char* addr_buf; 808 if (!*atok) { 809 driver_errf(lf->tool, "%.*s requires an address", (int)n, tok); 810 return 1; 811 } 812 while (atok[an] && atok[an] != ',') ++an; 813 p = atok + an + (atok[an] == ',' ? 1u : 0u); 814 addr_buf = lf_dup_owned(lf, atok, an); 815 if (!addr_buf) { 816 driver_errf(lf->tool, "out of memory"); 817 return 1; 818 } 819 if (driver_link_flags_record_section_addr(lf, secname, addr_buf) != 0) 820 return 1; 821 continue; 822 } 823 if (lf_tok_prefix(tok, n, "-Tdata=")) { 824 char* addr_buf = lf_dup_owned(lf, tok + 7, n - 7u); 825 if (!addr_buf) { 826 driver_errf(lf->tool, "out of memory"); 827 return 1; 828 } 829 if (driver_link_flags_record_section_addr(lf, ".data", addr_buf) != 0) 830 return 1; 831 continue; 832 } 833 if (lf_tok_prefix(tok, n, "-Tbss=")) { 834 char* addr_buf = lf_dup_owned(lf, tok + 6, n - 6u); 835 if (!addr_buf) { 836 driver_errf(lf->tool, "out of memory"); 837 return 1; 838 } 839 if (driver_link_flags_record_section_addr(lf, ".bss", addr_buf) != 0) 840 return 1; 841 continue; 842 } 843 /* --defsym NAME=EXPR */ 844 if (lf_tok_prefix(tok, n, "--defsym=")) { 845 if (driver_link_flags_record_defsym(lf, tok + 9, n - 9u) != 0) return 1; 846 continue; 847 } 848 if (lf_tok_eq(tok, n, "--defsym")) { 849 expect_defsym = 1; 850 continue; 851 } 852 /* --section-start=.NAME=ADDR */ 853 if (lf_tok_prefix(tok, n, "--section-start=")) { 854 if (driver_link_flags_record_section_start(lf, tok + 16, n - 16u) != 0) 855 return 1; 856 continue; 857 } 858 if (lf_tok_eq(tok, n, "--section-start")) { 859 expect_section_start = 1; 860 continue; 861 } 862 /* --cref [FILE] */ 863 if (lf_tok_prefix(tok, n, "--cref=")) { 864 if (driver_link_flags_record_cref(lf, tok + 7, n - 7u) != 0) return 1; 865 continue; 866 } 867 if (lf_tok_eq(tok, n, "--cref")) { 868 expect_cref = 1; 869 continue; 870 } 871 /* --orphan-handling=MODE */ 872 if (lf_tok_prefix(tok, n, "--orphan-handling=")) { 873 if (driver_link_flags_record_orphan_handling(lf, tok + 18, n - 18u) != 0) 874 return 1; 875 continue; 876 } 877 if (lf_tok_eq(tok, n, "--orphan-handling")) { 878 expect_orphan = 1; 879 continue; 880 } 881 if (lf_tok_eq(tok, n, "--fatal-warnings")) { 882 lf->fatal_warnings = 1; 883 continue; 884 } 885 if (lf_tok_eq(tok, n, "--no-fatal-warnings")) { 886 lf->fatal_warnings = 0; 887 continue; 888 } 889 if (lf_tok_eq(tok, n, "--print-memory-usage")) { 890 lf->print_memory_usage = 1; 891 continue; 892 } 893 894 driver_errf(lf->tool, "unsupported -Wl, token: %.*s", (int)n, tok); 895 return 1; 896 } 897 if (expect_rpath || expect_soname || expect_interp || expect_subsystem || 898 expect_z || expect_map || expect_symbols || expect_ttext || 899 expect_defsym || expect_section_start || expect_cref || expect_orphan || 900 expect_entry || expect_script) { 901 driver_errf(lf->tool, "-Wl option requires another comma argument"); 902 return 1; 903 } 904 return 0; 905 } 906 907 int driver_link_flags_fill_options(const DriverLinkFlags* lf, 908 KitTargetSpec target, int explicit_pie, 909 int shared, int relocatable, 910 uint8_t output_kind, 911 const KitLinkScript* script, 912 KitLinkSessionOptions* lopts, 913 KitSlice** rpath_slices_out) { 914 KitSlice* rpath_slices = NULL; 915 uint32_t i; 916 *rpath_slices_out = NULL; 917 if (lf->nrpaths) { 918 rpath_slices = (KitSlice*)driver_alloc_zeroed( 919 lf->env, (size_t)lf->nrpaths * sizeof(*rpath_slices)); 920 if (!rpath_slices) { 921 driver_errf(lf->tool, "out of memory"); 922 return 1; 923 } 924 for (i = 0; i < lf->nrpaths; ++i) 925 rpath_slices[i] = kit_slice_cstr(lf->rpaths[i]); 926 } 927 memset(lopts, 0, sizeof(*lopts)); 928 lopts->output_kind = output_kind; 929 lopts->entry = kit_slice_cstr(lf->entry); 930 lopts->linker_script = script; 931 lopts->build_id_mode = lf->build_id_mode; 932 lopts->build_id_bytes = lf->build_id_bytes; 933 lopts->build_id_len = lf->build_id_len; 934 lopts->gc_sections = lf->gc_sections != 0; 935 lopts->strip_debug = lf->strip_debug != 0; 936 lopts->text_base_set = lf->text_base_set != 0; 937 lopts->text_base = lf->text_base; 938 lopts->defsyms = lf->defsyms; 939 lopts->ndefsyms = lf->ndefsyms; 940 lopts->section_starts = lf->section_starts; 941 lopts->nsection_starts = lf->nsection_starts; 942 lopts->orphan_handling = lf->orphan_handling; 943 lopts->fatal_warnings = lf->fatal_warnings != 0; 944 lopts->pie = driver_link_pie(target, explicit_pie, shared, relocatable) != 0; 945 lopts->pe_subsystem = lf->pe_subsystem; 946 lopts->interp_path = kit_slice_cstr(lf->interp_path); 947 lopts->soname = kit_slice_cstr(lf->soname); 948 if (lf->new_dtags) { 949 lopts->runpaths = rpath_slices; 950 lopts->nrunpaths = lf->nrpaths; 951 } else { 952 lopts->rpaths = rpath_slices; 953 lopts->nrpaths = lf->nrpaths; 954 } 955 lopts->allow_undefined = lf->allow_undefined != 0; 956 *rpath_slices_out = rpath_slices; 957 return 0; 958 } 959 960 void driver_link_flags_free_rpath_slices(const DriverLinkFlags* lf, 961 KitSlice* rpath_slices) { 962 if (rpath_slices) 963 driver_free(lf->env, rpath_slices, 964 (size_t)lf->nrpaths * sizeof(*rpath_slices)); 965 }