xref: /llvm-project-15.0.7/lld/wasm/Driver.cpp (revision ed2853d2)
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 "InputTable.h"
14 #include "MarkLive.h"
15 #include "SymbolTable.h"
16 #include "Writer.h"
17 #include "lld/Common/Args.h"
18 #include "lld/Common/ErrorHandler.h"
19 #include "lld/Common/Filesystem.h"
20 #include "lld/Common/Memory.h"
21 #include "lld/Common/Reproduce.h"
22 #include "lld/Common/Strings.h"
23 #include "lld/Common/Version.h"
24 #include "llvm/ADT/Twine.h"
25 #include "llvm/Config/llvm-config.h"
26 #include "llvm/Object/Wasm.h"
27 #include "llvm/Option/Arg.h"
28 #include "llvm/Option/ArgList.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/Host.h"
31 #include "llvm/Support/Parallel.h"
32 #include "llvm/Support/Path.h"
33 #include "llvm/Support/Process.h"
34 #include "llvm/Support/TarWriter.h"
35 #include "llvm/Support/TargetSelect.h"
36 
37 #define DEBUG_TYPE "lld"
38 
39 using namespace llvm;
40 using namespace llvm::object;
41 using namespace llvm::sys;
42 using namespace llvm::wasm;
43 
44 namespace lld {
45 namespace wasm {
46 Configuration *config;
47 
48 namespace {
49 
50 // Create enum with OPT_xxx values for each option in Options.td
51 enum {
52   OPT_INVALID = 0,
53 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
54 #include "Options.inc"
55 #undef OPTION
56 };
57 
58 // This function is called on startup. We need this for LTO since
59 // LTO calls LLVM functions to compile bitcode files to native code.
60 // Technically this can be delayed until we read bitcode files, but
61 // we don't bother to do lazily because the initialization is fast.
62 static void initLLVM() {
63   InitializeAllTargets();
64   InitializeAllTargetMCs();
65   InitializeAllAsmPrinters();
66   InitializeAllAsmParsers();
67 }
68 
69 class LinkerDriver {
70 public:
71   void linkerMain(ArrayRef<const char *> argsArr);
72 
73 private:
74   void createFiles(opt::InputArgList &args);
75   void addFile(StringRef path);
76   void addLibrary(StringRef name);
77 
78   // True if we are in --whole-archive and --no-whole-archive.
79   bool inWholeArchive = false;
80 
81   std::vector<InputFile *> files;
82 };
83 } // anonymous namespace
84 
85 bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
86           raw_ostream &stderrOS) {
87   lld::stdoutOS = &stdoutOS;
88   lld::stderrOS = &stderrOS;
89 
90   errorHandler().cleanupCallback = []() { freeArena(); };
91 
92   errorHandler().logName = args::getFilenameWithoutExe(args[0]);
93   errorHandler().errorLimitExceededMsg =
94       "too many errors emitted, stopping now (use "
95       "-error-limit=0 to see all errors)";
96   stderrOS.enable_colors(stderrOS.has_colors());
97 
98   config = make<Configuration>();
99   symtab = make<SymbolTable>();
100 
101   initLLVM();
102   LinkerDriver().linkerMain(args);
103 
104   // Exit immediately if we don't need to return to the caller.
105   // This saves time because the overhead of calling destructors
106   // for all globally-allocated objects is not negligible.
107   if (canExitEarly)
108     exitLld(errorCount() ? 1 : 0);
109 
110   return !errorCount();
111 }
112 
113 // Create prefix string literals used in Options.td
114 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
115 #include "Options.inc"
116 #undef PREFIX
117 
118 // Create table mapping all options defined in Options.td
119 static const opt::OptTable::Info optInfo[] = {
120 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
121   {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
122    X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
123 #include "Options.inc"
124 #undef OPTION
125 };
126 
127 namespace {
128 class WasmOptTable : public llvm::opt::OptTable {
129 public:
130   WasmOptTable() : OptTable(optInfo) {}
131   opt::InputArgList parse(ArrayRef<const char *> argv);
132 };
133 } // namespace
134 
135 // Set color diagnostics according to -color-diagnostics={auto,always,never}
136 // or -no-color-diagnostics flags.
137 static void handleColorDiagnostics(opt::InputArgList &args) {
138   auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
139                               OPT_no_color_diagnostics);
140   if (!arg)
141     return;
142   if (arg->getOption().getID() == OPT_color_diagnostics) {
143     lld::errs().enable_colors(true);
144   } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
145     lld::errs().enable_colors(false);
146   } else {
147     StringRef s = arg->getValue();
148     if (s == "always")
149       lld::errs().enable_colors(true);
150     else if (s == "never")
151       lld::errs().enable_colors(false);
152     else if (s != "auto")
153       error("unknown option: --color-diagnostics=" + s);
154   }
155 }
156 
157 static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) {
158   if (auto *arg = args.getLastArg(OPT_rsp_quoting)) {
159     StringRef s = arg->getValue();
160     if (s != "windows" && s != "posix")
161       error("invalid response file quoting: " + s);
162     if (s == "windows")
163       return cl::TokenizeWindowsCommandLine;
164     return cl::TokenizeGNUCommandLine;
165   }
166   if (Triple(sys::getProcessTriple()).isOSWindows())
167     return cl::TokenizeWindowsCommandLine;
168   return cl::TokenizeGNUCommandLine;
169 }
170 
171 // Find a file by concatenating given paths.
172 static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
173   SmallString<128> s;
174   path::append(s, path1, path2);
175   if (fs::exists(s))
176     return std::string(s);
177   return None;
178 }
179 
180 opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) {
181   SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
182 
183   unsigned missingIndex;
184   unsigned missingCount;
185 
186   // We need to get the quoting style for response files before parsing all
187   // options so we parse here before and ignore all the options but
188   // --rsp-quoting.
189   opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
190 
191   // Expand response files (arguments in the form of @<filename>)
192   // and then parse the argument again.
193   cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec);
194   args = this->ParseArgs(vec, missingIndex, missingCount);
195 
196   handleColorDiagnostics(args);
197   for (auto *arg : args.filtered(OPT_UNKNOWN))
198     error("unknown argument: " + arg->getAsString(args));
199   return args;
200 }
201 
202 // Currently we allow a ".imports" to live alongside a library. This can
203 // be used to specify a list of symbols which can be undefined at link
204 // time (imported from the environment.  For example libc.a include an
205 // import file that lists the syscall functions it relies on at runtime.
206 // In the long run this information would be better stored as a symbol
207 // attribute/flag in the object file itself.
208 // See: https://github.com/WebAssembly/tool-conventions/issues/35
209 static void readImportFile(StringRef filename) {
210   if (Optional<MemoryBufferRef> buf = readFile(filename))
211     for (StringRef sym : args::getLines(*buf))
212       config->allowUndefinedSymbols.insert(sym);
213 }
214 
215 // Returns slices of MB by parsing MB as an archive file.
216 // Each slice consists of a member file in the archive.
217 std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef mb) {
218   std::unique_ptr<Archive> file =
219       CHECK(Archive::create(mb),
220             mb.getBufferIdentifier() + ": failed to parse archive");
221 
222   std::vector<MemoryBufferRef> v;
223   Error err = Error::success();
224   for (const Archive::Child &c : file->children(err)) {
225     MemoryBufferRef mbref =
226         CHECK(c.getMemoryBufferRef(),
227               mb.getBufferIdentifier() +
228                   ": could not get the buffer for a child of the archive");
229     v.push_back(mbref);
230   }
231   if (err)
232     fatal(mb.getBufferIdentifier() +
233           ": Archive::children failed: " + toString(std::move(err)));
234 
235   // Take ownership of memory buffers created for members of thin archives.
236   for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
237     make<std::unique_ptr<MemoryBuffer>>(std::move(mb));
238 
239   return v;
240 }
241 
242 void LinkerDriver::addFile(StringRef path) {
243   Optional<MemoryBufferRef> buffer = readFile(path);
244   if (!buffer.hasValue())
245     return;
246   MemoryBufferRef mbref = *buffer;
247 
248   switch (identify_magic(mbref.getBuffer())) {
249   case file_magic::archive: {
250     SmallString<128> importFile = path;
251     path::replace_extension(importFile, ".imports");
252     if (fs::exists(importFile))
253       readImportFile(importFile.str());
254 
255     // Handle -whole-archive.
256     if (inWholeArchive) {
257       for (MemoryBufferRef &m : getArchiveMembers(mbref)) {
258         auto *object = createObjectFile(m, path);
259         // Mark object as live; object members are normally not
260         // live by default but -whole-archive is designed to treat
261         // them as such.
262         object->markLive();
263         files.push_back(object);
264       }
265 
266       return;
267     }
268 
269     std::unique_ptr<Archive> file =
270         CHECK(Archive::create(mbref), path + ": failed to parse archive");
271 
272     if (!file->isEmpty() && !file->hasSymbolTable()) {
273       error(mbref.getBufferIdentifier() +
274             ": archive has no index; run ranlib to add one");
275     }
276 
277     files.push_back(make<ArchiveFile>(mbref));
278     return;
279   }
280   case file_magic::bitcode:
281   case file_magic::wasm_object:
282     files.push_back(createObjectFile(mbref));
283     break;
284   default:
285     error("unknown file type: " + mbref.getBufferIdentifier());
286   }
287 }
288 
289 // Add a given library by searching it from input search paths.
290 void LinkerDriver::addLibrary(StringRef name) {
291   for (StringRef dir : config->searchPaths) {
292     if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) {
293       addFile(*s);
294       return;
295     }
296   }
297 
298   error("unable to find library -l" + name);
299 }
300 
301 void LinkerDriver::createFiles(opt::InputArgList &args) {
302   for (auto *arg : args) {
303     switch (arg->getOption().getID()) {
304     case OPT_l:
305       addLibrary(arg->getValue());
306       break;
307     case OPT_INPUT:
308       addFile(arg->getValue());
309       break;
310     case OPT_whole_archive:
311       inWholeArchive = true;
312       break;
313     case OPT_no_whole_archive:
314       inWholeArchive = false;
315       break;
316     }
317   }
318   if (files.empty() && errorCount() == 0)
319     error("no input files");
320 }
321 
322 static StringRef getEntry(opt::InputArgList &args) {
323   auto *arg = args.getLastArg(OPT_entry, OPT_no_entry);
324   if (!arg) {
325     if (args.hasArg(OPT_relocatable))
326       return "";
327     if (args.hasArg(OPT_shared))
328       return "__wasm_call_ctors";
329     return "_start";
330   }
331   if (arg->getOption().getID() == OPT_no_entry)
332     return "";
333   return arg->getValue();
334 }
335 
336 // Determines what we should do if there are remaining unresolved
337 // symbols after the name resolution.
338 static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &args) {
339   UnresolvedPolicy errorOrWarn = args.hasFlag(OPT_error_unresolved_symbols,
340                                               OPT_warn_unresolved_symbols, true)
341                                      ? UnresolvedPolicy::ReportError
342                                      : UnresolvedPolicy::Warn;
343 
344   if (auto *arg = args.getLastArg(OPT_unresolved_symbols)) {
345     StringRef s = arg->getValue();
346     if (s == "ignore-all")
347       return UnresolvedPolicy::Ignore;
348     if (s == "import-functions")
349       return UnresolvedPolicy::ImportFuncs;
350     if (s == "report-all")
351       return errorOrWarn;
352     error("unknown --unresolved-symbols value: " + s);
353   }
354 
355   // Legacy --allow-undefined flag which is equivalent to
356   // --unresolve-symbols=ignore-all
357   if (args.hasArg(OPT_allow_undefined))
358     return UnresolvedPolicy::ImportFuncs;
359 
360   return errorOrWarn;
361 }
362 
363 // Initializes Config members by the command line options.
364 static void readConfigs(opt::InputArgList &args) {
365   config->bsymbolic = args.hasArg(OPT_Bsymbolic);
366   config->checkFeatures =
367       args.hasFlag(OPT_check_features, OPT_no_check_features, true);
368   config->compressRelocations = args.hasArg(OPT_compress_relocations);
369   config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
370   config->disableVerify = args.hasArg(OPT_disable_verify);
371   config->emitRelocs = args.hasArg(OPT_emit_relocs);
372   config->experimentalPic = args.hasArg(OPT_experimental_pic);
373   config->entry = getEntry(args);
374   config->exportAll = args.hasArg(OPT_export_all);
375   config->exportTable = args.hasArg(OPT_export_table);
376   config->growableTable = args.hasArg(OPT_growable_table);
377   errorHandler().fatalWarnings =
378       args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
379   config->importMemory = args.hasArg(OPT_import_memory);
380   config->sharedMemory = args.hasArg(OPT_shared_memory);
381   config->importTable = args.hasArg(OPT_import_table);
382   config->ltoo = args::getInteger(args, OPT_lto_O, 2);
383   config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
384   config->ltoNewPassManager =
385       args.hasFlag(OPT_no_lto_legacy_pass_manager, OPT_lto_legacy_pass_manager,
386                    LLVM_ENABLE_NEW_PASS_MANAGER);
387   config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
388   config->mapFile = args.getLastArgValue(OPT_Map);
389   config->optimize = args::getInteger(args, OPT_O, 0);
390   config->outputFile = args.getLastArgValue(OPT_o);
391   config->relocatable = args.hasArg(OPT_relocatable);
392   config->gcSections =
393       args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable);
394   config->mergeDataSegments =
395       args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
396                    !config->relocatable);
397   config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
398   config->printGcSections =
399       args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
400   config->saveTemps = args.hasArg(OPT_save_temps);
401   config->searchPaths = args::getStrings(args, OPT_L);
402   config->shared = args.hasArg(OPT_shared);
403   config->stripAll = args.hasArg(OPT_strip_all);
404   config->stripDebug = args.hasArg(OPT_strip_debug);
405   config->stackFirst = args.hasArg(OPT_stack_first);
406   config->trace = args.hasArg(OPT_trace);
407   config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
408   config->thinLTOCachePolicy = CHECK(
409       parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
410       "--thinlto-cache-policy: invalid cache policy");
411   config->unresolvedSymbols = getUnresolvedSymbolPolicy(args);
412   errorHandler().verbose = args.hasArg(OPT_verbose);
413   LLVM_DEBUG(errorHandler().verbose = true);
414 
415   config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
416   config->globalBase = args::getInteger(args, OPT_global_base, 1024);
417   config->maxMemory = args::getInteger(args, OPT_max_memory, 0);
418   config->zStackSize =
419       args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize);
420 
421   // Default value of exportDynamic depends on `-shared`
422   config->exportDynamic =
423       args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared);
424 
425   // Parse wasm32/64.
426   if (auto *arg = args.getLastArg(OPT_m)) {
427     StringRef s = arg->getValue();
428     if (s == "wasm32")
429       config->is64 = false;
430     else if (s == "wasm64")
431       config->is64 = true;
432     else
433       error("invalid target architecture: " + s);
434   }
435 
436   // --threads= takes a positive integer and provides the default value for
437   // --thinlto-jobs=.
438   if (auto *arg = args.getLastArg(OPT_threads)) {
439     StringRef v(arg->getValue());
440     unsigned threads = 0;
441     if (!llvm::to_integer(v, threads, 0) || threads == 0)
442       error(arg->getSpelling() + ": expected a positive integer, but got '" +
443             arg->getValue() + "'");
444     parallel::strategy = hardware_concurrency(threads);
445     config->thinLTOJobs = v;
446   }
447   if (auto *arg = args.getLastArg(OPT_thinlto_jobs))
448     config->thinLTOJobs = arg->getValue();
449 
450   if (auto *arg = args.getLastArg(OPT_features)) {
451     config->features =
452         llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
453     for (StringRef s : arg->getValues())
454       config->features->push_back(std::string(s));
455   }
456 
457   if (args.hasArg(OPT_print_map))
458     config->mapFile = "-";
459 }
460 
461 // Some Config members do not directly correspond to any particular
462 // command line options, but computed based on other Config values.
463 // This function initialize such members. See Config.h for the details
464 // of these values.
465 static void setConfigs() {
466   config->isPic = config->pie || config->shared;
467 
468   if (config->isPic) {
469     if (config->exportTable)
470       error("-shared/-pie is incompatible with --export-table");
471     config->importTable = true;
472   }
473 
474   if (config->shared) {
475     config->importMemory = true;
476     config->unresolvedSymbols = UnresolvedPolicy::ImportFuncs;
477   }
478 }
479 
480 // Some command line options or some combinations of them are not allowed.
481 // This function checks for such errors.
482 static void checkOptions(opt::InputArgList &args) {
483   if (!config->stripDebug && !config->stripAll && config->compressRelocations)
484     error("--compress-relocations is incompatible with output debug"
485           " information. Please pass --strip-debug or --strip-all");
486 
487   if (config->ltoo > 3)
488     error("invalid optimization level for LTO: " + Twine(config->ltoo));
489   if (config->ltoPartitions == 0)
490     error("--lto-partitions: number of threads must be > 0");
491   if (!get_threadpool_strategy(config->thinLTOJobs))
492     error("--thinlto-jobs: invalid job count: " + config->thinLTOJobs);
493 
494   if (config->pie && config->shared)
495     error("-shared and -pie may not be used together");
496 
497   if (config->outputFile.empty())
498     error("no output file specified");
499 
500   if (config->importTable && config->exportTable)
501     error("--import-table and --export-table may not be used together");
502 
503   if (config->relocatable) {
504     if (!config->entry.empty())
505       error("entry point specified for relocatable output file");
506     if (config->gcSections)
507       error("-r and --gc-sections may not be used together");
508     if (config->compressRelocations)
509       error("-r -and --compress-relocations may not be used together");
510     if (args.hasArg(OPT_undefined))
511       error("-r -and --undefined may not be used together");
512     if (config->pie)
513       error("-r and -pie may not be used together");
514     if (config->sharedMemory)
515       error("-r and --shared-memory may not be used together");
516   }
517 
518   // To begin to prepare for Module Linking-style shared libraries, start
519   // warning about uses of `-shared` and related flags outside of Experimental
520   // mode, to give anyone using them a heads-up that they will be changing.
521   //
522   // Also, warn about flags which request explicit exports.
523   if (!config->experimentalPic) {
524     // -shared will change meaning when Module Linking is implemented.
525     if (config->shared) {
526       warn("creating shared libraries, with -shared, is not yet stable");
527     }
528 
529     // -pie will change meaning when Module Linking is implemented.
530     if (config->pie) {
531       warn("creating PIEs, with -pie, is not yet stable");
532     }
533   }
534 
535   if (config->bsymbolic && !config->shared) {
536     warn("-Bsymbolic is only meaningful when combined with -shared");
537   }
538 }
539 
540 // Force Sym to be entered in the output. Used for -u or equivalent.
541 static Symbol *handleUndefined(StringRef name) {
542   Symbol *sym = symtab->find(name);
543   if (!sym)
544     return nullptr;
545 
546   // Since symbol S may not be used inside the program, LTO may
547   // eliminate it. Mark the symbol as "used" to prevent it.
548   sym->isUsedInRegularObj = true;
549 
550   if (auto *lazySym = dyn_cast<LazySymbol>(sym))
551     lazySym->fetch();
552 
553   return sym;
554 }
555 
556 static void handleLibcall(StringRef name) {
557   Symbol *sym = symtab->find(name);
558   if (!sym)
559     return;
560 
561   if (auto *lazySym = dyn_cast<LazySymbol>(sym)) {
562     MemoryBufferRef mb = lazySym->getMemberBuffer();
563     if (isBitcode(mb))
564       lazySym->fetch();
565   }
566 }
567 
568 static UndefinedGlobal *
569 createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
570   auto *sym = cast<UndefinedGlobal>(symtab->addUndefinedGlobal(
571       name, None, None, WASM_SYMBOL_UNDEFINED, nullptr, type));
572   config->allowUndefinedSymbols.insert(sym->getName());
573   sym->isUsedInRegularObj = true;
574   return sym;
575 }
576 
577 static InputGlobal *createGlobal(StringRef name, bool isMutable) {
578   llvm::wasm::WasmGlobal wasmGlobal;
579   if (config->is64.getValueOr(false)) {
580     wasmGlobal.Type = {WASM_TYPE_I64, isMutable};
581     wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I64_CONST;
582     wasmGlobal.InitExpr.Value.Int64 = 0;
583   } else {
584     wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
585     wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
586     wasmGlobal.InitExpr.Value.Int32 = 0;
587   }
588   wasmGlobal.SymbolName = name;
589   return make<InputGlobal>(wasmGlobal, nullptr);
590 }
591 
592 static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable) {
593   InputGlobal *g = createGlobal(name, isMutable);
594   return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN, g);
595 }
596 
597 static GlobalSymbol *createOptionalGlobal(StringRef name, bool isMutable) {
598   InputGlobal *g = createGlobal(name, isMutable);
599   return symtab->addOptionalGlobalSymbols(name, WASM_SYMBOL_VISIBILITY_HIDDEN,
600                                           g);
601 }
602 
603 // Create ABI-defined synthetic symbols
604 static void createSyntheticSymbols() {
605   if (config->relocatable)
606     return;
607 
608   static WasmSignature nullSignature = {{}, {}};
609   static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
610   static WasmSignature i64ArgSignature = {{}, {ValType::I64}};
611   static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
612   static llvm::wasm::WasmGlobalType globalTypeI64 = {WASM_TYPE_I64, false};
613   static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
614                                                             true};
615   static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64,
616                                                             true};
617   WasmSym::callCtors = symtab->addSyntheticFunction(
618       "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
619       make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
620 
621   if (config->isPic) {
622     WasmSym::stackPointer =
623         createUndefinedGlobal("__stack_pointer", config->is64.getValueOr(false)
624                                                      ? &mutableGlobalTypeI64
625                                                      : &mutableGlobalTypeI32);
626     // For PIC code, we import two global variables (__memory_base and
627     // __table_base) from the environment and use these as the offset at
628     // which to load our static data and function table.
629     // See:
630     // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
631     WasmSym::memoryBase = createUndefinedGlobal(
632         "__memory_base",
633         config->is64.getValueOr(false) ? &globalTypeI64 : &globalTypeI32);
634     WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32);
635     WasmSym::memoryBase->markLive();
636     WasmSym::tableBase->markLive();
637   } else {
638     // For non-PIC code
639     WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true);
640     WasmSym::stackPointer->markLive();
641   }
642 
643   if (config->sharedMemory && !config->relocatable) {
644     WasmSym::tlsBase = createGlobalVariable("__tls_base", true);
645     WasmSym::tlsSize = createGlobalVariable("__tls_size", false);
646     WasmSym::tlsAlign = createGlobalVariable("__tls_align", false);
647     WasmSym::initTLS = symtab->addSyntheticFunction(
648         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
649         make<SyntheticFunction>(
650             config->is64.getValueOr(false) ? i64ArgSignature : i32ArgSignature,
651             "__wasm_init_tls"));
652   }
653 }
654 
655 static void createOptionalSymbols() {
656   if (config->relocatable)
657     return;
658 
659   WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
660 
661   if (!config->shared)
662     WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
663 
664   if (!config->isPic) {
665     WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
666     WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
667     WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
668     WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base");
669   }
670 
671   // For non-shared memory programs we still need to define __tls_base since we
672   // allow object files built with TLS to be linked into single threaded
673   // programs, and such object files can contains refernced to this symbol.
674   //
675   // However, in this case __tls_base is immutable and points directly to the
676   // start of the `.tdata` static segment.
677   //
678   // __tls_size and __tls_align are not needed in this case since they are only
679   // needed for __wasm_init_tls (which we do not create in this case).
680   if (!config->sharedMemory)
681     WasmSym::tlsBase = createOptionalGlobal("__tls_base", false);
682 }
683 
684 // Reconstructs command line arguments so that so that you can re-run
685 // the same command with the same inputs. This is for --reproduce.
686 static std::string createResponseFile(const opt::InputArgList &args) {
687   SmallString<0> data;
688   raw_svector_ostream os(data);
689 
690   // Copy the command line to the output while rewriting paths.
691   for (auto *arg : args) {
692     switch (arg->getOption().getID()) {
693     case OPT_reproduce:
694       break;
695     case OPT_INPUT:
696       os << quote(relativeToRoot(arg->getValue())) << "\n";
697       break;
698     case OPT_o:
699       // If -o path contains directories, "lld @response.txt" will likely
700       // fail because the archive we are creating doesn't contain empty
701       // directories for the output path (-o doesn't create directories).
702       // Strip directories to prevent the issue.
703       os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
704       break;
705     default:
706       os << toString(*arg) << "\n";
707     }
708   }
709   return std::string(data.str());
710 }
711 
712 // The --wrap option is a feature to rename symbols so that you can write
713 // wrappers for existing functions. If you pass `-wrap=foo`, all
714 // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
715 // expected to write `wrap_foo` function as a wrapper). The original
716 // symbol becomes accessible as `real_foo`, so you can call that from your
717 // wrapper.
718 //
719 // This data structure is instantiated for each -wrap option.
720 struct WrappedSymbol {
721   Symbol *sym;
722   Symbol *real;
723   Symbol *wrap;
724 };
725 
726 static Symbol *addUndefined(StringRef name) {
727   return symtab->addUndefinedFunction(name, None, None, WASM_SYMBOL_UNDEFINED,
728                                       nullptr, nullptr, false);
729 }
730 
731 // Handles -wrap option.
732 //
733 // This function instantiates wrapper symbols. At this point, they seem
734 // like they are not being used at all, so we explicitly set some flags so
735 // that LTO won't eliminate them.
736 static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
737   std::vector<WrappedSymbol> v;
738   DenseSet<StringRef> seen;
739 
740   for (auto *arg : args.filtered(OPT_wrap)) {
741     StringRef name = arg->getValue();
742     if (!seen.insert(name).second)
743       continue;
744 
745     Symbol *sym = symtab->find(name);
746     if (!sym)
747       continue;
748 
749     Symbol *real = addUndefined(saver.save("__real_" + name));
750     Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
751     v.push_back({sym, real, wrap});
752 
753     // We want to tell LTO not to inline symbols to be overwritten
754     // because LTO doesn't know the final symbol contents after renaming.
755     real->canInline = false;
756     sym->canInline = false;
757 
758     // Tell LTO not to eliminate these symbols.
759     sym->isUsedInRegularObj = true;
760     wrap->isUsedInRegularObj = true;
761     real->isUsedInRegularObj = false;
762   }
763   return v;
764 }
765 
766 // Do renaming for -wrap by updating pointers to symbols.
767 //
768 // When this function is executed, only InputFiles and symbol table
769 // contain pointers to symbol objects. We visit them to replace pointers,
770 // so that wrapped symbols are swapped as instructed by the command line.
771 static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
772   DenseMap<Symbol *, Symbol *> map;
773   for (const WrappedSymbol &w : wrapped) {
774     map[w.sym] = w.wrap;
775     map[w.real] = w.sym;
776   }
777 
778   // Update pointers in input files.
779   parallelForEach(symtab->objectFiles, [&](InputFile *file) {
780     MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
781     for (size_t i = 0, e = syms.size(); i != e; ++i)
782       if (Symbol *s = map.lookup(syms[i]))
783         syms[i] = s;
784   });
785 
786   // Update pointers in the symbol table.
787   for (const WrappedSymbol &w : wrapped)
788     symtab->wrap(w.sym, w.real, w.wrap);
789 }
790 
791 static TableSymbol *createDefinedIndirectFunctionTable(StringRef name) {
792   const uint32_t invalidIndex = -1;
793   WasmLimits limits{0, 0, 0}; // Set by the writer.
794   WasmTableType type{uint8_t(ValType::FUNCREF), limits};
795   WasmTable desc{invalidIndex, type, name};
796   InputTable *table = make<InputTable>(desc, nullptr);
797   uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
798   TableSymbol *sym = symtab->addSyntheticTable(name, flags, table);
799   sym->markLive();
800   sym->forceExport = config->exportTable;
801   return sym;
802 }
803 
804 static TableSymbol *createUndefinedIndirectFunctionTable(StringRef name) {
805   WasmLimits limits{0, 0, 0}; // Set by the writer.
806   WasmTableType *type = make<WasmTableType>();
807   type->ElemType = uint8_t(ValType::FUNCREF);
808   type->Limits = limits;
809   StringRef module(defaultModule);
810   uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
811   flags |= WASM_SYMBOL_UNDEFINED;
812   Symbol *sym =
813       symtab->addUndefinedTable(name, name, module, flags, nullptr, type);
814   sym->markLive();
815   sym->forceExport = config->exportTable;
816   return cast<TableSymbol>(sym);
817 }
818 
819 static TableSymbol *resolveIndirectFunctionTable() {
820   Symbol *existingTable = symtab->find(functionTableName);
821   if (existingTable) {
822     if (!isa<TableSymbol>(existingTable)) {
823       error(Twine("reserved symbol must be of type table: `") +
824             functionTableName + "`");
825       return nullptr;
826     }
827     if (existingTable->isDefined()) {
828       error(Twine("reserved symbol must not be defined in input files: `") +
829             functionTableName + "`");
830       return nullptr;
831     }
832   }
833 
834   if (config->importTable) {
835     if (existingTable)
836       return cast<TableSymbol>(existingTable);
837     else
838       return createUndefinedIndirectFunctionTable(functionTableName);
839   } else if ((existingTable && existingTable->isLive()) ||
840              config->exportTable) {
841     // A defined table is required.  Either because the user request an exported
842     // table or because the table symbol is already live.  The existing table is
843     // guaranteed to be undefined due to the check above.
844     return createDefinedIndirectFunctionTable(functionTableName);
845   }
846 
847   // An indirect function table will only be present in the symbol table if
848   // needed by a reloc; if we get here, we don't need one.
849   return nullptr;
850 }
851 
852 void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
853   WasmOptTable parser;
854   opt::InputArgList args = parser.parse(argsArr.slice(1));
855 
856   // Handle --help
857   if (args.hasArg(OPT_help)) {
858     parser.PrintHelp(lld::outs(),
859                      (std::string(argsArr[0]) + " [options] file...").c_str(),
860                      "LLVM Linker", false);
861     return;
862   }
863 
864   // Handle --version
865   if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) {
866     lld::outs() << getLLDVersion() << "\n";
867     return;
868   }
869 
870   // Handle --reproduce
871   if (auto *arg = args.getLastArg(OPT_reproduce)) {
872     StringRef path = arg->getValue();
873     Expected<std::unique_ptr<TarWriter>> errOrWriter =
874         TarWriter::create(path, path::stem(path));
875     if (errOrWriter) {
876       tar = std::move(*errOrWriter);
877       tar->append("response.txt", createResponseFile(args));
878       tar->append("version.txt", getLLDVersion() + "\n");
879     } else {
880       error("--reproduce: " + toString(errOrWriter.takeError()));
881     }
882   }
883 
884   // Parse and evaluate -mllvm options.
885   std::vector<const char *> v;
886   v.push_back("wasm-ld (LLVM option parsing)");
887   for (auto *arg : args.filtered(OPT_mllvm))
888     v.push_back(arg->getValue());
889   cl::ResetAllOptionOccurrences();
890   cl::ParseCommandLineOptions(v.size(), v.data());
891 
892   errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
893 
894   readConfigs(args);
895 
896   createFiles(args);
897   if (errorCount())
898     return;
899 
900   setConfigs();
901   checkOptions(args);
902   if (errorCount())
903     return;
904 
905   if (auto *arg = args.getLastArg(OPT_allow_undefined_file))
906     readImportFile(arg->getValue());
907 
908   // Fail early if the output file or map file is not writable. If a user has a
909   // long link, e.g. due to a large LTO link, they do not wish to run it and
910   // find that it failed because there was a mistake in their command-line.
911   if (auto e = tryCreateFile(config->outputFile))
912     error("cannot open output file " + config->outputFile + ": " + e.message());
913   if (auto e = tryCreateFile(config->mapFile))
914     error("cannot open map file " + config->mapFile + ": " + e.message());
915   if (errorCount())
916     return;
917 
918   // Handle --trace-symbol.
919   for (auto *arg : args.filtered(OPT_trace_symbol))
920     symtab->trace(arg->getValue());
921 
922   for (auto *arg : args.filtered(OPT_export))
923     config->exportedSymbols.insert(arg->getValue());
924 
925   createSyntheticSymbols();
926 
927   // Add all files to the symbol table. This will add almost all
928   // symbols that we need to the symbol table.
929   for (InputFile *f : files)
930     symtab->addFile(f);
931   if (errorCount())
932     return;
933 
934   // Handle the `--undefined <sym>` options.
935   for (auto *arg : args.filtered(OPT_undefined))
936     handleUndefined(arg->getValue());
937 
938   // Handle the `--export <sym>` options
939   // This works like --undefined but also exports the symbol if its found
940   for (auto *arg : args.filtered(OPT_export))
941     handleUndefined(arg->getValue());
942 
943   Symbol *entrySym = nullptr;
944   if (!config->relocatable && !config->entry.empty()) {
945     entrySym = handleUndefined(config->entry);
946     if (entrySym && entrySym->isDefined())
947       entrySym->forceExport = true;
948     else
949       error("entry symbol not defined (pass --no-entry to suppress): " +
950             config->entry);
951   }
952 
953   // If the user code defines a `__wasm_call_dtors` function, remember it so
954   // that we can call it from the command export wrappers. Unlike
955   // `__wasm_call_ctors` which we synthesize, `__wasm_call_dtors` is defined
956   // by libc/etc., because destructors are registered dynamically with
957   // `__cxa_atexit` and friends.
958   if (!config->relocatable && !config->shared &&
959       !WasmSym::callCtors->isUsedInRegularObj &&
960       WasmSym::callCtors->getName() != config->entry &&
961       !config->exportedSymbols.count(WasmSym::callCtors->getName())) {
962     if (Symbol *callDtors = handleUndefined("__wasm_call_dtors")) {
963       if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(callDtors)) {
964         if (callDtorsFunc->signature &&
965             (!callDtorsFunc->signature->Params.empty() ||
966              !callDtorsFunc->signature->Returns.empty())) {
967           error("__wasm_call_dtors must have no argument or return values");
968         }
969         WasmSym::callDtors = callDtorsFunc;
970       } else {
971         error("__wasm_call_dtors must be a function");
972       }
973     }
974   }
975 
976   createOptionalSymbols();
977 
978   if (errorCount())
979     return;
980 
981   // Create wrapped symbols for -wrap option.
982   std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
983 
984   // If any of our inputs are bitcode files, the LTO code generator may create
985   // references to certain library functions that might not be explicit in the
986   // bitcode file's symbol table. If any of those library functions are defined
987   // in a bitcode file in an archive member, we need to arrange to use LTO to
988   // compile those archive members by adding them to the link beforehand.
989   //
990   // We only need to add libcall symbols to the link before LTO if the symbol's
991   // definition is in bitcode. Any other required libcall symbols will be added
992   // to the link after LTO when we add the LTO object file to the link.
993   if (!symtab->bitcodeFiles.empty())
994     for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
995       handleLibcall(s);
996   if (errorCount())
997     return;
998 
999   // Do link-time optimization if given files are LLVM bitcode files.
1000   // This compiles bitcode files into real object files.
1001   symtab->addCombinedLTOObject();
1002   if (errorCount())
1003     return;
1004 
1005   // Resolve any variant symbols that were created due to signature
1006   // mismatchs.
1007   symtab->handleSymbolVariants();
1008   if (errorCount())
1009     return;
1010 
1011   // Apply symbol renames for -wrap.
1012   if (!wrapped.empty())
1013     wrapSymbols(wrapped);
1014 
1015   for (auto *arg : args.filtered(OPT_export)) {
1016     Symbol *sym = symtab->find(arg->getValue());
1017     if (sym && sym->isDefined())
1018       sym->forceExport = true;
1019     else if (config->unresolvedSymbols == UnresolvedPolicy::ReportError)
1020       error(Twine("symbol exported via --export not found: ") +
1021             arg->getValue());
1022     else if (config->unresolvedSymbols == UnresolvedPolicy::Warn)
1023       warn(Twine("symbol exported via --export not found: ") + arg->getValue());
1024   }
1025 
1026   if (!config->relocatable && !config->isPic) {
1027     // Add synthetic dummies for weak undefined functions.  Must happen
1028     // after LTO otherwise functions may not yet have signatures.
1029     symtab->handleWeakUndefines();
1030   }
1031 
1032   if (entrySym)
1033     entrySym->setHidden(false);
1034 
1035   if (errorCount())
1036     return;
1037 
1038   // Do size optimizations: garbage collection
1039   markLive();
1040 
1041   if (!config->relocatable) {
1042     // Provide the indirect funciton table if needed.
1043     WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
1044 
1045     if (errorCount())
1046       return;
1047   }
1048 
1049   // Write the result to the file.
1050   writeResult();
1051 }
1052 
1053 } // namespace wasm
1054 } // namespace lld
1055