xref: /llvm-project-15.0.7/lld/wasm/Driver.cpp (revision c98ec609)
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 "InputGlobal.h"
13 #include "MarkLive.h"
14 #include "SymbolTable.h"
15 #include "Writer.h"
16 #include "lld/Common/Args.h"
17 #include "lld/Common/ErrorHandler.h"
18 #include "lld/Common/Memory.h"
19 #include "lld/Common/Reproduce.h"
20 #include "lld/Common/Strings.h"
21 #include "lld/Common/Threads.h"
22 #include "lld/Common/Version.h"
23 #include "llvm/ADT/Twine.h"
24 #include "llvm/Object/Wasm.h"
25 #include "llvm/Option/Arg.h"
26 #include "llvm/Option/ArgList.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/Path.h"
29 #include "llvm/Support/Process.h"
30 #include "llvm/Support/TarWriter.h"
31 #include "llvm/Support/TargetSelect.h"
32 
33 #define DEBUG_TYPE "lld"
34 
35 using namespace llvm;
36 using namespace llvm::object;
37 using namespace llvm::sys;
38 using namespace llvm::wasm;
39 
40 using namespace lld;
41 using namespace lld::wasm;
42 
43 Configuration *lld::wasm::config;
44 
45 namespace {
46 
47 // Create enum with OPT_xxx values for each option in Options.td
48 enum {
49   OPT_INVALID = 0,
50 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
51 #include "Options.inc"
52 #undef OPTION
53 };
54 
55 // This function is called on startup. We need this for LTO since
56 // LTO calls LLVM functions to compile bitcode files to native code.
57 // Technically this can be delayed until we read bitcode files, but
58 // we don't bother to do lazily because the initialization is fast.
59 static void initLLVM() {
60   InitializeAllTargets();
61   InitializeAllTargetMCs();
62   InitializeAllAsmPrinters();
63   InitializeAllAsmParsers();
64 }
65 
66 class LinkerDriver {
67 public:
68   void link(ArrayRef<const char *> argsArr);
69 
70 private:
71   void createFiles(opt::InputArgList &args);
72   void addFile(StringRef path);
73   void addLibrary(StringRef name);
74 
75   // True if we are in --whole-archive and --no-whole-archive.
76   bool inWholeArchive = false;
77 
78   std::vector<InputFile *> files;
79 };
80 } // anonymous namespace
81 
82 bool lld::wasm::link(ArrayRef<const char *> args, bool canExitEarly,
83                      raw_ostream &error) {
84   errorHandler().logName = args::getFilenameWithoutExe(args[0]);
85   errorHandler().errorOS = &error;
86   errorHandler().errorLimitExceededMsg =
87       "too many errors emitted, stopping now (use "
88       "-error-limit=0 to see all errors)";
89   enableColors(error.has_colors());
90 
91   config = make<Configuration>();
92   symtab = make<SymbolTable>();
93 
94   initLLVM();
95   LinkerDriver().link(args);
96 
97   // Exit immediately if we don't need to return to the caller.
98   // This saves time because the overhead of calling destructors
99   // for all globally-allocated objects is not negligible.
100   if (canExitEarly)
101     exitLld(errorCount() ? 1 : 0);
102 
103   freeArena();
104   return !errorCount();
105 }
106 
107 // Create prefix string literals used in Options.td
108 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
109 #include "Options.inc"
110 #undef PREFIX
111 
112 // Create table mapping all options defined in Options.td
113 static const opt::OptTable::Info optInfo[] = {
114 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
115   {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
116    X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
117 #include "Options.inc"
118 #undef OPTION
119 };
120 
121 namespace {
122 class WasmOptTable : public llvm::opt::OptTable {
123 public:
124   WasmOptTable() : OptTable(optInfo) {}
125   opt::InputArgList parse(ArrayRef<const char *> argv);
126 };
127 } // namespace
128 
129 // Set color diagnostics according to -color-diagnostics={auto,always,never}
130 // or -no-color-diagnostics flags.
131 static void handleColorDiagnostics(opt::InputArgList &args) {
132   auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
133                               OPT_no_color_diagnostics);
134   if (!arg)
135     return;
136   if (arg->getOption().getID() == OPT_color_diagnostics) {
137     enableColors(true);
138   } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
139     enableColors(false);
140   } else {
141     StringRef s = arg->getValue();
142     if (s == "always")
143       enableColors(true);
144     else if (s == "never")
145       enableColors(false);
146     else if (s != "auto")
147       error("unknown option: --color-diagnostics=" + s);
148   }
149 }
150 
151 // Find a file by concatenating given paths.
152 static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
153   SmallString<128> s;
154   path::append(s, path1, path2);
155   if (fs::exists(s))
156     return s.str().str();
157   return None;
158 }
159 
160 opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) {
161   SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
162 
163   unsigned missingIndex;
164   unsigned missingCount;
165 
166   // Expand response files (arguments in the form of @<filename>)
167   cl::ExpandResponseFiles(saver, cl::TokenizeGNUCommandLine, vec);
168 
169   opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
170 
171   handleColorDiagnostics(args);
172   for (auto *arg : args.filtered(OPT_UNKNOWN))
173     error("unknown argument: " + arg->getAsString(args));
174   return args;
175 }
176 
177 // Currently we allow a ".imports" to live alongside a library. This can
178 // be used to specify a list of symbols which can be undefined at link
179 // time (imported from the environment.  For example libc.a include an
180 // import file that lists the syscall functions it relies on at runtime.
181 // In the long run this information would be better stored as a symbol
182 // attribute/flag in the object file itself.
183 // See: https://github.com/WebAssembly/tool-conventions/issues/35
184 static void readImportFile(StringRef filename) {
185   if (Optional<MemoryBufferRef> buf = readFile(filename))
186     for (StringRef sym : args::getLines(*buf))
187       config->allowUndefinedSymbols.insert(sym);
188 }
189 
190 // Returns slices of MB by parsing MB as an archive file.
191 // Each slice consists of a member file in the archive.
192 std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef mb) {
193   std::unique_ptr<Archive> file =
194       CHECK(Archive::create(mb),
195             mb.getBufferIdentifier() + ": failed to parse archive");
196 
197   std::vector<MemoryBufferRef> v;
198   Error err = Error::success();
199   for (const ErrorOr<Archive::Child> &cOrErr : file->children(err)) {
200     Archive::Child c =
201         CHECK(cOrErr, mb.getBufferIdentifier() +
202                           ": could not get the child of the archive");
203     MemoryBufferRef mbref =
204         CHECK(c.getMemoryBufferRef(),
205               mb.getBufferIdentifier() +
206                   ": could not get the buffer for a child of the archive");
207     v.push_back(mbref);
208   }
209   if (err)
210     fatal(mb.getBufferIdentifier() +
211           ": Archive::children failed: " + toString(std::move(err)));
212 
213   // Take ownership of memory buffers created for members of thin archives.
214   for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
215     make<std::unique_ptr<MemoryBuffer>>(std::move(mb));
216 
217   return v;
218 }
219 
220 void LinkerDriver::addFile(StringRef path) {
221   Optional<MemoryBufferRef> buffer = readFile(path);
222   if (!buffer.hasValue())
223     return;
224   MemoryBufferRef mbref = *buffer;
225 
226   switch (identify_magic(mbref.getBuffer())) {
227   case file_magic::archive: {
228     SmallString<128> importFile = path;
229     path::replace_extension(importFile, ".imports");
230     if (fs::exists(importFile))
231       readImportFile(importFile.str());
232 
233     // Handle -whole-archive.
234     if (inWholeArchive) {
235       for (MemoryBufferRef &m : getArchiveMembers(mbref))
236         files.push_back(createObjectFile(m, path));
237       return;
238     }
239 
240     std::unique_ptr<Archive> file =
241         CHECK(Archive::create(mbref), path + ": failed to parse archive");
242 
243     if (!file->isEmpty() && !file->hasSymbolTable()) {
244       error(mbref.getBufferIdentifier() +
245             ": archive has no index; run ranlib to add one");
246     }
247 
248     files.push_back(make<ArchiveFile>(mbref));
249     return;
250   }
251   case file_magic::bitcode:
252   case file_magic::wasm_object:
253     files.push_back(createObjectFile(mbref));
254     break;
255   default:
256     error("unknown file type: " + mbref.getBufferIdentifier());
257   }
258 }
259 
260 // Add a given library by searching it from input search paths.
261 void LinkerDriver::addLibrary(StringRef name) {
262   for (StringRef dir : config->searchPaths) {
263     if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) {
264       addFile(*s);
265       return;
266     }
267   }
268 
269   error("unable to find library -l" + name);
270 }
271 
272 void LinkerDriver::createFiles(opt::InputArgList &args) {
273   for (auto *arg : args) {
274     switch (arg->getOption().getID()) {
275     case OPT_l:
276       addLibrary(arg->getValue());
277       break;
278     case OPT_INPUT:
279       addFile(arg->getValue());
280       break;
281     case OPT_whole_archive:
282       inWholeArchive = true;
283       break;
284     case OPT_no_whole_archive:
285       inWholeArchive = false;
286       break;
287     }
288   }
289 }
290 
291 static StringRef getEntry(opt::InputArgList &args) {
292   auto *arg = args.getLastArg(OPT_entry, OPT_no_entry);
293   if (!arg) {
294     if (args.hasArg(OPT_relocatable))
295       return "";
296     if (args.hasArg(OPT_shared))
297       return "__wasm_call_ctors";
298     return "_start";
299   }
300   if (arg->getOption().getID() == OPT_no_entry)
301     return "";
302   return arg->getValue();
303 }
304 
305 // Initializes Config members by the command line options.
306 static void readConfigs(opt::InputArgList &args) {
307   config->allowUndefined = args.hasArg(OPT_allow_undefined);
308   config->checkFeatures =
309       args.hasFlag(OPT_check_features, OPT_no_check_features, true);
310   config->compressRelocations = args.hasArg(OPT_compress_relocations);
311   config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
312   config->disableVerify = args.hasArg(OPT_disable_verify);
313   config->emitRelocs = args.hasArg(OPT_emit_relocs);
314   config->entry = getEntry(args);
315   config->exportAll = args.hasArg(OPT_export_all);
316   config->exportTable = args.hasArg(OPT_export_table);
317   config->growableTable = args.hasArg(OPT_growable_table);
318   errorHandler().fatalWarnings =
319       args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
320   config->importMemory = args.hasArg(OPT_import_memory);
321   config->sharedMemory = args.hasArg(OPT_shared_memory);
322   config->importTable = args.hasArg(OPT_import_table);
323   config->ltoo = args::getInteger(args, OPT_lto_O, 2);
324   config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
325   config->optimize = args::getInteger(args, OPT_O, 0);
326   config->outputFile = args.getLastArgValue(OPT_o);
327   config->relocatable = args.hasArg(OPT_relocatable);
328   config->gcSections =
329       args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable);
330   config->mergeDataSegments =
331       args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
332                    !config->relocatable);
333   config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
334   config->printGcSections =
335       args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
336   config->saveTemps = args.hasArg(OPT_save_temps);
337   config->searchPaths = args::getStrings(args, OPT_L);
338   config->shared = args.hasArg(OPT_shared);
339   config->stripAll = args.hasArg(OPT_strip_all);
340   config->stripDebug = args.hasArg(OPT_strip_debug);
341   config->stackFirst = args.hasArg(OPT_stack_first);
342   config->trace = args.hasArg(OPT_trace);
343   config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
344   config->thinLTOCachePolicy = CHECK(
345       parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
346       "--thinlto-cache-policy: invalid cache policy");
347   config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u);
348   errorHandler().verbose = args.hasArg(OPT_verbose);
349   LLVM_DEBUG(errorHandler().verbose = true);
350   threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true);
351 
352   config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
353   config->globalBase = args::getInteger(args, OPT_global_base, 1024);
354   config->maxMemory = args::getInteger(args, OPT_max_memory, 0);
355   config->zStackSize =
356       args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize);
357 
358   // Default value of exportDynamic depends on `-shared`
359   config->exportDynamic =
360       args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared);
361 
362   if (auto *arg = args.getLastArg(OPT_features)) {
363     config->features =
364         llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
365     for (StringRef s : arg->getValues())
366       config->features->push_back(s);
367   }
368 }
369 
370 // Some Config members do not directly correspond to any particular
371 // command line options, but computed based on other Config values.
372 // This function initialize such members. See Config.h for the details
373 // of these values.
374 static void setConfigs() {
375   config->isPic = config->pie || config->shared;
376 
377   if (config->isPic) {
378     if (config->exportTable)
379       error("-shared/-pie is incompatible with --export-table");
380     config->importTable = true;
381   }
382 
383   if (config->shared) {
384     config->importMemory = true;
385     config->allowUndefined = true;
386   }
387 }
388 
389 // Some command line options or some combinations of them are not allowed.
390 // This function checks for such errors.
391 static void checkOptions(opt::InputArgList &args) {
392   if (!config->stripDebug && !config->stripAll && config->compressRelocations)
393     error("--compress-relocations is incompatible with output debug"
394           " information. Please pass --strip-debug or --strip-all");
395 
396   if (config->ltoo > 3)
397     error("invalid optimization level for LTO: " + Twine(config->ltoo));
398   if (config->ltoPartitions == 0)
399     error("--lto-partitions: number of threads must be > 0");
400   if (config->thinLTOJobs == 0)
401     error("--thinlto-jobs: number of threads must be > 0");
402 
403   if (config->pie && config->shared)
404     error("-shared and -pie may not be used together");
405 
406   if (config->outputFile.empty())
407     error("no output file specified");
408 
409   if (config->importTable && config->exportTable)
410     error("--import-table and --export-table may not be used together");
411 
412   if (config->relocatable) {
413     if (!config->entry.empty())
414       error("entry point specified for relocatable output file");
415     if (config->gcSections)
416       error("-r and --gc-sections may not be used together");
417     if (config->compressRelocations)
418       error("-r -and --compress-relocations may not be used together");
419     if (args.hasArg(OPT_undefined))
420       error("-r -and --undefined may not be used together");
421     if (config->pie)
422       error("-r and -pie may not be used together");
423   }
424 }
425 
426 // Force Sym to be entered in the output. Used for -u or equivalent.
427 static Symbol *handleUndefined(StringRef name) {
428   Symbol *sym = symtab->find(name);
429   if (!sym)
430     return nullptr;
431 
432   // Since symbol S may not be used inside the program, LTO may
433   // eliminate it. Mark the symbol as "used" to prevent it.
434   sym->isUsedInRegularObj = true;
435 
436   if (auto *lazySym = dyn_cast<LazySymbol>(sym))
437     lazySym->fetch();
438 
439   return sym;
440 }
441 
442 static UndefinedGlobal *
443 createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
444   auto *sym =
445       cast<UndefinedGlobal>(symtab->addUndefinedGlobal(name, name,
446                                                        defaultModule, 0,
447                                                        nullptr, type));
448   config->allowUndefinedSymbols.insert(sym->getName());
449   sym->isUsedInRegularObj = true;
450   return sym;
451 }
452 
453 static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable,
454                                           int value) {
455   llvm::wasm::WasmGlobal wasmGlobal;
456   wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
457   wasmGlobal.InitExpr.Value.Int32 = value;
458   wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
459   wasmGlobal.SymbolName = name;
460   return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN,
461                                     make<InputGlobal>(wasmGlobal, nullptr));
462 }
463 
464 // Create ABI-defined synthetic symbols
465 static void createSyntheticSymbols() {
466   if (config->relocatable)
467     return;
468 
469   static WasmSignature nullSignature = {{}, {}};
470   static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
471   static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
472   static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
473                                                             true};
474   WasmSym::callCtors = symtab->addSyntheticFunction(
475       "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
476       make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
477 
478   if (config->isPic) {
479     // For PIC code we create a synthetic function __wasm_apply_relocs which
480     // is called from __wasm_call_ctors before the user-level constructors.
481     WasmSym::applyRelocs = symtab->addSyntheticFunction(
482         "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
483         make<SyntheticFunction>(nullSignature, "__wasm_apply_relocs"));
484   }
485 
486 
487   if (config->isPic) {
488     WasmSym::stackPointer =
489         createUndefinedGlobal("__stack_pointer", &mutableGlobalTypeI32);
490     // For PIC code, we import two global variables (__memory_base and
491     // __table_base) from the environment and use these as the offset at
492     // which to load our static data and function table.
493     // See:
494     // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
495     WasmSym::memoryBase =
496         createUndefinedGlobal("__memory_base", &globalTypeI32);
497     WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32);
498     WasmSym::memoryBase->markLive();
499     WasmSym::tableBase->markLive();
500   } else {
501     // For non-PIC code
502     WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true, 0);
503     WasmSym::stackPointer->markLive();
504   }
505 
506   if (config->sharedMemory && !config->shared) {
507     // Passive segments are used to avoid memory being reinitialized on each
508     // thread's instantiation. These passive segments are initialized and
509     // dropped in __wasm_init_memory, which is registered as the start function
510     WasmSym::initMemory = symtab->addSyntheticFunction(
511         "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
512         make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
513     WasmSym::initMemoryFlag = symtab->addSyntheticDataSymbol(
514         "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN);
515     assert(WasmSym::initMemoryFlag);
516     WasmSym::tlsBase = createGlobalVariable("__tls_base", true, 0);
517     WasmSym::tlsSize = createGlobalVariable("__tls_size", false, 0);
518     WasmSym::tlsAlign = createGlobalVariable("__tls_align", false, 1);
519     WasmSym::initTLS = symtab->addSyntheticFunction(
520         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
521         make<SyntheticFunction>(i32ArgSignature, "__wasm_init_tls"));
522   }
523 }
524 
525 static void createOptionalSymbols() {
526   if (config->relocatable)
527     return;
528 
529   WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
530 
531   if (!config->shared)
532     WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
533 
534   if (!config->isPic) {
535     WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
536     WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
537     WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
538     WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base");
539   }
540 }
541 
542 // Reconstructs command line arguments so that so that you can re-run
543 // the same command with the same inputs. This is for --reproduce.
544 static std::string createResponseFile(const opt::InputArgList &args) {
545   SmallString<0> data;
546   raw_svector_ostream os(data);
547 
548   // Copy the command line to the output while rewriting paths.
549   for (auto *arg : args) {
550     switch (arg->getOption().getID()) {
551     case OPT_reproduce:
552       break;
553     case OPT_INPUT:
554       os << quote(relativeToRoot(arg->getValue())) << "\n";
555       break;
556     case OPT_o:
557       // If -o path contains directories, "lld @response.txt" will likely
558       // fail because the archive we are creating doesn't contain empty
559       // directories for the output path (-o doesn't create directories).
560       // Strip directories to prevent the issue.
561       os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
562       break;
563     default:
564       os << toString(*arg) << "\n";
565     }
566   }
567   return data.str();
568 }
569 
570 // The --wrap option is a feature to rename symbols so that you can write
571 // wrappers for existing functions. If you pass `-wrap=foo`, all
572 // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
573 // expected to write `wrap_foo` function as a wrapper). The original
574 // symbol becomes accessible as `real_foo`, so you can call that from your
575 // wrapper.
576 //
577 // This data structure is instantiated for each -wrap option.
578 struct WrappedSymbol {
579   Symbol *sym;
580   Symbol *real;
581   Symbol *wrap;
582 };
583 
584 static Symbol *addUndefined(StringRef name) {
585   return symtab->addUndefinedFunction(name, "", "", 0, nullptr, nullptr, false);
586 }
587 
588 // Handles -wrap option.
589 //
590 // This function instantiates wrapper symbols. At this point, they seem
591 // like they are not being used at all, so we explicitly set some flags so
592 // that LTO won't eliminate them.
593 static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
594   std::vector<WrappedSymbol> v;
595   DenseSet<StringRef> seen;
596 
597   for (auto *arg : args.filtered(OPT_wrap)) {
598     StringRef name = arg->getValue();
599     if (!seen.insert(name).second)
600       continue;
601 
602     Symbol *sym = symtab->find(name);
603     if (!sym)
604       continue;
605 
606     Symbol *real = addUndefined(saver.save("__real_" + name));
607     Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
608     v.push_back({sym, real, wrap});
609 
610     // We want to tell LTO not to inline symbols to be overwritten
611     // because LTO doesn't know the final symbol contents after renaming.
612     real->canInline = false;
613     sym->canInline = false;
614 
615     // Tell LTO not to eliminate these symbols.
616     sym->isUsedInRegularObj = true;
617     wrap->isUsedInRegularObj = true;
618     real->isUsedInRegularObj = false;
619   }
620   return v;
621 }
622 
623 // Do renaming for -wrap by updating pointers to symbols.
624 //
625 // When this function is executed, only InputFiles and symbol table
626 // contain pointers to symbol objects. We visit them to replace pointers,
627 // so that wrapped symbols are swapped as instructed by the command line.
628 static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
629   DenseMap<Symbol *, Symbol *> map;
630   for (const WrappedSymbol &w : wrapped) {
631     map[w.sym] = w.wrap;
632     map[w.real] = w.sym;
633   }
634 
635   // Update pointers in input files.
636   parallelForEach(symtab->objectFiles, [&](InputFile *file) {
637     MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
638     for (size_t i = 0, e = syms.size(); i != e; ++i)
639       if (Symbol *s = map.lookup(syms[i]))
640         syms[i] = s;
641   });
642 
643   // Update pointers in the symbol table.
644   for (const WrappedSymbol &w : wrapped)
645     symtab->wrap(w.sym, w.real, w.wrap);
646 }
647 
648 void LinkerDriver::link(ArrayRef<const char *> argsArr) {
649   WasmOptTable parser;
650   opt::InputArgList args = parser.parse(argsArr.slice(1));
651 
652   // Handle --help
653   if (args.hasArg(OPT_help)) {
654     parser.PrintHelp(outs(),
655                      (std::string(argsArr[0]) + " [options] file...").c_str(),
656                      "LLVM Linker", false);
657     return;
658   }
659 
660   // Handle --version
661   if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) {
662     outs() << getLLDVersion() << "\n";
663     return;
664   }
665 
666   // Handle --reproduce
667   if (auto *arg = args.getLastArg(OPT_reproduce)) {
668     StringRef path = arg->getValue();
669     Expected<std::unique_ptr<TarWriter>> errOrWriter =
670         TarWriter::create(path, path::stem(path));
671     if (errOrWriter) {
672       tar = std::move(*errOrWriter);
673       tar->append("response.txt", createResponseFile(args));
674       tar->append("version.txt", getLLDVersion() + "\n");
675     } else {
676       error("--reproduce: " + toString(errOrWriter.takeError()));
677     }
678   }
679 
680   // Parse and evaluate -mllvm options.
681   std::vector<const char *> v;
682   v.push_back("wasm-ld (LLVM option parsing)");
683   for (auto *arg : args.filtered(OPT_mllvm))
684     v.push_back(arg->getValue());
685   cl::ParseCommandLineOptions(v.size(), v.data());
686 
687   errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
688 
689   readConfigs(args);
690   setConfigs();
691   checkOptions(args);
692 
693   if (auto *arg = args.getLastArg(OPT_allow_undefined_file))
694     readImportFile(arg->getValue());
695 
696   if (!args.hasArg(OPT_INPUT)) {
697     error("no input files");
698     return;
699   }
700 
701   // Handle --trace-symbol.
702   for (auto *arg : args.filtered(OPT_trace_symbol))
703     symtab->trace(arg->getValue());
704 
705   for (auto *arg : args.filtered(OPT_export))
706     config->exportedSymbols.insert(arg->getValue());
707 
708   createSyntheticSymbols();
709 
710   createFiles(args);
711   if (errorCount())
712     return;
713 
714   // Add all files to the symbol table. This will add almost all
715   // symbols that we need to the symbol table.
716   for (InputFile *f : files)
717     symtab->addFile(f);
718   if (errorCount())
719     return;
720 
721   // Handle the `--undefined <sym>` options.
722   for (auto *arg : args.filtered(OPT_undefined))
723     handleUndefined(arg->getValue());
724 
725   // Handle the `--export <sym>` options
726   // This works like --undefined but also exports the symbol if its found
727   for (auto *arg : args.filtered(OPT_export))
728     handleUndefined(arg->getValue());
729 
730   Symbol *entrySym = nullptr;
731   if (!config->relocatable && !config->entry.empty()) {
732     entrySym = handleUndefined(config->entry);
733     if (entrySym && entrySym->isDefined())
734       entrySym->forceExport = true;
735     else
736       error("entry symbol not defined (pass --no-entry to supress): " +
737             config->entry);
738   }
739 
740   createOptionalSymbols();
741 
742   if (errorCount())
743     return;
744 
745   // Create wrapped symbols for -wrap option.
746   std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
747 
748   // Do link-time optimization if given files are LLVM bitcode files.
749   // This compiles bitcode files into real object files.
750   symtab->addCombinedLTOObject();
751   if (errorCount())
752     return;
753 
754   // Resolve any variant symbols that were created due to signature
755   // mismatchs.
756   symtab->handleSymbolVariants();
757   if (errorCount())
758     return;
759 
760   // Apply symbol renames for -wrap.
761   if (!wrapped.empty())
762     wrapSymbols(wrapped);
763 
764   for (auto *arg : args.filtered(OPT_export)) {
765     Symbol *sym = symtab->find(arg->getValue());
766     if (sym && sym->isDefined())
767       sym->forceExport = true;
768     else if (!config->allowUndefined)
769       error(Twine("symbol exported via --export not found: ") +
770             arg->getValue());
771   }
772 
773   if (!config->relocatable) {
774     // Add synthetic dummies for weak undefined functions.  Must happen
775     // after LTO otherwise functions may not yet have signatures.
776     symtab->handleWeakUndefines();
777   }
778 
779   if (entrySym)
780     entrySym->setHidden(false);
781 
782   if (errorCount())
783     return;
784 
785   // Do size optimizations: garbage collection
786   markLive();
787 
788   // Write the result to the file.
789   writeResult();
790 }
791