xref: /llvm-project-15.0.7/lld/wasm/Driver.cpp (revision fcd549a7)
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().colorDiagnostics = error.has_colors();
87   errorHandler().errorLimitExceededMsg =
88       "too many errors emitted, stopping now (use "
89       "-error-limit=0 to see all errors)";
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     errorHandler().colorDiagnostics = true;
138   } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
139     errorHandler().colorDiagnostics = false;
140   } else {
141     StringRef s = arg->getValue();
142     if (s == "always")
143       errorHandler().colorDiagnostics = true;
144     else if (s == "never")
145       errorHandler().colorDiagnostics = 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->exportDynamic = args.hasFlag(OPT_export_dynamic,
317       OPT_no_export_dynamic, false);
318   config->exportTable = args.hasArg(OPT_export_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->passiveSegments = args.hasFlag(
324       OPT_passive_segments, OPT_active_segments, config->sharedMemory);
325   config->importTable = args.hasArg(OPT_import_table);
326   config->ltoo = args::getInteger(args, OPT_lto_O, 2);
327   config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
328   config->optimize = args::getInteger(args, OPT_O, 0);
329   config->outputFile = args.getLastArgValue(OPT_o);
330   config->relocatable = args.hasArg(OPT_relocatable);
331   config->gcSections =
332       args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable);
333   config->mergeDataSegments =
334       args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
335                    !config->relocatable);
336   config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
337   config->printGcSections =
338       args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
339   config->saveTemps = args.hasArg(OPT_save_temps);
340   config->searchPaths = args::getStrings(args, OPT_L);
341   config->shared = args.hasArg(OPT_shared);
342   config->stripAll = args.hasArg(OPT_strip_all);
343   config->stripDebug = args.hasArg(OPT_strip_debug);
344   config->stackFirst = args.hasArg(OPT_stack_first);
345   config->trace = args.hasArg(OPT_trace);
346   config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
347   config->thinLTOCachePolicy = CHECK(
348       parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
349       "--thinlto-cache-policy: invalid cache policy");
350   config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u);
351   errorHandler().verbose = args.hasArg(OPT_verbose);
352   LLVM_DEBUG(errorHandler().verbose = true);
353   threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true);
354 
355   config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
356   config->globalBase = args::getInteger(args, OPT_global_base, 1024);
357   config->maxMemory = args::getInteger(args, OPT_max_memory, 0);
358   config->zStackSize =
359       args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize);
360 
361   if (auto *arg = args.getLastArg(OPT_features)) {
362     config->features =
363         llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
364     for (StringRef s : arg->getValues())
365       config->features->push_back(s);
366   }
367 }
368 
369 // Some Config members do not directly correspond to any particular
370 // command line options, but computed based on other Config values.
371 // This function initialize such members. See Config.h for the details
372 // of these values.
373 static void setConfigs() {
374   config->isPic = config->pie || config->shared;
375 
376   if (config->isPic) {
377     if (config->exportTable)
378       error("-shared/-pie is incompatible with --export-table");
379     config->importTable = true;
380   }
381 
382   if (config->shared) {
383     config->importMemory = true;
384     config->exportDynamic = 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   static WasmSignature nullSignature = {{}, {}};
467   static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
468   static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
469   static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
470                                                             true};
471 
472   if (!config->relocatable) {
473     WasmSym::callCtors = symtab->addSyntheticFunction(
474         "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
475         make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
476 
477     if (config->passiveSegments) {
478       // Passive segments are used to avoid memory being reinitialized on each
479       // thread's instantiation. These passive segments are initialized and
480       // dropped in __wasm_init_memory, which is the first function called from
481       // __wasm_call_ctors.
482       WasmSym::initMemory = symtab->addSyntheticFunction(
483           "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
484           make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
485     }
486 
487     if (config->isPic) {
488       // For PIC code we create a synthetic function __wasm_apply_relocs which
489       // is called from __wasm_call_ctors before the user-level constructors.
490       WasmSym::applyRelocs = symtab->addSyntheticFunction(
491           "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
492           make<SyntheticFunction>(nullSignature, "__wasm_apply_relocs"));
493     }
494   }
495 
496   if (!config->shared)
497     WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
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     llvm::wasm::WasmGlobal global;
514     global.Type = {WASM_TYPE_I32, true};
515     global.InitExpr.Value.Int32 = 0;
516     global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
517     global.SymbolName = "__stack_pointer";
518     auto *stackPointer = make<InputGlobal>(global, nullptr);
519     stackPointer->live = true;
520     // For non-PIC code
521     // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global
522     // spec proposal is implemented in all major browsers.
523     // See: https://github.com/WebAssembly/mutable-global
524     WasmSym::stackPointer = symtab->addSyntheticGlobal(
525         "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, stackPointer);
526     WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
527     WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
528   }
529 
530   if (config->sharedMemory && !config->shared) {
531     WasmSym::tlsBase = createGlobalVariable("__tls_base", true, 0);
532     WasmSym::tlsSize = createGlobalVariable("__tls_size", false, 0);
533     WasmSym::tlsAlign = createGlobalVariable("__tls_align", false, 1);
534     WasmSym::initTLS = symtab->addSyntheticFunction(
535         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
536         make<SyntheticFunction>(i32ArgSignature, "__wasm_init_tls"));
537   }
538 
539   WasmSym::dsoHandle = symtab->addSyntheticDataSymbol(
540       "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);
541 }
542 
543 // Reconstructs command line arguments so that so that you can re-run
544 // the same command with the same inputs. This is for --reproduce.
545 static std::string createResponseFile(const opt::InputArgList &args) {
546   SmallString<0> data;
547   raw_svector_ostream os(data);
548 
549   // Copy the command line to the output while rewriting paths.
550   for (auto *arg : args) {
551     switch (arg->getOption().getID()) {
552     case OPT_reproduce:
553       break;
554     case OPT_INPUT:
555       os << quote(relativeToRoot(arg->getValue())) << "\n";
556       break;
557     case OPT_o:
558       // If -o path contains directories, "lld @response.txt" will likely
559       // fail because the archive we are creating doesn't contain empty
560       // directories for the output path (-o doesn't create directories).
561       // Strip directories to prevent the issue.
562       os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
563       break;
564     default:
565       os << toString(*arg) << "\n";
566     }
567   }
568   return data.str();
569 }
570 
571 // The --wrap option is a feature to rename symbols so that you can write
572 // wrappers for existing functions. If you pass `-wrap=foo`, all
573 // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
574 // expected to write `wrap_foo` function as a wrapper). The original
575 // symbol becomes accessible as `real_foo`, so you can call that from your
576 // wrapper.
577 //
578 // This data structure is instantiated for each -wrap option.
579 struct WrappedSymbol {
580   Symbol *sym;
581   Symbol *real;
582   Symbol *wrap;
583 };
584 
585 static Symbol *addUndefined(StringRef name) {
586   return symtab->addUndefinedFunction(name, "", "", 0, nullptr, nullptr, false);
587 }
588 
589 // Handles -wrap option.
590 //
591 // This function instantiates wrapper symbols. At this point, they seem
592 // like they are not being used at all, so we explicitly set some flags so
593 // that LTO won't eliminate them.
594 static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
595   std::vector<WrappedSymbol> v;
596   DenseSet<StringRef> seen;
597 
598   for (auto *arg : args.filtered(OPT_wrap)) {
599     StringRef name = arg->getValue();
600     if (!seen.insert(name).second)
601       continue;
602 
603     Symbol *sym = symtab->find(name);
604     if (!sym)
605       continue;
606 
607     Symbol *real = addUndefined(saver.save("__real_" + name));
608     Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
609     v.push_back({sym, real, wrap});
610 
611     // We want to tell LTO not to inline symbols to be overwritten
612     // because LTO doesn't know the final symbol contents after renaming.
613     real->canInline = false;
614     sym->canInline = false;
615 
616     // Tell LTO not to eliminate these symbols.
617     sym->isUsedInRegularObj = true;
618     wrap->isUsedInRegularObj = true;
619     real->isUsedInRegularObj = false;
620   }
621   return v;
622 }
623 
624 // Do renaming for -wrap by updating pointers to symbols.
625 //
626 // When this function is executed, only InputFiles and symbol table
627 // contain pointers to symbol objects. We visit them to replace pointers,
628 // so that wrapped symbols are swapped as instructed by the command line.
629 static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
630   DenseMap<Symbol *, Symbol *> map;
631   for (const WrappedSymbol &w : wrapped) {
632     map[w.sym] = w.wrap;
633     map[w.real] = w.sym;
634   }
635 
636   // Update pointers in input files.
637   parallelForEach(symtab->objectFiles, [&](InputFile *file) {
638     MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
639     for (size_t i = 0, e = syms.size(); i != e; ++i)
640       if (Symbol *s = map.lookup(syms[i]))
641         syms[i] = s;
642   });
643 
644   // Update pointers in the symbol table.
645   for (const WrappedSymbol &w : wrapped)
646     symtab->wrap(w.sym, w.real, w.wrap);
647 }
648 
649 void LinkerDriver::link(ArrayRef<const char *> argsArr) {
650   WasmOptTable parser;
651   opt::InputArgList args = parser.parse(argsArr.slice(1));
652 
653   // Handle --help
654   if (args.hasArg(OPT_help)) {
655     parser.PrintHelp(outs(),
656                      (std::string(argsArr[0]) + " [options] file...").c_str(),
657                      "LLVM Linker", false);
658     return;
659   }
660 
661   // Handle --version
662   if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) {
663     outs() << getLLDVersion() << "\n";
664     return;
665   }
666 
667   // Handle --reproduce
668   if (auto *arg = args.getLastArg(OPT_reproduce)) {
669     StringRef path = arg->getValue();
670     Expected<std::unique_ptr<TarWriter>> errOrWriter =
671         TarWriter::create(path, path::stem(path));
672     if (errOrWriter) {
673       tar = std::move(*errOrWriter);
674       tar->append("response.txt", createResponseFile(args));
675       tar->append("version.txt", getLLDVersion() + "\n");
676     } else {
677       error("--reproduce: " + toString(errOrWriter.takeError()));
678     }
679   }
680 
681   // Parse and evaluate -mllvm options.
682   std::vector<const char *> v;
683   v.push_back("wasm-ld (LLVM option parsing)");
684   for (auto *arg : args.filtered(OPT_mllvm))
685     v.push_back(arg->getValue());
686   cl::ParseCommandLineOptions(v.size(), v.data());
687 
688   errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
689 
690   readConfigs(args);
691   setConfigs();
692   checkOptions(args);
693 
694   if (auto *arg = args.getLastArg(OPT_allow_undefined_file))
695     readImportFile(arg->getValue());
696 
697   if (!args.hasArg(OPT_INPUT)) {
698     error("no input files");
699     return;
700   }
701 
702   // Handle --trace-symbol.
703   for (auto *arg : args.filtered(OPT_trace_symbol))
704     symtab->trace(arg->getValue());
705 
706   for (auto *arg : args.filtered(OPT_export))
707     config->exportedSymbols.insert(arg->getValue());
708 
709   if (!config->relocatable)
710     createSyntheticSymbols();
711 
712   createFiles(args);
713   if (errorCount())
714     return;
715 
716   // Add all files to the symbol table. This will add almost all
717   // symbols that we need to the symbol table.
718   for (InputFile *f : files)
719     symtab->addFile(f);
720   if (errorCount())
721     return;
722 
723   // Handle the `--undefined <sym>` options.
724   for (auto *arg : args.filtered(OPT_undefined))
725     handleUndefined(arg->getValue());
726 
727   // Handle the `--export <sym>` options
728   // This works like --undefined but also exports the symbol if its found
729   for (auto *arg : args.filtered(OPT_export))
730     handleUndefined(arg->getValue());
731 
732   Symbol *entrySym = nullptr;
733   if (!config->relocatable && !config->entry.empty()) {
734     entrySym = handleUndefined(config->entry);
735     if (entrySym && entrySym->isDefined())
736       entrySym->forceExport = true;
737     else
738       error("entry symbol not defined (pass --no-entry to supress): " +
739             config->entry);
740   }
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