xref: /llvm-project-15.0.7/lld/wasm/Driver.cpp (revision f97936fa)
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 &stdoutOS,
82           raw_ostream &stderrOS) {
83   lld::stdoutOS = &stdoutOS;
84   lld::stderrOS = &stderrOS;
85 
86   errorHandler().logName = args::getFilenameWithoutExe(args[0]);
87   errorHandler().errorLimitExceededMsg =
88       "too many errors emitted, stopping now (use "
89       "-error-limit=0 to see all errors)";
90   stderrOS.enable_colors(stderrOS.has_colors());
91 
92   config = make<Configuration>();
93   symtab = make<SymbolTable>();
94 
95   initLLVM();
96   LinkerDriver().link(args);
97 
98   // Exit immediately if we don't need to return to the caller.
99   // This saves time because the overhead of calling destructors
100   // for all globally-allocated objects is not negligible.
101   if (canExitEarly)
102     exitLld(errorCount() ? 1 : 0);
103 
104   freeArena();
105   return !errorCount();
106 }
107 
108 // Create prefix string literals used in Options.td
109 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
110 #include "Options.inc"
111 #undef PREFIX
112 
113 // Create table mapping all options defined in Options.td
114 static const 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 llvm::opt::OptTable {
124 public:
125   WasmOptTable() : OptTable(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 // Find a file by concatenating given paths.
153 static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
154   SmallString<128> s;
155   path::append(s, path1, path2);
156   if (fs::exists(s))
157     return s.str().str();
158   return None;
159 }
160 
161 opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) {
162   SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
163 
164   unsigned missingIndex;
165   unsigned missingCount;
166 
167   // Expand response files (arguments in the form of @<filename>)
168   cl::ExpandResponseFiles(saver, cl::TokenizeGNUCommandLine, vec);
169 
170   opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
171 
172   handleColorDiagnostics(args);
173   for (auto *arg : args.filtered(OPT_UNKNOWN))
174     error("unknown argument: " + arg->getAsString(args));
175   return args;
176 }
177 
178 // Currently we allow a ".imports" to live alongside a library. This can
179 // be used to specify a list of symbols which can be undefined at link
180 // time (imported from the environment.  For example libc.a include an
181 // import file that lists the syscall functions it relies on at runtime.
182 // In the long run this information would be better stored as a symbol
183 // attribute/flag in the object file itself.
184 // See: https://github.com/WebAssembly/tool-conventions/issues/35
185 static void readImportFile(StringRef filename) {
186   if (Optional<MemoryBufferRef> buf = readFile(filename))
187     for (StringRef sym : args::getLines(*buf))
188       config->allowUndefinedSymbols.insert(sym);
189 }
190 
191 // Returns slices of MB by parsing MB as an archive file.
192 // Each slice consists of a member file in the archive.
193 std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef mb) {
194   std::unique_ptr<Archive> file =
195       CHECK(Archive::create(mb),
196             mb.getBufferIdentifier() + ": failed to parse archive");
197 
198   std::vector<MemoryBufferRef> v;
199   Error err = Error::success();
200   for (const ErrorOr<Archive::Child> &cOrErr : file->children(err)) {
201     Archive::Child c =
202         CHECK(cOrErr, mb.getBufferIdentifier() +
203                           ": could not get the child of the archive");
204     MemoryBufferRef mbref =
205         CHECK(c.getMemoryBufferRef(),
206               mb.getBufferIdentifier() +
207                   ": could not get the buffer for a child of the archive");
208     v.push_back(mbref);
209   }
210   if (err)
211     fatal(mb.getBufferIdentifier() +
212           ": Archive::children failed: " + toString(std::move(err)));
213 
214   // Take ownership of memory buffers created for members of thin archives.
215   for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
216     make<std::unique_ptr<MemoryBuffer>>(std::move(mb));
217 
218   return v;
219 }
220 
221 void LinkerDriver::addFile(StringRef path) {
222   Optional<MemoryBufferRef> buffer = readFile(path);
223   if (!buffer.hasValue())
224     return;
225   MemoryBufferRef mbref = *buffer;
226 
227   switch (identify_magic(mbref.getBuffer())) {
228   case file_magic::archive: {
229     SmallString<128> importFile = path;
230     path::replace_extension(importFile, ".imports");
231     if (fs::exists(importFile))
232       readImportFile(importFile.str());
233 
234     // Handle -whole-archive.
235     if (inWholeArchive) {
236       for (MemoryBufferRef &m : getArchiveMembers(mbref))
237         files.push_back(createObjectFile(m, path));
238       return;
239     }
240 
241     std::unique_ptr<Archive> file =
242         CHECK(Archive::create(mbref), path + ": failed to parse archive");
243 
244     if (!file->isEmpty() && !file->hasSymbolTable()) {
245       error(mbref.getBufferIdentifier() +
246             ": archive has no index; run ranlib to add one");
247     }
248 
249     files.push_back(make<ArchiveFile>(mbref));
250     return;
251   }
252   case file_magic::bitcode:
253   case file_magic::wasm_object:
254     files.push_back(createObjectFile(mbref));
255     break;
256   default:
257     error("unknown file type: " + mbref.getBufferIdentifier());
258   }
259 }
260 
261 // Add a given library by searching it from input search paths.
262 void LinkerDriver::addLibrary(StringRef name) {
263   for (StringRef dir : config->searchPaths) {
264     if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) {
265       addFile(*s);
266       return;
267     }
268   }
269 
270   error("unable to find library -l" + name);
271 }
272 
273 void LinkerDriver::createFiles(opt::InputArgList &args) {
274   for (auto *arg : args) {
275     switch (arg->getOption().getID()) {
276     case OPT_l:
277       addLibrary(arg->getValue());
278       break;
279     case OPT_INPUT:
280       addFile(arg->getValue());
281       break;
282     case OPT_whole_archive:
283       inWholeArchive = true;
284       break;
285     case OPT_no_whole_archive:
286       inWholeArchive = false;
287       break;
288     }
289   }
290 }
291 
292 static StringRef getEntry(opt::InputArgList &args) {
293   auto *arg = args.getLastArg(OPT_entry, OPT_no_entry);
294   if (!arg) {
295     if (args.hasArg(OPT_relocatable))
296       return "";
297     if (args.hasArg(OPT_shared))
298       return "__wasm_call_ctors";
299     return "_start";
300   }
301   if (arg->getOption().getID() == OPT_no_entry)
302     return "";
303   return arg->getValue();
304 }
305 
306 // Initializes Config members by the command line options.
307 static void readConfigs(opt::InputArgList &args) {
308   config->allowUndefined = args.hasArg(OPT_allow_undefined);
309   config->checkFeatures =
310       args.hasFlag(OPT_check_features, OPT_no_check_features, true);
311   config->compressRelocations = args.hasArg(OPT_compress_relocations);
312   config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
313   config->disableVerify = args.hasArg(OPT_disable_verify);
314   config->emitRelocs = args.hasArg(OPT_emit_relocs);
315   config->entry = getEntry(args);
316   config->exportAll = args.hasArg(OPT_export_all);
317   config->exportTable = args.hasArg(OPT_export_table);
318   config->growableTable = args.hasArg(OPT_growable_table);
319   errorHandler().fatalWarnings =
320       args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
321   config->importMemory = args.hasArg(OPT_import_memory);
322   config->sharedMemory = args.hasArg(OPT_shared_memory);
323   config->importTable = args.hasArg(OPT_import_table);
324   config->ltoo = args::getInteger(args, OPT_lto_O, 2);
325   config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
326   config->optimize = args::getInteger(args, OPT_O, 0);
327   config->outputFile = args.getLastArgValue(OPT_o);
328   config->relocatable = args.hasArg(OPT_relocatable);
329   config->gcSections =
330       args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable);
331   config->mergeDataSegments =
332       args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
333                    !config->relocatable);
334   config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
335   config->printGcSections =
336       args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
337   config->saveTemps = args.hasArg(OPT_save_temps);
338   config->searchPaths = args::getStrings(args, OPT_L);
339   config->shared = args.hasArg(OPT_shared);
340   config->stripAll = args.hasArg(OPT_strip_all);
341   config->stripDebug = args.hasArg(OPT_strip_debug);
342   config->stackFirst = args.hasArg(OPT_stack_first);
343   config->trace = args.hasArg(OPT_trace);
344   config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
345   config->thinLTOCachePolicy = CHECK(
346       parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
347       "--thinlto-cache-policy: invalid cache policy");
348   config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u);
349   errorHandler().verbose = args.hasArg(OPT_verbose);
350   LLVM_DEBUG(errorHandler().verbose = true);
351   threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true);
352 
353   config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
354   config->globalBase = args::getInteger(args, OPT_global_base, 1024);
355   config->maxMemory = args::getInteger(args, OPT_max_memory, 0);
356   config->zStackSize =
357       args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize);
358 
359   // Default value of exportDynamic depends on `-shared`
360   config->exportDynamic =
361       args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared);
362 
363   if (auto *arg = args.getLastArg(OPT_features)) {
364     config->features =
365         llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
366     for (StringRef s : arg->getValues())
367       config->features->push_back(s);
368   }
369 }
370 
371 // Some Config members do not directly correspond to any particular
372 // command line options, but computed based on other Config values.
373 // This function initialize such members. See Config.h for the details
374 // of these values.
375 static void setConfigs() {
376   config->isPic = config->pie || config->shared;
377 
378   if (config->isPic) {
379     if (config->exportTable)
380       error("-shared/-pie is incompatible with --export-table");
381     config->importTable = true;
382   }
383 
384   if (config->shared) {
385     config->importMemory = true;
386     config->allowUndefined = true;
387   }
388 }
389 
390 // Some command line options or some combinations of them are not allowed.
391 // This function checks for such errors.
392 static void checkOptions(opt::InputArgList &args) {
393   if (!config->stripDebug && !config->stripAll && config->compressRelocations)
394     error("--compress-relocations is incompatible with output debug"
395           " information. Please pass --strip-debug or --strip-all");
396 
397   if (config->ltoo > 3)
398     error("invalid optimization level for LTO: " + Twine(config->ltoo));
399   if (config->ltoPartitions == 0)
400     error("--lto-partitions: number of threads must be > 0");
401   if (config->thinLTOJobs == 0)
402     error("--thinlto-jobs: number of threads must be > 0");
403 
404   if (config->pie && config->shared)
405     error("-shared and -pie may not be used together");
406 
407   if (config->outputFile.empty())
408     error("no output file specified");
409 
410   if (config->importTable && config->exportTable)
411     error("--import-table and --export-table may not be used together");
412 
413   if (config->relocatable) {
414     if (!config->entry.empty())
415       error("entry point specified for relocatable output file");
416     if (config->gcSections)
417       error("-r and --gc-sections may not be used together");
418     if (config->compressRelocations)
419       error("-r -and --compress-relocations may not be used together");
420     if (args.hasArg(OPT_undefined))
421       error("-r -and --undefined may not be used together");
422     if (config->pie)
423       error("-r and -pie may not be used together");
424   }
425 }
426 
427 // Force Sym to be entered in the output. Used for -u or equivalent.
428 static Symbol *handleUndefined(StringRef name) {
429   Symbol *sym = symtab->find(name);
430   if (!sym)
431     return nullptr;
432 
433   // Since symbol S may not be used inside the program, LTO may
434   // eliminate it. Mark the symbol as "used" to prevent it.
435   sym->isUsedInRegularObj = true;
436 
437   if (auto *lazySym = dyn_cast<LazySymbol>(sym))
438     lazySym->fetch();
439 
440   return sym;
441 }
442 
443 static UndefinedGlobal *
444 createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
445   auto *sym = cast<UndefinedGlobal>(symtab->addUndefinedGlobal(
446       name, name, defaultModule, WASM_SYMBOL_UNDEFINED, nullptr, type));
447   config->allowUndefinedSymbols.insert(sym->getName());
448   sym->isUsedInRegularObj = true;
449   return sym;
450 }
451 
452 static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable,
453                                           int value) {
454   llvm::wasm::WasmGlobal wasmGlobal;
455   wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
456   wasmGlobal.InitExpr.Value.Int32 = value;
457   wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
458   wasmGlobal.SymbolName = name;
459   return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN,
460                                     make<InputGlobal>(wasmGlobal, nullptr));
461 }
462 
463 // Create ABI-defined synthetic symbols
464 static void createSyntheticSymbols() {
465   if (config->relocatable)
466     return;
467 
468   static WasmSignature nullSignature = {{}, {}};
469   static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
470   static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
471   static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
472                                                             true};
473   WasmSym::callCtors = symtab->addSyntheticFunction(
474       "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
475       make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
476 
477   if (config->isPic) {
478     // For PIC code we create a synthetic function __wasm_apply_relocs which
479     // is called from __wasm_call_ctors before the user-level constructors.
480     WasmSym::applyRelocs = symtab->addSyntheticFunction(
481         "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
482         make<SyntheticFunction>(nullSignature, "__wasm_apply_relocs"));
483   }
484 
485 
486   if (config->isPic) {
487     WasmSym::stackPointer =
488         createUndefinedGlobal("__stack_pointer", &mutableGlobalTypeI32);
489     // For PIC code, we import two global variables (__memory_base and
490     // __table_base) from the environment and use these as the offset at
491     // which to load our static data and function table.
492     // See:
493     // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
494     WasmSym::memoryBase =
495         createUndefinedGlobal("__memory_base", &globalTypeI32);
496     WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32);
497     WasmSym::memoryBase->markLive();
498     WasmSym::tableBase->markLive();
499   } else {
500     // For non-PIC code
501     WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true, 0);
502     WasmSym::stackPointer->markLive();
503   }
504 
505   if (config->sharedMemory && !config->shared) {
506     // Passive segments are used to avoid memory being reinitialized on each
507     // thread's instantiation. These passive segments are initialized and
508     // dropped in __wasm_init_memory, which is registered as the start function
509     WasmSym::initMemory = symtab->addSyntheticFunction(
510         "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
511         make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
512     WasmSym::initMemoryFlag = symtab->addSyntheticDataSymbol(
513         "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN);
514     assert(WasmSym::initMemoryFlag);
515     WasmSym::tlsBase = createGlobalVariable("__tls_base", true, 0);
516     WasmSym::tlsSize = createGlobalVariable("__tls_size", false, 0);
517     WasmSym::tlsAlign = createGlobalVariable("__tls_align", false, 1);
518     WasmSym::initTLS = symtab->addSyntheticFunction(
519         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
520         make<SyntheticFunction>(i32ArgSignature, "__wasm_init_tls"));
521   }
522 }
523 
524 static void createOptionalSymbols() {
525   if (config->relocatable)
526     return;
527 
528   WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
529 
530   if (!config->shared)
531     WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
532 
533   if (!config->isPic) {
534     WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
535     WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
536     WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
537     WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base");
538   }
539 }
540 
541 // Reconstructs command line arguments so that so that you can re-run
542 // the same command with the same inputs. This is for --reproduce.
543 static std::string createResponseFile(const opt::InputArgList &args) {
544   SmallString<0> data;
545   raw_svector_ostream os(data);
546 
547   // Copy the command line to the output while rewriting paths.
548   for (auto *arg : args) {
549     switch (arg->getOption().getID()) {
550     case OPT_reproduce:
551       break;
552     case OPT_INPUT:
553       os << quote(relativeToRoot(arg->getValue())) << "\n";
554       break;
555     case OPT_o:
556       // If -o path contains directories, "lld @response.txt" will likely
557       // fail because the archive we are creating doesn't contain empty
558       // directories for the output path (-o doesn't create directories).
559       // Strip directories to prevent the issue.
560       os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
561       break;
562     default:
563       os << toString(*arg) << "\n";
564     }
565   }
566   return data.str();
567 }
568 
569 // The --wrap option is a feature to rename symbols so that you can write
570 // wrappers for existing functions. If you pass `-wrap=foo`, all
571 // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
572 // expected to write `wrap_foo` function as a wrapper). The original
573 // symbol becomes accessible as `real_foo`, so you can call that from your
574 // wrapper.
575 //
576 // This data structure is instantiated for each -wrap option.
577 struct WrappedSymbol {
578   Symbol *sym;
579   Symbol *real;
580   Symbol *wrap;
581 };
582 
583 static Symbol *addUndefined(StringRef name) {
584   return symtab->addUndefinedFunction(name, "", "", WASM_SYMBOL_UNDEFINED,
585                                       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(lld::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     lld::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 
792 } // namespace wasm
793 } // namespace lld
794