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