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