1 //===- Driver.cpp ---------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lld/Common/Driver.h" 10 #include "Config.h" 11 #include "InputChunks.h" 12 #include "InputElement.h" 13 #include "MarkLive.h" 14 #include "SymbolTable.h" 15 #include "Writer.h" 16 #include "lld/Common/Args.h" 17 #include "lld/Common/CommonLinkerContext.h" 18 #include "lld/Common/ErrorHandler.h" 19 #include "lld/Common/Filesystem.h" 20 #include "lld/Common/Memory.h" 21 #include "lld/Common/Reproduce.h" 22 #include "lld/Common/Strings.h" 23 #include "lld/Common/Version.h" 24 #include "llvm/ADT/Twine.h" 25 #include "llvm/Config/llvm-config.h" 26 #include "llvm/Object/Wasm.h" 27 #include "llvm/Option/Arg.h" 28 #include "llvm/Option/ArgList.h" 29 #include "llvm/Support/CommandLine.h" 30 #include "llvm/Support/Host.h" 31 #include "llvm/Support/Parallel.h" 32 #include "llvm/Support/Path.h" 33 #include "llvm/Support/Process.h" 34 #include "llvm/Support/TarWriter.h" 35 #include "llvm/Support/TargetSelect.h" 36 #include <optional> 37 38 #define DEBUG_TYPE "lld" 39 40 using namespace llvm; 41 using namespace llvm::object; 42 using namespace llvm::sys; 43 using namespace llvm::wasm; 44 45 namespace lld { 46 namespace wasm { 47 Configuration *config; 48 49 namespace { 50 51 // Create enum with OPT_xxx values for each option in Options.td 52 enum { 53 OPT_INVALID = 0, 54 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, 55 #include "Options.inc" 56 #undef OPTION 57 }; 58 59 // This function is called on startup. We need this for LTO since 60 // LTO calls LLVM functions to compile bitcode files to native code. 61 // Technically this can be delayed until we read bitcode files, but 62 // we don't bother to do lazily because the initialization is fast. 63 static void initLLVM() { 64 InitializeAllTargets(); 65 InitializeAllTargetMCs(); 66 InitializeAllAsmPrinters(); 67 InitializeAllAsmParsers(); 68 } 69 70 class LinkerDriver { 71 public: 72 void linkerMain(ArrayRef<const char *> argsArr); 73 74 private: 75 void createFiles(opt::InputArgList &args); 76 void addFile(StringRef path); 77 void addLibrary(StringRef name); 78 79 // True if we are in --whole-archive and --no-whole-archive. 80 bool inWholeArchive = false; 81 82 std::vector<InputFile *> files; 83 }; 84 } // anonymous namespace 85 86 bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, 87 llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) { 88 // This driver-specific context will be freed later by lldMain(). 89 auto *ctx = new CommonLinkerContext; 90 91 ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput); 92 ctx->e.logName = args::getFilenameWithoutExe(args[0]); 93 ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now (use " 94 "-error-limit=0 to see all errors)"; 95 96 config = make<Configuration>(); 97 symtab = make<SymbolTable>(); 98 99 initLLVM(); 100 LinkerDriver().linkerMain(args); 101 102 return errorCount() == 0; 103 } 104 105 // Create prefix string literals used in Options.td 106 #define PREFIX(NAME, VALUE) \ 107 static constexpr StringLiteral NAME##_init[] = VALUE; \ 108 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 109 std::size(NAME##_init) - 1); 110 #include "Options.inc" 111 #undef PREFIX 112 113 // Create table mapping all options defined in Options.td 114 static constexpr opt::OptTable::Info optInfo[] = { 115 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 116 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ 117 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, 118 #include "Options.inc" 119 #undef OPTION 120 }; 121 122 namespace { 123 class WasmOptTable : public opt::GenericOptTable { 124 public: 125 WasmOptTable() : opt::GenericOptTable(optInfo) {} 126 opt::InputArgList parse(ArrayRef<const char *> argv); 127 }; 128 } // namespace 129 130 // Set color diagnostics according to -color-diagnostics={auto,always,never} 131 // or -no-color-diagnostics flags. 132 static void handleColorDiagnostics(opt::InputArgList &args) { 133 auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, 134 OPT_no_color_diagnostics); 135 if (!arg) 136 return; 137 if (arg->getOption().getID() == OPT_color_diagnostics) { 138 lld::errs().enable_colors(true); 139 } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { 140 lld::errs().enable_colors(false); 141 } else { 142 StringRef s = arg->getValue(); 143 if (s == "always") 144 lld::errs().enable_colors(true); 145 else if (s == "never") 146 lld::errs().enable_colors(false); 147 else if (s != "auto") 148 error("unknown option: --color-diagnostics=" + s); 149 } 150 } 151 152 static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) { 153 if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { 154 StringRef s = arg->getValue(); 155 if (s != "windows" && s != "posix") 156 error("invalid response file quoting: " + s); 157 if (s == "windows") 158 return cl::TokenizeWindowsCommandLine; 159 return cl::TokenizeGNUCommandLine; 160 } 161 if (Triple(sys::getProcessTriple()).isOSWindows()) 162 return cl::TokenizeWindowsCommandLine; 163 return cl::TokenizeGNUCommandLine; 164 } 165 166 // Find a file by concatenating given paths. 167 static std::optional<std::string> findFile(StringRef path1, 168 const Twine &path2) { 169 SmallString<128> s; 170 path::append(s, path1, path2); 171 if (fs::exists(s)) 172 return std::string(s); 173 return std::nullopt; 174 } 175 176 opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) { 177 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); 178 179 unsigned missingIndex; 180 unsigned missingCount; 181 182 // We need to get the quoting style for response files before parsing all 183 // options so we parse here before and ignore all the options but 184 // --rsp-quoting. 185 opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); 186 187 // Expand response files (arguments in the form of @<filename>) 188 // and then parse the argument again. 189 cl::ExpandResponseFiles(saver(), getQuotingStyle(args), vec); 190 args = this->ParseArgs(vec, missingIndex, missingCount); 191 192 handleColorDiagnostics(args); 193 if (missingCount) 194 error(Twine(args.getArgString(missingIndex)) + ": missing argument"); 195 196 for (auto *arg : args.filtered(OPT_UNKNOWN)) 197 error("unknown argument: " + arg->getAsString(args)); 198 return args; 199 } 200 201 // Currently we allow a ".imports" to live alongside a library. This can 202 // be used to specify a list of symbols which can be undefined at link 203 // time (imported from the environment. For example libc.a include an 204 // import file that lists the syscall functions it relies on at runtime. 205 // In the long run this information would be better stored as a symbol 206 // attribute/flag in the object file itself. 207 // See: https://github.com/WebAssembly/tool-conventions/issues/35 208 static void readImportFile(StringRef filename) { 209 if (std::optional<MemoryBufferRef> buf = readFile(filename)) 210 for (StringRef sym : args::getLines(*buf)) 211 config->allowUndefinedSymbols.insert(sym); 212 } 213 214 // Returns slices of MB by parsing MB as an archive file. 215 // Each slice consists of a member file in the archive. 216 std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef mb) { 217 std::unique_ptr<Archive> file = 218 CHECK(Archive::create(mb), 219 mb.getBufferIdentifier() + ": failed to parse archive"); 220 221 std::vector<MemoryBufferRef> v; 222 Error err = Error::success(); 223 for (const Archive::Child &c : file->children(err)) { 224 MemoryBufferRef mbref = 225 CHECK(c.getMemoryBufferRef(), 226 mb.getBufferIdentifier() + 227 ": could not get the buffer for a child of the archive"); 228 v.push_back(mbref); 229 } 230 if (err) 231 fatal(mb.getBufferIdentifier() + 232 ": Archive::children failed: " + toString(std::move(err))); 233 234 // Take ownership of memory buffers created for members of thin archives. 235 for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers()) 236 make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); 237 238 return v; 239 } 240 241 void LinkerDriver::addFile(StringRef path) { 242 std::optional<MemoryBufferRef> buffer = readFile(path); 243 if (!buffer) 244 return; 245 MemoryBufferRef mbref = *buffer; 246 247 switch (identify_magic(mbref.getBuffer())) { 248 case file_magic::archive: { 249 SmallString<128> importFile = path; 250 path::replace_extension(importFile, ".imports"); 251 if (fs::exists(importFile)) 252 readImportFile(importFile.str()); 253 254 // Handle -whole-archive. 255 if (inWholeArchive) { 256 for (MemoryBufferRef &m : getArchiveMembers(mbref)) { 257 auto *object = createObjectFile(m, path); 258 // Mark object as live; object members are normally not 259 // live by default but -whole-archive is designed to treat 260 // them as such. 261 object->markLive(); 262 files.push_back(object); 263 } 264 265 return; 266 } 267 268 std::unique_ptr<Archive> file = 269 CHECK(Archive::create(mbref), path + ": failed to parse archive"); 270 271 if (!file->isEmpty() && !file->hasSymbolTable()) { 272 error(mbref.getBufferIdentifier() + 273 ": archive has no index; run ranlib to add one"); 274 } 275 276 files.push_back(make<ArchiveFile>(mbref)); 277 return; 278 } 279 case file_magic::bitcode: 280 case file_magic::wasm_object: 281 files.push_back(createObjectFile(mbref)); 282 break; 283 case file_magic::unknown: 284 if (mbref.getBuffer().starts_with("#STUB")) { 285 files.push_back(make<StubFile>(mbref)); 286 break; 287 } 288 [[fallthrough]]; 289 default: 290 error("unknown file type: " + mbref.getBufferIdentifier()); 291 } 292 } 293 294 static std::optional<std::string> findFromSearchPaths(StringRef path) { 295 for (StringRef dir : config->searchPaths) 296 if (std::optional<std::string> s = findFile(dir, path)) 297 return s; 298 return std::nullopt; 299 } 300 301 // This is for -l<basename>. We'll look for lib<basename>.a from 302 // search paths. 303 static std::optional<std::string> searchLibraryBaseName(StringRef name) { 304 for (StringRef dir : config->searchPaths) { 305 // Currently we don't enable dyanmic linking at all unless -shared or -pie 306 // are used, so don't even look for .so files in that case.. 307 if (config->isPic && !config->isStatic) 308 if (std::optional<std::string> s = findFile(dir, "lib" + name + ".so")) 309 return s; 310 if (std::optional<std::string> s = findFile(dir, "lib" + name + ".a")) 311 return s; 312 } 313 return std::nullopt; 314 } 315 316 // This is for -l<namespec>. 317 static std::optional<std::string> searchLibrary(StringRef name) { 318 if (name.startswith(":")) 319 return findFromSearchPaths(name.substr(1)); 320 return searchLibraryBaseName(name); 321 } 322 323 // Add a given library by searching it from input search paths. 324 void LinkerDriver::addLibrary(StringRef name) { 325 if (std::optional<std::string> path = searchLibrary(name)) 326 addFile(saver().save(*path)); 327 else 328 error("unable to find library -l" + name, ErrorTag::LibNotFound, {name}); 329 } 330 331 void LinkerDriver::createFiles(opt::InputArgList &args) { 332 for (auto *arg : args) { 333 switch (arg->getOption().getID()) { 334 case OPT_library: 335 addLibrary(arg->getValue()); 336 break; 337 case OPT_INPUT: 338 addFile(arg->getValue()); 339 break; 340 case OPT_Bstatic: 341 config->isStatic = true; 342 break; 343 case OPT_Bdynamic: 344 config->isStatic = false; 345 break; 346 case OPT_whole_archive: 347 inWholeArchive = true; 348 break; 349 case OPT_no_whole_archive: 350 inWholeArchive = false; 351 break; 352 } 353 } 354 if (files.empty() && errorCount() == 0) 355 error("no input files"); 356 } 357 358 static StringRef getEntry(opt::InputArgList &args) { 359 auto *arg = args.getLastArg(OPT_entry, OPT_no_entry); 360 if (!arg) { 361 if (args.hasArg(OPT_relocatable)) 362 return ""; 363 if (args.hasArg(OPT_shared)) 364 return "__wasm_call_ctors"; 365 return "_start"; 366 } 367 if (arg->getOption().getID() == OPT_no_entry) 368 return ""; 369 return arg->getValue(); 370 } 371 372 // Determines what we should do if there are remaining unresolved 373 // symbols after the name resolution. 374 static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &args) { 375 UnresolvedPolicy errorOrWarn = args.hasFlag(OPT_error_unresolved_symbols, 376 OPT_warn_unresolved_symbols, true) 377 ? UnresolvedPolicy::ReportError 378 : UnresolvedPolicy::Warn; 379 380 if (auto *arg = args.getLastArg(OPT_unresolved_symbols)) { 381 StringRef s = arg->getValue(); 382 if (s == "ignore-all") 383 return UnresolvedPolicy::Ignore; 384 if (s == "import-dynamic") 385 return UnresolvedPolicy::ImportDynamic; 386 if (s == "report-all") 387 return errorOrWarn; 388 error("unknown --unresolved-symbols value: " + s); 389 } 390 391 return errorOrWarn; 392 } 393 394 // Initializes Config members by the command line options. 395 static void readConfigs(opt::InputArgList &args) { 396 config->bsymbolic = args.hasArg(OPT_Bsymbolic); 397 config->checkFeatures = 398 args.hasFlag(OPT_check_features, OPT_no_check_features, true); 399 config->compressRelocations = args.hasArg(OPT_compress_relocations); 400 config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true); 401 config->disableVerify = args.hasArg(OPT_disable_verify); 402 config->emitRelocs = args.hasArg(OPT_emit_relocs); 403 config->experimentalPic = args.hasArg(OPT_experimental_pic); 404 config->entry = getEntry(args); 405 config->exportAll = args.hasArg(OPT_export_all); 406 config->exportTable = args.hasArg(OPT_export_table); 407 config->growableTable = args.hasArg(OPT_growable_table); 408 409 if (args.hasArg(OPT_import_memory_with_name)) { 410 config->memoryImport = 411 args.getLastArgValue(OPT_import_memory_with_name).split(","); 412 } else if (args.hasArg(OPT_import_memory)) { 413 config->memoryImport = 414 std::pair<llvm::StringRef, llvm::StringRef>(defaultModule, memoryName); 415 } else { 416 config->memoryImport = 417 std::optional<std::pair<llvm::StringRef, llvm::StringRef>>(); 418 } 419 420 if (args.hasArg(OPT_export_memory_with_name)) { 421 config->memoryExport = 422 args.getLastArgValue(OPT_export_memory_with_name); 423 } else if (args.hasArg(OPT_export_memory)) { 424 config->memoryExport = memoryName; 425 } else { 426 config->memoryExport = std::optional<llvm::StringRef>(); 427 } 428 429 config->sharedMemory = args.hasArg(OPT_shared_memory); 430 config->importTable = args.hasArg(OPT_import_table); 431 config->importUndefined = args.hasArg(OPT_import_undefined); 432 config->ltoo = args::getInteger(args, OPT_lto_O, 2); 433 config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); 434 config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager); 435 config->mapFile = args.getLastArgValue(OPT_Map); 436 config->optimize = args::getInteger(args, OPT_O, 1); 437 config->outputFile = args.getLastArgValue(OPT_o); 438 config->relocatable = args.hasArg(OPT_relocatable); 439 config->gcSections = 440 args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable); 441 config->mergeDataSegments = 442 args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments, 443 !config->relocatable); 444 config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false); 445 config->printGcSections = 446 args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); 447 config->saveTemps = args.hasArg(OPT_save_temps); 448 config->searchPaths = args::getStrings(args, OPT_library_path); 449 config->shared = args.hasArg(OPT_shared); 450 config->stripAll = args.hasArg(OPT_strip_all); 451 config->stripDebug = args.hasArg(OPT_strip_debug); 452 config->stackFirst = args.hasArg(OPT_stack_first); 453 config->trace = args.hasArg(OPT_trace); 454 config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir); 455 config->thinLTOCachePolicy = CHECK( 456 parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)), 457 "--thinlto-cache-policy: invalid cache policy"); 458 config->unresolvedSymbols = getUnresolvedSymbolPolicy(args); 459 config->whyExtract = args.getLastArgValue(OPT_why_extract); 460 errorHandler().verbose = args.hasArg(OPT_verbose); 461 LLVM_DEBUG(errorHandler().verbose = true); 462 463 config->initialMemory = args::getInteger(args, OPT_initial_memory, 0); 464 config->globalBase = args::getInteger(args, OPT_global_base, 0); 465 config->maxMemory = args::getInteger(args, OPT_max_memory, 0); 466 config->zStackSize = 467 args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize); 468 469 // Default value of exportDynamic depends on `-shared` 470 config->exportDynamic = 471 args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared); 472 473 // Parse wasm32/64. 474 if (auto *arg = args.getLastArg(OPT_m)) { 475 StringRef s = arg->getValue(); 476 if (s == "wasm32") 477 config->is64 = false; 478 else if (s == "wasm64") 479 config->is64 = true; 480 else 481 error("invalid target architecture: " + s); 482 } 483 484 // --threads= takes a positive integer and provides the default value for 485 // --thinlto-jobs=. 486 if (auto *arg = args.getLastArg(OPT_threads)) { 487 StringRef v(arg->getValue()); 488 unsigned threads = 0; 489 if (!llvm::to_integer(v, threads, 0) || threads == 0) 490 error(arg->getSpelling() + ": expected a positive integer, but got '" + 491 arg->getValue() + "'"); 492 parallel::strategy = hardware_concurrency(threads); 493 config->thinLTOJobs = v; 494 } 495 if (auto *arg = args.getLastArg(OPT_thinlto_jobs)) 496 config->thinLTOJobs = arg->getValue(); 497 498 if (auto *arg = args.getLastArg(OPT_features)) { 499 config->features = 500 std::optional<std::vector<std::string>>(std::vector<std::string>()); 501 for (StringRef s : arg->getValues()) 502 config->features->push_back(std::string(s)); 503 } 504 505 if (auto *arg = args.getLastArg(OPT_extra_features)) { 506 config->extraFeatures = 507 std::optional<std::vector<std::string>>(std::vector<std::string>()); 508 for (StringRef s : arg->getValues()) 509 config->extraFeatures->push_back(std::string(s)); 510 } 511 512 // Legacy --allow-undefined flag which is equivalent to 513 // --unresolve-symbols=ignore + --import-undefined 514 if (args.hasArg(OPT_allow_undefined)) { 515 config->importUndefined = true; 516 config->unresolvedSymbols = UnresolvedPolicy::Ignore; 517 } 518 519 if (args.hasArg(OPT_print_map)) 520 config->mapFile = "-"; 521 } 522 523 // Some Config members do not directly correspond to any particular 524 // command line options, but computed based on other Config values. 525 // This function initialize such members. See Config.h for the details 526 // of these values. 527 static void setConfigs() { 528 config->isPic = config->pie || config->shared; 529 530 if (config->isPic) { 531 if (config->exportTable) 532 error("-shared/-pie is incompatible with --export-table"); 533 config->importTable = true; 534 } 535 536 if (config->relocatable) { 537 if (config->exportTable) 538 error("--relocatable is incompatible with --export-table"); 539 if (config->growableTable) 540 error("--relocatable is incompatible with --growable-table"); 541 // Ignore any --import-table, as it's redundant. 542 config->importTable = true; 543 } 544 545 if (config->shared) { 546 if (config->memoryExport.has_value()) { 547 error("--export-memory is incompatible with --shared"); 548 } 549 if (!config->memoryImport.has_value()) { 550 config->memoryImport = 551 std::pair<llvm::StringRef, llvm::StringRef>(defaultModule, memoryName); 552 } 553 config->importUndefined = true; 554 } 555 556 // If neither export-memory nor import-memory is specified, default to 557 // exporting memory under its default name. 558 if (!config->memoryExport.has_value() && !config->memoryImport.has_value()) { 559 config->memoryExport = memoryName; 560 } 561 } 562 563 // Some command line options or some combinations of them are not allowed. 564 // This function checks for such errors. 565 static void checkOptions(opt::InputArgList &args) { 566 if (!config->stripDebug && !config->stripAll && config->compressRelocations) 567 error("--compress-relocations is incompatible with output debug" 568 " information. Please pass --strip-debug or --strip-all"); 569 570 if (config->ltoo > 3) 571 error("invalid optimization level for LTO: " + Twine(config->ltoo)); 572 if (config->ltoPartitions == 0) 573 error("--lto-partitions: number of threads must be > 0"); 574 if (!get_threadpool_strategy(config->thinLTOJobs)) 575 error("--thinlto-jobs: invalid job count: " + config->thinLTOJobs); 576 577 if (config->pie && config->shared) 578 error("-shared and -pie may not be used together"); 579 580 if (config->outputFile.empty()) 581 error("no output file specified"); 582 583 if (config->importTable && config->exportTable) 584 error("--import-table and --export-table may not be used together"); 585 586 if (config->relocatable) { 587 if (!config->entry.empty()) 588 error("entry point specified for relocatable output file"); 589 if (config->gcSections) 590 error("-r and --gc-sections may not be used together"); 591 if (config->compressRelocations) 592 error("-r -and --compress-relocations may not be used together"); 593 if (args.hasArg(OPT_undefined)) 594 error("-r -and --undefined may not be used together"); 595 if (config->pie) 596 error("-r and -pie may not be used together"); 597 if (config->sharedMemory) 598 error("-r and --shared-memory may not be used together"); 599 if (config->globalBase) 600 error("-r and --global-base may not by used together"); 601 } 602 603 // To begin to prepare for Module Linking-style shared libraries, start 604 // warning about uses of `-shared` and related flags outside of Experimental 605 // mode, to give anyone using them a heads-up that they will be changing. 606 // 607 // Also, warn about flags which request explicit exports. 608 if (!config->experimentalPic) { 609 // -shared will change meaning when Module Linking is implemented. 610 if (config->shared) { 611 warn("creating shared libraries, with -shared, is not yet stable"); 612 } 613 614 // -pie will change meaning when Module Linking is implemented. 615 if (config->pie) { 616 warn("creating PIEs, with -pie, is not yet stable"); 617 } 618 619 if (config->unresolvedSymbols == UnresolvedPolicy::ImportDynamic) { 620 warn("dynamic imports are not yet stable " 621 "(--unresolved-symbols=import-dynamic)"); 622 } 623 } 624 625 if (config->bsymbolic && !config->shared) { 626 warn("-Bsymbolic is only meaningful when combined with -shared"); 627 } 628 629 if (config->globalBase && config->isPic) { 630 error("--global-base may not be used with -shared/-pie"); 631 } 632 } 633 634 static const char *getReproduceOption(opt::InputArgList &args) { 635 if (auto *arg = args.getLastArg(OPT_reproduce)) 636 return arg->getValue(); 637 return getenv("LLD_REPRODUCE"); 638 } 639 640 // Force Sym to be entered in the output. Used for -u or equivalent. 641 static Symbol *handleUndefined(StringRef name, const char *option) { 642 Symbol *sym = symtab->find(name); 643 if (!sym) 644 return nullptr; 645 646 // Since symbol S may not be used inside the program, LTO may 647 // eliminate it. Mark the symbol as "used" to prevent it. 648 sym->isUsedInRegularObj = true; 649 650 if (auto *lazySym = dyn_cast<LazySymbol>(sym)) { 651 lazySym->fetch(); 652 if (!config->whyExtract.empty()) 653 config->whyExtractRecords.emplace_back(option, sym->getFile(), *sym); 654 } 655 656 return sym; 657 } 658 659 static void handleLibcall(StringRef name) { 660 Symbol *sym = symtab->find(name); 661 if (!sym) 662 return; 663 664 if (auto *lazySym = dyn_cast<LazySymbol>(sym)) { 665 MemoryBufferRef mb = lazySym->getMemberBuffer(); 666 if (isBitcode(mb)) { 667 if (!config->whyExtract.empty()) 668 config->whyExtractRecords.emplace_back("<libcall>", sym->getFile(), 669 *sym); 670 lazySym->fetch(); 671 } 672 } 673 } 674 675 static void writeWhyExtract() { 676 if (config->whyExtract.empty()) 677 return; 678 679 std::error_code ec; 680 raw_fd_ostream os(config->whyExtract, ec, sys::fs::OF_None); 681 if (ec) { 682 error("cannot open --why-extract= file " + config->whyExtract + ": " + 683 ec.message()); 684 return; 685 } 686 687 os << "reference\textracted\tsymbol\n"; 688 for (auto &entry : config->whyExtractRecords) { 689 os << std::get<0>(entry) << '\t' << toString(std::get<1>(entry)) << '\t' 690 << toString(std::get<2>(entry)) << '\n'; 691 } 692 } 693 694 // Equivalent of demote demoteSharedAndLazySymbols() in the ELF linker 695 static void demoteLazySymbols() { 696 for (Symbol *sym : symtab->symbols()) { 697 if (auto* s = dyn_cast<LazySymbol>(sym)) { 698 if (s->signature) { 699 LLVM_DEBUG(llvm::dbgs() 700 << "demoting lazy func: " << s->getName() << "\n"); 701 replaceSymbol<UndefinedFunction>(s, s->getName(), std::nullopt, 702 std::nullopt, WASM_SYMBOL_BINDING_WEAK, 703 s->getFile(), s->signature); 704 } 705 } 706 } 707 } 708 709 static UndefinedGlobal * 710 createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) { 711 auto *sym = cast<UndefinedGlobal>(symtab->addUndefinedGlobal( 712 name, std::nullopt, std::nullopt, WASM_SYMBOL_UNDEFINED, nullptr, type)); 713 config->allowUndefinedSymbols.insert(sym->getName()); 714 sym->isUsedInRegularObj = true; 715 return sym; 716 } 717 718 static InputGlobal *createGlobal(StringRef name, bool isMutable) { 719 llvm::wasm::WasmGlobal wasmGlobal; 720 bool is64 = config->is64.value_or(false); 721 wasmGlobal.Type = {uint8_t(is64 ? WASM_TYPE_I64 : WASM_TYPE_I32), isMutable}; 722 wasmGlobal.InitExpr = intConst(0, is64); 723 wasmGlobal.SymbolName = name; 724 return make<InputGlobal>(wasmGlobal, nullptr); 725 } 726 727 static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable) { 728 InputGlobal *g = createGlobal(name, isMutable); 729 return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN, g); 730 } 731 732 static GlobalSymbol *createOptionalGlobal(StringRef name, bool isMutable) { 733 InputGlobal *g = createGlobal(name, isMutable); 734 return symtab->addOptionalGlobalSymbol(name, g); 735 } 736 737 // Create ABI-defined synthetic symbols 738 static void createSyntheticSymbols() { 739 if (config->relocatable) 740 return; 741 742 static WasmSignature nullSignature = {{}, {}}; 743 static WasmSignature i32ArgSignature = {{}, {ValType::I32}}; 744 static WasmSignature i64ArgSignature = {{}, {ValType::I64}}; 745 static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false}; 746 static llvm::wasm::WasmGlobalType globalTypeI64 = {WASM_TYPE_I64, false}; 747 static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32, 748 true}; 749 static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64, 750 true}; 751 WasmSym::callCtors = symtab->addSyntheticFunction( 752 "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN, 753 make<SyntheticFunction>(nullSignature, "__wasm_call_ctors")); 754 755 bool is64 = config->is64.value_or(false); 756 757 if (config->isPic) { 758 WasmSym::stackPointer = 759 createUndefinedGlobal("__stack_pointer", config->is64.value_or(false) 760 ? &mutableGlobalTypeI64 761 : &mutableGlobalTypeI32); 762 // For PIC code, we import two global variables (__memory_base and 763 // __table_base) from the environment and use these as the offset at 764 // which to load our static data and function table. 765 // See: 766 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md 767 auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32; 768 WasmSym::memoryBase = createUndefinedGlobal("__memory_base", globalType); 769 WasmSym::tableBase = createUndefinedGlobal("__table_base", globalType); 770 WasmSym::memoryBase->markLive(); 771 WasmSym::tableBase->markLive(); 772 if (is64) { 773 WasmSym::tableBase32 = 774 createUndefinedGlobal("__table_base32", &globalTypeI32); 775 WasmSym::tableBase32->markLive(); 776 } else { 777 WasmSym::tableBase32 = nullptr; 778 } 779 } else { 780 // For non-PIC code 781 WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true); 782 WasmSym::stackPointer->markLive(); 783 } 784 785 if (config->sharedMemory) { 786 WasmSym::tlsBase = createGlobalVariable("__tls_base", true); 787 WasmSym::tlsSize = createGlobalVariable("__tls_size", false); 788 WasmSym::tlsAlign = createGlobalVariable("__tls_align", false); 789 WasmSym::initTLS = symtab->addSyntheticFunction( 790 "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN, 791 make<SyntheticFunction>( 792 is64 ? i64ArgSignature : i32ArgSignature, 793 "__wasm_init_tls")); 794 } 795 796 if (config->isPic || 797 config->unresolvedSymbols == UnresolvedPolicy::ImportDynamic) { 798 // For PIC code, or when dynamically importing addresses, we create 799 // synthetic functions that apply relocations. These get called from 800 // __wasm_call_ctors before the user-level constructors. 801 WasmSym::applyDataRelocs = symtab->addSyntheticFunction( 802 "__wasm_apply_data_relocs", 803 WASM_SYMBOL_VISIBILITY_DEFAULT | WASM_SYMBOL_EXPORTED, 804 make<SyntheticFunction>(nullSignature, "__wasm_apply_data_relocs")); 805 } 806 } 807 808 static void createOptionalSymbols() { 809 if (config->relocatable) 810 return; 811 812 WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle"); 813 814 if (!config->shared) 815 WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end"); 816 817 if (!config->isPic) { 818 WasmSym::stackLow = symtab->addOptionalDataSymbol("__stack_low"); 819 WasmSym::stackHigh = symtab->addOptionalDataSymbol("__stack_high"); 820 WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base"); 821 WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base"); 822 WasmSym::heapEnd = symtab->addOptionalDataSymbol("__heap_end"); 823 WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base"); 824 WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base"); 825 if (config->is64.value_or(false)) 826 WasmSym::definedTableBase32 = 827 symtab->addOptionalDataSymbol("__table_base32"); 828 } 829 830 // For non-shared memory programs we still need to define __tls_base since we 831 // allow object files built with TLS to be linked into single threaded 832 // programs, and such object files can contain references to this symbol. 833 // 834 // However, in this case __tls_base is immutable and points directly to the 835 // start of the `.tdata` static segment. 836 // 837 // __tls_size and __tls_align are not needed in this case since they are only 838 // needed for __wasm_init_tls (which we do not create in this case). 839 if (!config->sharedMemory) 840 WasmSym::tlsBase = createOptionalGlobal("__tls_base", false); 841 } 842 843 static void processStubLibraries() { 844 log("-- processStubLibraries"); 845 for (auto &stub_file : symtab->stubFiles) { 846 LLVM_DEBUG(llvm::dbgs() 847 << "processing stub file: " << stub_file->getName() << "\n"); 848 for (auto [name, deps]: stub_file->symbolDependencies) { 849 auto* sym = symtab->find(name); 850 if (!sym || !sym->isUndefined() || !sym->isUsedInRegularObj || 851 sym->forceImport) { 852 LLVM_DEBUG(llvm::dbgs() << "stub not in needed: " << name << "\n"); 853 continue; 854 } 855 // The first stub library to define a given symbol sets this and 856 // definitions in later stub libraries are ignored. 857 sym->forceImport = true; 858 if (sym->traced) 859 message(toString(stub_file) + ": importing " + name); 860 else 861 LLVM_DEBUG(llvm::dbgs() 862 << toString(stub_file) << ": importing " << name << "\n"); 863 for (const auto dep : deps) { 864 auto* needed = symtab->find(dep); 865 if (!needed) { 866 error(toString(stub_file) + ": undefined symbol: " + dep + 867 ". Required by " + toString(*sym)); 868 } else if (needed->isUndefined()) { 869 error(toString(stub_file) + 870 ": undefined symbol: " + toString(*needed) + 871 ". Required by " + toString(*sym)); 872 } else { 873 LLVM_DEBUG(llvm::dbgs() 874 << "force export: " << toString(*needed) << "\n"); 875 needed->forceExport = true; 876 needed->isUsedInRegularObj = true; 877 if (auto *lazy = dyn_cast<LazySymbol>(needed)) { 878 lazy->fetch(); 879 if (!config->whyExtract.empty()) 880 config->whyExtractRecords.emplace_back(stub_file->getName(), 881 sym->getFile(), *sym); 882 } 883 } 884 } 885 } 886 } 887 log("-- done processStubLibraries"); 888 } 889 890 // Reconstructs command line arguments so that so that you can re-run 891 // the same command with the same inputs. This is for --reproduce. 892 static std::string createResponseFile(const opt::InputArgList &args) { 893 SmallString<0> data; 894 raw_svector_ostream os(data); 895 896 // Copy the command line to the output while rewriting paths. 897 for (auto *arg : args) { 898 switch (arg->getOption().getID()) { 899 case OPT_reproduce: 900 break; 901 case OPT_INPUT: 902 os << quote(relativeToRoot(arg->getValue())) << "\n"; 903 break; 904 case OPT_o: 905 // If -o path contains directories, "lld @response.txt" will likely 906 // fail because the archive we are creating doesn't contain empty 907 // directories for the output path (-o doesn't create directories). 908 // Strip directories to prevent the issue. 909 os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n"; 910 break; 911 default: 912 os << toString(*arg) << "\n"; 913 } 914 } 915 return std::string(data.str()); 916 } 917 918 // The --wrap option is a feature to rename symbols so that you can write 919 // wrappers for existing functions. If you pass `-wrap=foo`, all 920 // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are 921 // expected to write `wrap_foo` function as a wrapper). The original 922 // symbol becomes accessible as `real_foo`, so you can call that from your 923 // wrapper. 924 // 925 // This data structure is instantiated for each -wrap option. 926 struct WrappedSymbol { 927 Symbol *sym; 928 Symbol *real; 929 Symbol *wrap; 930 }; 931 932 static Symbol *addUndefined(StringRef name) { 933 return symtab->addUndefinedFunction(name, std::nullopt, std::nullopt, 934 WASM_SYMBOL_UNDEFINED, nullptr, nullptr, 935 false); 936 } 937 938 // Handles -wrap option. 939 // 940 // This function instantiates wrapper symbols. At this point, they seem 941 // like they are not being used at all, so we explicitly set some flags so 942 // that LTO won't eliminate them. 943 static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) { 944 std::vector<WrappedSymbol> v; 945 DenseSet<StringRef> seen; 946 947 for (auto *arg : args.filtered(OPT_wrap)) { 948 StringRef name = arg->getValue(); 949 if (!seen.insert(name).second) 950 continue; 951 952 Symbol *sym = symtab->find(name); 953 if (!sym) 954 continue; 955 956 Symbol *real = addUndefined(saver().save("__real_" + name)); 957 Symbol *wrap = addUndefined(saver().save("__wrap_" + name)); 958 v.push_back({sym, real, wrap}); 959 960 // We want to tell LTO not to inline symbols to be overwritten 961 // because LTO doesn't know the final symbol contents after renaming. 962 real->canInline = false; 963 sym->canInline = false; 964 965 // Tell LTO not to eliminate these symbols. 966 sym->isUsedInRegularObj = true; 967 wrap->isUsedInRegularObj = true; 968 real->isUsedInRegularObj = false; 969 } 970 return v; 971 } 972 973 // Do renaming for -wrap by updating pointers to symbols. 974 // 975 // When this function is executed, only InputFiles and symbol table 976 // contain pointers to symbol objects. We visit them to replace pointers, 977 // so that wrapped symbols are swapped as instructed by the command line. 978 static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) { 979 DenseMap<Symbol *, Symbol *> map; 980 for (const WrappedSymbol &w : wrapped) { 981 map[w.sym] = w.wrap; 982 map[w.real] = w.sym; 983 } 984 985 // Update pointers in input files. 986 parallelForEach(symtab->objectFiles, [&](InputFile *file) { 987 MutableArrayRef<Symbol *> syms = file->getMutableSymbols(); 988 for (size_t i = 0, e = syms.size(); i != e; ++i) 989 if (Symbol *s = map.lookup(syms[i])) 990 syms[i] = s; 991 }); 992 993 // Update pointers in the symbol table. 994 for (const WrappedSymbol &w : wrapped) 995 symtab->wrap(w.sym, w.real, w.wrap); 996 } 997 998 static void splitSections() { 999 // splitIntoPieces needs to be called on each MergeInputChunk 1000 // before calling finalizeContents(). 1001 LLVM_DEBUG(llvm::dbgs() << "splitSections\n"); 1002 parallelForEach(symtab->objectFiles, [](ObjFile *file) { 1003 for (InputChunk *seg : file->segments) { 1004 if (auto *s = dyn_cast<MergeInputChunk>(seg)) 1005 s->splitIntoPieces(); 1006 } 1007 for (InputChunk *sec : file->customSections) { 1008 if (auto *s = dyn_cast<MergeInputChunk>(sec)) 1009 s->splitIntoPieces(); 1010 } 1011 }); 1012 } 1013 1014 static bool isKnownZFlag(StringRef s) { 1015 // For now, we only support a very limited set of -z flags 1016 return s.startswith("stack-size="); 1017 } 1018 1019 // Report a warning for an unknown -z option. 1020 static void checkZOptions(opt::InputArgList &args) { 1021 for (auto *arg : args.filtered(OPT_z)) 1022 if (!isKnownZFlag(arg->getValue())) 1023 warn("unknown -z value: " + StringRef(arg->getValue())); 1024 } 1025 1026 void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { 1027 WasmOptTable parser; 1028 opt::InputArgList args = parser.parse(argsArr.slice(1)); 1029 1030 // Interpret these flags early because error()/warn() depend on them. 1031 errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20); 1032 errorHandler().fatalWarnings = 1033 args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); 1034 checkZOptions(args); 1035 1036 // Handle --help 1037 if (args.hasArg(OPT_help)) { 1038 parser.printHelp(lld::outs(), 1039 (std::string(argsArr[0]) + " [options] file...").c_str(), 1040 "LLVM Linker", false); 1041 return; 1042 } 1043 1044 // Handle --version 1045 if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) { 1046 lld::outs() << getLLDVersion() << "\n"; 1047 return; 1048 } 1049 1050 // Handle --reproduce 1051 if (const char *path = getReproduceOption(args)) { 1052 Expected<std::unique_ptr<TarWriter>> errOrWriter = 1053 TarWriter::create(path, path::stem(path)); 1054 if (errOrWriter) { 1055 tar = std::move(*errOrWriter); 1056 tar->append("response.txt", createResponseFile(args)); 1057 tar->append("version.txt", getLLDVersion() + "\n"); 1058 } else { 1059 error("--reproduce: " + toString(errOrWriter.takeError())); 1060 } 1061 } 1062 1063 // Parse and evaluate -mllvm options. 1064 std::vector<const char *> v; 1065 v.push_back("wasm-ld (LLVM option parsing)"); 1066 for (auto *arg : args.filtered(OPT_mllvm)) 1067 v.push_back(arg->getValue()); 1068 cl::ResetAllOptionOccurrences(); 1069 cl::ParseCommandLineOptions(v.size(), v.data()); 1070 1071 readConfigs(args); 1072 setConfigs(); 1073 1074 createFiles(args); 1075 if (errorCount()) 1076 return; 1077 1078 checkOptions(args); 1079 if (errorCount()) 1080 return; 1081 1082 if (auto *arg = args.getLastArg(OPT_allow_undefined_file)) 1083 readImportFile(arg->getValue()); 1084 1085 // Fail early if the output file or map file is not writable. If a user has a 1086 // long link, e.g. due to a large LTO link, they do not wish to run it and 1087 // find that it failed because there was a mistake in their command-line. 1088 if (auto e = tryCreateFile(config->outputFile)) 1089 error("cannot open output file " + config->outputFile + ": " + e.message()); 1090 if (auto e = tryCreateFile(config->mapFile)) 1091 error("cannot open map file " + config->mapFile + ": " + e.message()); 1092 if (errorCount()) 1093 return; 1094 1095 // Handle --trace-symbol. 1096 for (auto *arg : args.filtered(OPT_trace_symbol)) 1097 symtab->trace(arg->getValue()); 1098 1099 for (auto *arg : args.filtered(OPT_export_if_defined)) 1100 config->exportedSymbols.insert(arg->getValue()); 1101 1102 for (auto *arg : args.filtered(OPT_export)) { 1103 config->exportedSymbols.insert(arg->getValue()); 1104 config->requiredExports.push_back(arg->getValue()); 1105 } 1106 1107 createSyntheticSymbols(); 1108 1109 // Add all files to the symbol table. This will add almost all 1110 // symbols that we need to the symbol table. 1111 for (InputFile *f : files) 1112 symtab->addFile(f); 1113 if (errorCount()) 1114 return; 1115 1116 // Handle the `--undefined <sym>` options. 1117 for (auto *arg : args.filtered(OPT_undefined)) 1118 handleUndefined(arg->getValue(), "<internal>"); 1119 1120 // Handle the `--export <sym>` options 1121 // This works like --undefined but also exports the symbol if its found 1122 for (auto &iter : config->exportedSymbols) 1123 handleUndefined(iter.first(), "--export"); 1124 1125 Symbol *entrySym = nullptr; 1126 if (!config->relocatable && !config->entry.empty()) { 1127 entrySym = handleUndefined(config->entry, "--entry"); 1128 if (entrySym && entrySym->isDefined()) 1129 entrySym->forceExport = true; 1130 else 1131 error("entry symbol not defined (pass --no-entry to suppress): " + 1132 config->entry); 1133 } 1134 1135 // If the user code defines a `__wasm_call_dtors` function, remember it so 1136 // that we can call it from the command export wrappers. Unlike 1137 // `__wasm_call_ctors` which we synthesize, `__wasm_call_dtors` is defined 1138 // by libc/etc., because destructors are registered dynamically with 1139 // `__cxa_atexit` and friends. 1140 if (!config->relocatable && !config->shared && 1141 !WasmSym::callCtors->isUsedInRegularObj && 1142 WasmSym::callCtors->getName() != config->entry && 1143 !config->exportedSymbols.count(WasmSym::callCtors->getName())) { 1144 if (Symbol *callDtors = 1145 handleUndefined("__wasm_call_dtors", "<internal>")) { 1146 if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(callDtors)) { 1147 if (callDtorsFunc->signature && 1148 (!callDtorsFunc->signature->Params.empty() || 1149 !callDtorsFunc->signature->Returns.empty())) { 1150 error("__wasm_call_dtors must have no argument or return values"); 1151 } 1152 WasmSym::callDtors = callDtorsFunc; 1153 } else { 1154 error("__wasm_call_dtors must be a function"); 1155 } 1156 } 1157 } 1158 1159 if (errorCount()) 1160 return; 1161 1162 // Create wrapped symbols for -wrap option. 1163 std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args); 1164 1165 // If any of our inputs are bitcode files, the LTO code generator may create 1166 // references to certain library functions that might not be explicit in the 1167 // bitcode file's symbol table. If any of those library functions are defined 1168 // in a bitcode file in an archive member, we need to arrange to use LTO to 1169 // compile those archive members by adding them to the link beforehand. 1170 // 1171 // We only need to add libcall symbols to the link before LTO if the symbol's 1172 // definition is in bitcode. Any other required libcall symbols will be added 1173 // to the link after LTO when we add the LTO object file to the link. 1174 if (!symtab->bitcodeFiles.empty()) 1175 for (auto *s : lto::LTO::getRuntimeLibcallSymbols()) 1176 handleLibcall(s); 1177 if (errorCount()) 1178 return; 1179 1180 writeWhyExtract(); 1181 1182 // Do link-time optimization if given files are LLVM bitcode files. 1183 // This compiles bitcode files into real object files. 1184 symtab->compileBitcodeFiles(); 1185 if (errorCount()) 1186 return; 1187 1188 processStubLibraries(); 1189 1190 createOptionalSymbols(); 1191 1192 // Resolve any variant symbols that were created due to signature 1193 // mismatchs. 1194 symtab->handleSymbolVariants(); 1195 if (errorCount()) 1196 return; 1197 1198 // Apply symbol renames for -wrap. 1199 if (!wrapped.empty()) 1200 wrapSymbols(wrapped); 1201 1202 for (auto &iter : config->exportedSymbols) { 1203 Symbol *sym = symtab->find(iter.first()); 1204 if (sym && sym->isDefined()) 1205 sym->forceExport = true; 1206 } 1207 1208 if (!config->relocatable && !config->isPic) { 1209 // Add synthetic dummies for weak undefined functions. Must happen 1210 // after LTO otherwise functions may not yet have signatures. 1211 symtab->handleWeakUndefines(); 1212 } 1213 1214 if (entrySym) 1215 entrySym->setHidden(false); 1216 1217 if (errorCount()) 1218 return; 1219 1220 // Split WASM_SEG_FLAG_STRINGS sections into pieces in preparation for garbage 1221 // collection. 1222 splitSections(); 1223 1224 // Any remaining lazy symbols should be demoted to Undefined 1225 demoteLazySymbols(); 1226 1227 // Do size optimizations: garbage collection 1228 markLive(); 1229 1230 // Provide the indirect function table if needed. 1231 WasmSym::indirectFunctionTable = 1232 symtab->resolveIndirectFunctionTable(/*required =*/false); 1233 1234 if (errorCount()) 1235 return; 1236 1237 // Write the result to the file. 1238 writeResult(); 1239 } 1240 1241 } // namespace wasm 1242 } // namespace lld 1243