xref: /llvm-project-15.0.7/lld/wasm/Driver.cpp (revision a2e270fa)
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   errorHandler().fatalWarnings =
318       args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
319   config->importMemory = args.hasArg(OPT_import_memory);
320   config->sharedMemory = args.hasArg(OPT_shared_memory);
321   config->passiveSegments = args.hasFlag(
322       OPT_passive_segments, OPT_active_segments, config->sharedMemory);
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 =
446       cast<UndefinedGlobal>(symtab->addUndefinedGlobal(name, name,
447                                                        defaultModule, 0,
448                                                        nullptr, type));
449   config->allowUndefinedSymbols.insert(sym->getName());
450   sym->isUsedInRegularObj = true;
451   return sym;
452 }
453 
454 static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable,
455                                           int value) {
456   llvm::wasm::WasmGlobal wasmGlobal;
457   wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
458   wasmGlobal.InitExpr.Value.Int32 = value;
459   wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
460   wasmGlobal.SymbolName = name;
461   return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN,
462                                     make<InputGlobal>(wasmGlobal, nullptr));
463 }
464 
465 // Create ABI-defined synthetic symbols
466 static void createSyntheticSymbols() {
467   if (config->relocatable)
468     return;
469 
470   static WasmSignature nullSignature = {{}, {}};
471   static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
472   static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
473   static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
474                                                             true};
475 
476   WasmSym::callCtors = symtab->addSyntheticFunction(
477       "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
478       make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
479 
480   if (config->passiveSegments) {
481     // Passive segments are used to avoid memory being reinitialized on each
482     // thread's instantiation. These passive segments are initialized and
483     // dropped in __wasm_init_memory, which is the first function called from
484     // __wasm_call_ctors.
485     WasmSym::initMemory = symtab->addSyntheticFunction(
486         "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
487         make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
488   }
489 
490   if (config->isPic) {
491     // For PIC code we create a synthetic function __wasm_apply_relocs which
492     // is called from __wasm_call_ctors before the user-level constructors.
493     WasmSym::applyRelocs = symtab->addSyntheticFunction(
494         "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
495         make<SyntheticFunction>(nullSignature, "__wasm_apply_relocs"));
496   }
497 
498 
499   if (config->isPic) {
500     WasmSym::stackPointer =
501         createUndefinedGlobal("__stack_pointer", &mutableGlobalTypeI32);
502     // For PIC code, we import two global variables (__memory_base and
503     // __table_base) from the environment and use these as the offset at
504     // which to load our static data and function table.
505     // See:
506     // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
507     WasmSym::memoryBase =
508         createUndefinedGlobal("__memory_base", &globalTypeI32);
509     WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32);
510     WasmSym::memoryBase->markLive();
511     WasmSym::tableBase->markLive();
512   } else {
513     // For non-PIC code
514     WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true, 0);
515     WasmSym::stackPointer->markLive();
516   }
517 
518   if (config->sharedMemory && !config->shared) {
519     WasmSym::tlsBase = createGlobalVariable("__tls_base", true, 0);
520     WasmSym::tlsSize = createGlobalVariable("__tls_size", false, 0);
521     WasmSym::tlsAlign = createGlobalVariable("__tls_align", false, 1);
522     WasmSym::initTLS = symtab->addSyntheticFunction(
523         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
524         make<SyntheticFunction>(i32ArgSignature, "__wasm_init_tls"));
525   }
526 }
527 
528 static void createOptionalSymbols() {
529   if (config->relocatable)
530     return;
531 
532   WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
533 
534   if (!config->shared)
535     WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
536 
537   if (!config->isPic) {
538     WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
539     WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
540     WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
541     WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base");
542   }
543 }
544 
545 // Reconstructs command line arguments so that so that you can re-run
546 // the same command with the same inputs. This is for --reproduce.
547 static std::string createResponseFile(const opt::InputArgList &args) {
548   SmallString<0> data;
549   raw_svector_ostream os(data);
550 
551   // Copy the command line to the output while rewriting paths.
552   for (auto *arg : args) {
553     switch (arg->getOption().getID()) {
554     case OPT_reproduce:
555       break;
556     case OPT_INPUT:
557       os << quote(relativeToRoot(arg->getValue())) << "\n";
558       break;
559     case OPT_o:
560       // If -o path contains directories, "lld @response.txt" will likely
561       // fail because the archive we are creating doesn't contain empty
562       // directories for the output path (-o doesn't create directories).
563       // Strip directories to prevent the issue.
564       os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
565       break;
566     default:
567       os << toString(*arg) << "\n";
568     }
569   }
570   return data.str();
571 }
572 
573 // The --wrap option is a feature to rename symbols so that you can write
574 // wrappers for existing functions. If you pass `-wrap=foo`, all
575 // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
576 // expected to write `wrap_foo` function as a wrapper). The original
577 // symbol becomes accessible as `real_foo`, so you can call that from your
578 // wrapper.
579 //
580 // This data structure is instantiated for each -wrap option.
581 struct WrappedSymbol {
582   Symbol *sym;
583   Symbol *real;
584   Symbol *wrap;
585 };
586 
587 static Symbol *addUndefined(StringRef name) {
588   return symtab->addUndefinedFunction(name, "", "", 0, nullptr, nullptr, false);
589 }
590 
591 // Handles -wrap option.
592 //
593 // This function instantiates wrapper symbols. At this point, they seem
594 // like they are not being used at all, so we explicitly set some flags so
595 // that LTO won't eliminate them.
596 static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
597   std::vector<WrappedSymbol> v;
598   DenseSet<StringRef> seen;
599 
600   for (auto *arg : args.filtered(OPT_wrap)) {
601     StringRef name = arg->getValue();
602     if (!seen.insert(name).second)
603       continue;
604 
605     Symbol *sym = symtab->find(name);
606     if (!sym)
607       continue;
608 
609     Symbol *real = addUndefined(saver.save("__real_" + name));
610     Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
611     v.push_back({sym, real, wrap});
612 
613     // We want to tell LTO not to inline symbols to be overwritten
614     // because LTO doesn't know the final symbol contents after renaming.
615     real->canInline = false;
616     sym->canInline = false;
617 
618     // Tell LTO not to eliminate these symbols.
619     sym->isUsedInRegularObj = true;
620     wrap->isUsedInRegularObj = true;
621     real->isUsedInRegularObj = false;
622   }
623   return v;
624 }
625 
626 // Do renaming for -wrap by updating pointers to symbols.
627 //
628 // When this function is executed, only InputFiles and symbol table
629 // contain pointers to symbol objects. We visit them to replace pointers,
630 // so that wrapped symbols are swapped as instructed by the command line.
631 static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
632   DenseMap<Symbol *, Symbol *> map;
633   for (const WrappedSymbol &w : wrapped) {
634     map[w.sym] = w.wrap;
635     map[w.real] = w.sym;
636   }
637 
638   // Update pointers in input files.
639   parallelForEach(symtab->objectFiles, [&](InputFile *file) {
640     MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
641     for (size_t i = 0, e = syms.size(); i != e; ++i)
642       if (Symbol *s = map.lookup(syms[i]))
643         syms[i] = s;
644   });
645 
646   // Update pointers in the symbol table.
647   for (const WrappedSymbol &w : wrapped)
648     symtab->wrap(w.sym, w.real, w.wrap);
649 }
650 
651 void LinkerDriver::link(ArrayRef<const char *> argsArr) {
652   WasmOptTable parser;
653   opt::InputArgList args = parser.parse(argsArr.slice(1));
654 
655   // Handle --help
656   if (args.hasArg(OPT_help)) {
657     parser.PrintHelp(outs(),
658                      (std::string(argsArr[0]) + " [options] file...").c_str(),
659                      "LLVM Linker", false);
660     return;
661   }
662 
663   // Handle --version
664   if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) {
665     outs() << getLLDVersion() << "\n";
666     return;
667   }
668 
669   // Handle --reproduce
670   if (auto *arg = args.getLastArg(OPT_reproduce)) {
671     StringRef path = arg->getValue();
672     Expected<std::unique_ptr<TarWriter>> errOrWriter =
673         TarWriter::create(path, path::stem(path));
674     if (errOrWriter) {
675       tar = std::move(*errOrWriter);
676       tar->append("response.txt", createResponseFile(args));
677       tar->append("version.txt", getLLDVersion() + "\n");
678     } else {
679       error("--reproduce: " + toString(errOrWriter.takeError()));
680     }
681   }
682 
683   // Parse and evaluate -mllvm options.
684   std::vector<const char *> v;
685   v.push_back("wasm-ld (LLVM option parsing)");
686   for (auto *arg : args.filtered(OPT_mllvm))
687     v.push_back(arg->getValue());
688   cl::ParseCommandLineOptions(v.size(), v.data());
689 
690   errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
691 
692   readConfigs(args);
693   setConfigs();
694   checkOptions(args);
695 
696   if (auto *arg = args.getLastArg(OPT_allow_undefined_file))
697     readImportFile(arg->getValue());
698 
699   if (!args.hasArg(OPT_INPUT)) {
700     error("no input files");
701     return;
702   }
703 
704   // Handle --trace-symbol.
705   for (auto *arg : args.filtered(OPT_trace_symbol))
706     symtab->trace(arg->getValue());
707 
708   for (auto *arg : args.filtered(OPT_export))
709     config->exportedSymbols.insert(arg->getValue());
710 
711   createSyntheticSymbols();
712 
713   createFiles(args);
714   if (errorCount())
715     return;
716 
717   // Add all files to the symbol table. This will add almost all
718   // symbols that we need to the symbol table.
719   for (InputFile *f : files)
720     symtab->addFile(f);
721   if (errorCount())
722     return;
723 
724   createOptionalSymbols();
725 
726   // Handle the `--undefined <sym>` options.
727   for (auto *arg : args.filtered(OPT_undefined))
728     handleUndefined(arg->getValue());
729 
730   // Handle the `--export <sym>` options
731   // This works like --undefined but also exports the symbol if its found
732   for (auto *arg : args.filtered(OPT_export))
733     handleUndefined(arg->getValue());
734 
735   Symbol *entrySym = nullptr;
736   if (!config->relocatable && !config->entry.empty()) {
737     entrySym = handleUndefined(config->entry);
738     if (entrySym && entrySym->isDefined())
739       entrySym->forceExport = true;
740     else
741       error("entry symbol not defined (pass --no-entry to supress): " +
742             config->entry);
743   }
744 
745   if (errorCount())
746     return;
747 
748   // Create wrapped symbols for -wrap option.
749   std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
750 
751   // Do link-time optimization if given files are LLVM bitcode files.
752   // This compiles bitcode files into real object files.
753   symtab->addCombinedLTOObject();
754   if (errorCount())
755     return;
756 
757   // Resolve any variant symbols that were created due to signature
758   // mismatchs.
759   symtab->handleSymbolVariants();
760   if (errorCount())
761     return;
762 
763   // Apply symbol renames for -wrap.
764   if (!wrapped.empty())
765     wrapSymbols(wrapped);
766 
767   for (auto *arg : args.filtered(OPT_export)) {
768     Symbol *sym = symtab->find(arg->getValue());
769     if (sym && sym->isDefined())
770       sym->forceExport = true;
771     else if (!config->allowUndefined)
772       error(Twine("symbol exported via --export not found: ") +
773             arg->getValue());
774   }
775 
776   if (!config->relocatable) {
777     // Add synthetic dummies for weak undefined functions.  Must happen
778     // after LTO otherwise functions may not yet have signatures.
779     symtab->handleWeakUndefines();
780   }
781 
782   if (entrySym)
783     entrySym->setHidden(false);
784 
785   if (errorCount())
786     return;
787 
788   // Do size optimizations: garbage collection
789   markLive();
790 
791   // Write the result to the file.
792   writeResult();
793 }
794