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 "InputElement.h"
13#include "MarkLive.h"
14#include "SymbolTable.h"
15#include "Writer.h"
16#include "lld/Common/Args.h"
17#include "lld/Common/CommonLinkerContext.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/Option/Arg.h"
27#include "llvm/Option/ArgList.h"
28#include "llvm/Support/CommandLine.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#include "llvm/TargetParser/Host.h"
35#include <optional>
36
37#define DEBUG_TYPE "lld"
38
39using namespace llvm;
40using namespace llvm::object;
41using namespace llvm::opt;
42using namespace llvm::sys;
43using namespace llvm::wasm;
44
45namespace lld::wasm {
46Ctx ctx;
47
48void errorOrWarn(const llvm::Twine &msg) {
49 if (ctx.arg.noinhibitExec)
50 warn(msg);
51 else
52 error(msg);
53}
54
55Ctx::Ctx() {}
56
57void Ctx::reset() {
58 arg.~Config();
59 new (&arg) Config();
60 objectFiles.clear();
61 stubFiles.clear();
62 sharedFiles.clear();
63 bitcodeFiles.clear();
64 lazyBitcodeFiles.clear();
65 syntheticFunctions.clear();
66 syntheticGlobals.clear();
67 syntheticTables.clear();
68 whyExtractRecords.clear();
69 isPic = false;
70 legacyFunctionTable = false;
71 emitBssSegments = false;
72 sym = WasmSym{};
73}
74
75namespace {
76
77// Create enum with OPT_xxx values for each option in Options.td
78enum {
79 OPT_INVALID = 0,
80#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
81#include "Options.inc"
82#undef OPTION
83};
84
85// This function is called on startup. We need this for LTO since
86// LTO calls LLVM functions to compile bitcode files to native code.
87// Technically this can be delayed until we read bitcode files, but
88// we don't bother to do lazily because the initialization is fast.
89static void initLLVM() {
90 InitializeAllTargets();
91 InitializeAllTargetMCs();
92 InitializeAllAsmPrinters();
93 InitializeAllAsmParsers();
94}
95
96class LinkerDriver {
97public:
98 LinkerDriver(Ctx &);
99 void linkerMain(ArrayRef<const char *> argsArr);
100
101private:
102 void createFiles(opt::InputArgList &args);
103 void addFile(StringRef path);
104 void addLibrary(StringRef name);
105
106 Ctx &ctx;
107
108 // True if we are in --whole-archive and --no-whole-archive.
109 bool inWholeArchive = false;
110
111 // True if we are in --start-lib and --end-lib.
112 bool inLib = false;
113
114 std::vector<InputFile *> files;
115};
116
117static bool hasZOption(opt::InputArgList &args, StringRef key) {
118 bool ret = false;
119 for (const auto *arg : args.filtered(Ids: OPT_z))
120 if (key == arg->getValue()) {
121 ret = true;
122 arg->claim();
123 }
124 return ret;
125}
126} // anonymous namespace
127
128bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
129 llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
130 // This driver-specific context will be freed later by unsafeLldMain().
131 auto *context = new CommonLinkerContext;
132
133 context->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
134 context->e.cleanupCallback = []() { ctx.reset(); };
135 context->e.logName = args::getFilenameWithoutExe(path: args[0]);
136 context->e.errorLimitExceededMsg =
137 "too many errors emitted, stopping now (use "
138 "-error-limit=0 to see all errors)";
139
140 symtab = make<SymbolTable>();
141
142 initLLVM();
143 LinkerDriver(ctx).linkerMain(argsArr: args);
144
145 return errorCount() == 0;
146}
147
148#define OPTTABLE_STR_TABLE_CODE
149#include "Options.inc"
150#undef OPTTABLE_STR_TABLE_CODE
151
152#define OPTTABLE_PREFIXES_TABLE_CODE
153#include "Options.inc"
154#undef OPTTABLE_PREFIXES_TABLE_CODE
155
156// Create table mapping all options defined in Options.td
157static constexpr opt::OptTable::Info optInfo[] = {
158#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
159 VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \
160 VALUES, SUBCOMMANDIDS_OFFSET) \
161 {PREFIX, \
162 NAME, \
163 HELPTEXT, \
164 HELPTEXTSFORVARIANTS, \
165 METAVAR, \
166 OPT_##ID, \
167 opt::Option::KIND##Class, \
168 PARAM, \
169 FLAGS, \
170 VISIBILITY, \
171 OPT_##GROUP, \
172 OPT_##ALIAS, \
173 ALIASARGS, \
174 VALUES, \
175 SUBCOMMANDIDS_OFFSET},
176#include "Options.inc"
177#undef OPTION
178};
179
180namespace {
181class WasmOptTable : public opt::GenericOptTable {
182public:
183 WasmOptTable()
184 : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, optInfo) {}
185 opt::InputArgList parse(ArrayRef<const char *> argv);
186};
187} // namespace
188
189// Set color diagnostics according to -color-diagnostics={auto,always,never}
190// or -no-color-diagnostics flags.
191static void handleColorDiagnostics(opt::InputArgList &args) {
192 auto *arg = args.getLastArg(Ids: OPT_color_diagnostics, Ids: OPT_color_diagnostics_eq,
193 Ids: OPT_no_color_diagnostics);
194 if (!arg)
195 return;
196 auto &errs = errorHandler().errs();
197 if (arg->getOption().getID() == OPT_color_diagnostics) {
198 errs.enable_colors(enable: true);
199 } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
200 errs.enable_colors(enable: false);
201 } else {
202 StringRef s = arg->getValue();
203 if (s == "always")
204 errs.enable_colors(enable: true);
205 else if (s == "never")
206 errs.enable_colors(enable: false);
207 else if (s != "auto")
208 error(msg: "unknown option: --color-diagnostics=" + s);
209 }
210}
211
212static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) {
213 if (auto *arg = args.getLastArg(Ids: OPT_rsp_quoting)) {
214 StringRef s = arg->getValue();
215 if (s != "windows" && s != "posix")
216 error(msg: "invalid response file quoting: " + s);
217 if (s == "windows")
218 return cl::TokenizeWindowsCommandLine;
219 return cl::TokenizeGNUCommandLine;
220 }
221 if (Triple(sys::getProcessTriple()).isOSWindows())
222 return cl::TokenizeWindowsCommandLine;
223 return cl::TokenizeGNUCommandLine;
224}
225
226// Find a file by concatenating given paths.
227static std::optional<std::string> findFile(StringRef path1,
228 const Twine &path2) {
229 SmallString<128> s;
230 path::append(path&: s, a: path1, b: path2);
231 if (fs::exists(Path: s))
232 return std::string(s);
233 return std::nullopt;
234}
235
236opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) {
237 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
238
239 unsigned missingIndex;
240 unsigned missingCount;
241
242 // We need to get the quoting style for response files before parsing all
243 // options so we parse here before and ignore all the options but
244 // --rsp-quoting.
245 opt::InputArgList args = this->ParseArgs(Args: vec, MissingArgIndex&: missingIndex, MissingArgCount&: missingCount);
246
247 // Expand response files (arguments in the form of @<filename>)
248 // and then parse the argument again.
249 cl::ExpandResponseFiles(Saver&: saver(), Tokenizer: getQuotingStyle(args), Argv&: vec);
250 args = this->ParseArgs(Args: vec, MissingArgIndex&: missingIndex, MissingArgCount&: missingCount);
251
252 handleColorDiagnostics(args);
253 if (missingCount)
254 error(msg: Twine(args.getArgString(Index: missingIndex)) + ": missing argument");
255
256 for (auto *arg : args.filtered(Ids: OPT_UNKNOWN))
257 error(msg: "unknown argument: " + arg->getAsString(Args: args));
258 return args;
259}
260
261// Currently we allow a ".imports" to live alongside a library. This can
262// be used to specify a list of symbols which can be undefined at link
263// time (imported from the environment. For example libc.a include an
264// import file that lists the syscall functions it relies on at runtime.
265// In the long run this information would be better stored as a symbol
266// attribute/flag in the object file itself.
267// See: https://github.com/WebAssembly/tool-conventions/issues/35
268static void readImportFile(StringRef filename) {
269 if (std::optional<MemoryBufferRef> buf = readFile(path: filename))
270 for (StringRef sym : args::getLines(mb: *buf))
271 ctx.arg.allowUndefinedSymbols.insert(key: sym);
272}
273
274// Returns slices of MB by parsing MB as an archive file.
275// Each slice consists of a member file in the archive.
276std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
277 MemoryBufferRef mb) {
278 std::unique_ptr<Archive> file =
279 CHECK(Archive::create(mb),
280 mb.getBufferIdentifier() + ": failed to parse archive");
281
282 std::vector<std::pair<MemoryBufferRef, uint64_t>> v;
283 Error err = Error::success();
284 for (const Archive::Child &c : file->children(Err&: err)) {
285 MemoryBufferRef mbref =
286 CHECK(c.getMemoryBufferRef(),
287 mb.getBufferIdentifier() +
288 ": could not get the buffer for a child of the archive");
289 v.push_back(x: std::make_pair(x&: mbref, y: c.getChildOffset()));
290 }
291 if (err)
292 fatal(msg: mb.getBufferIdentifier() +
293 ": Archive::children failed: " + toString(E: std::move(err)));
294
295 // Take ownership of memory buffers created for members of thin archives.
296 for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
297 make<std::unique_ptr<MemoryBuffer>>(args: std::move(mb));
298
299 return v;
300}
301
302void LinkerDriver::addFile(StringRef path) {
303 std::optional<MemoryBufferRef> buffer = readFile(path);
304 if (!buffer)
305 return;
306 MemoryBufferRef mbref = *buffer;
307
308 switch (identify_magic(magic: mbref.getBuffer())) {
309 case file_magic::archive: {
310 SmallString<128> importFile = path;
311 path::replace_extension(path&: importFile, extension: ".imports");
312 if (fs::exists(Path: importFile))
313 readImportFile(filename: importFile.str());
314
315 auto members = getArchiveMembers(mb: mbref);
316
317 // Handle -whole-archive.
318 if (inWholeArchive) {
319 for (const auto &[m, offset] : members) {
320 auto *object = createObjectFile(mb: m, archiveName: path, offsetInArchive: offset);
321 files.push_back(x: object);
322 }
323
324 return;
325 }
326
327 std::unique_ptr<Archive> file =
328 CHECK(Archive::create(mbref), path + ": failed to parse archive");
329
330 for (const auto &[m, offset] : members) {
331 auto magic = identify_magic(magic: m.getBuffer());
332 if (magic == file_magic::wasm_object || magic == file_magic::bitcode)
333 files.push_back(x: createObjectFile(mb: m, archiveName: path, offsetInArchive: offset, lazy: true));
334 else
335 warn(msg: path + ": archive member '" + m.getBufferIdentifier() +
336 "' is neither Wasm object file nor LLVM bitcode");
337 }
338
339 return;
340 }
341 case file_magic::bitcode:
342 case file_magic::wasm_object: {
343 auto obj = createObjectFile(mb: mbref, archiveName: "", offsetInArchive: 0, lazy: inLib);
344 if (ctx.arg.isStatic && isa<SharedFile>(Val: obj)) {
345 error(msg: "attempted static link of dynamic object " + path);
346 break;
347 }
348 files.push_back(x: obj);
349 break;
350 }
351 case file_magic::unknown:
352 if (mbref.getBuffer().starts_with(Prefix: "#STUB")) {
353 files.push_back(x: make<StubFile>(args&: mbref));
354 break;
355 }
356 [[fallthrough]];
357 default:
358 error(msg: "unknown file type: " + mbref.getBufferIdentifier());
359 }
360}
361
362static std::optional<std::string> findFromSearchPaths(StringRef path) {
363 for (StringRef dir : ctx.arg.searchPaths)
364 if (std::optional<std::string> s = findFile(path1: dir, path2: path))
365 return s;
366 return std::nullopt;
367}
368
369// This is for -l<basename>. We'll look for lib<basename>.a from
370// search paths.
371static std::optional<std::string> searchLibraryBaseName(StringRef name) {
372 for (StringRef dir : ctx.arg.searchPaths) {
373 if (!ctx.arg.isStatic)
374 if (std::optional<std::string> s = findFile(path1: dir, path2: "lib" + name + ".so"))
375 return s;
376 if (std::optional<std::string> s = findFile(path1: dir, path2: "lib" + name + ".a"))
377 return s;
378 }
379 return std::nullopt;
380}
381
382// This is for -l<namespec>.
383static std::optional<std::string> searchLibrary(StringRef name) {
384 if (name.starts_with(Prefix: ":"))
385 return findFromSearchPaths(path: name.substr(Start: 1));
386 return searchLibraryBaseName(name);
387}
388
389// Add a given library by searching it from input search paths.
390void LinkerDriver::addLibrary(StringRef name) {
391 if (std::optional<std::string> path = searchLibrary(name))
392 addFile(path: saver().save(S: *path));
393 else
394 error(msg: "unable to find library -l" + name, tag: ErrorTag::LibNotFound, args: {name});
395}
396
397void LinkerDriver::createFiles(opt::InputArgList &args) {
398 for (auto *arg : args) {
399 switch (arg->getOption().getID()) {
400 case OPT_library:
401 addLibrary(name: arg->getValue());
402 break;
403 case OPT_INPUT:
404 addFile(path: arg->getValue());
405 break;
406 case OPT_Bstatic:
407 ctx.arg.isStatic = true;
408 break;
409 case OPT_Bdynamic:
410 if (!ctx.arg.relocatable)
411 ctx.arg.isStatic = false;
412 break;
413 case OPT_whole_archive:
414 inWholeArchive = true;
415 break;
416 case OPT_no_whole_archive:
417 inWholeArchive = false;
418 break;
419 case OPT_start_lib:
420 if (inLib)
421 error(msg: "nested --start-lib");
422 inLib = true;
423 break;
424 case OPT_end_lib:
425 if (!inLib)
426 error(msg: "stray --end-lib");
427 inLib = false;
428 break;
429 }
430 }
431 if (files.empty() && errorCount() == 0)
432 error(msg: "no input files");
433}
434
435static StringRef getAliasSpelling(opt::Arg *arg) {
436 if (const opt::Arg *alias = arg->getAlias())
437 return alias->getSpelling();
438 return arg->getSpelling();
439}
440
441static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
442 unsigned id) {
443 auto *arg = args.getLastArg(Ids: id);
444 if (!arg)
445 return {"", ""};
446
447 StringRef s = arg->getValue();
448 std::pair<StringRef, StringRef> ret = s.split(Separator: ';');
449 if (ret.second.empty())
450 error(msg: getAliasSpelling(arg) + " expects 'old;new' format, but got " + s);
451 return ret;
452}
453
454// Parse options of the form "old;new[;extra]".
455static std::tuple<StringRef, StringRef, StringRef>
456getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) {
457 auto [oldDir, second] = getOldNewOptions(args, id);
458 auto [newDir, extraDir] = second.split(Separator: ';');
459 return {oldDir, newDir, extraDir};
460}
461
462static StringRef getEntry(opt::InputArgList &args) {
463 auto *arg = args.getLastArg(Ids: OPT_entry, Ids: OPT_no_entry);
464 if (!arg) {
465 if (args.hasArg(Ids: OPT_relocatable))
466 return "";
467 if (args.hasArg(Ids: OPT_shared))
468 return "__wasm_call_ctors";
469 return "_start";
470 }
471 if (arg->getOption().getID() == OPT_no_entry)
472 return "";
473 return arg->getValue();
474}
475
476// Determines what we should do if there are remaining unresolved
477// symbols after the name resolution.
478static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &args) {
479 UnresolvedPolicy errorOrWarn = args.hasFlag(Pos: OPT_error_unresolved_symbols,
480 Neg: OPT_warn_unresolved_symbols, Default: true)
481 ? UnresolvedPolicy::ReportError
482 : UnresolvedPolicy::Warn;
483
484 if (auto *arg = args.getLastArg(Ids: OPT_unresolved_symbols)) {
485 StringRef s = arg->getValue();
486 if (s == "ignore-all")
487 return UnresolvedPolicy::Ignore;
488 if (s == "import-dynamic")
489 return UnresolvedPolicy::ImportDynamic;
490 if (s == "report-all")
491 return errorOrWarn;
492 error(msg: "unknown --unresolved-symbols value: " + s);
493 }
494
495 return errorOrWarn;
496}
497
498// Parse --build-id or --build-id=<style>. We handle "tree" as a
499// synonym for "sha1" because all our hash functions including
500// -build-id=sha1 are actually tree hashes for performance reasons.
501static std::pair<BuildIdKind, SmallVector<uint8_t, 0>>
502getBuildId(opt::InputArgList &args) {
503 auto *arg = args.getLastArg(Ids: OPT_build_id, Ids: OPT_build_id_eq);
504 if (!arg)
505 return {BuildIdKind::None, {}};
506
507 if (arg->getOption().getID() == OPT_build_id)
508 return {BuildIdKind::Fast, {}};
509
510 StringRef s = arg->getValue();
511 if (s == "fast")
512 return {BuildIdKind::Fast, {}};
513 if (s == "sha1" || s == "tree")
514 return {BuildIdKind::Sha1, {}};
515 if (s == "uuid")
516 return {BuildIdKind::Uuid, {}};
517 if (s.starts_with(Prefix: "0x"))
518 return {BuildIdKind::Hexstring, parseHex(s: s.substr(Start: 2))};
519
520 if (s != "none")
521 error(msg: "unknown --build-id style: " + s);
522 return {BuildIdKind::None, {}};
523}
524
525// Initializes Config members by the command line options.
526static void readConfigs(opt::InputArgList &args) {
527 ctx.arg.allowMultipleDefinition =
528 hasZOption(args, key: "muldefs") ||
529 args.hasFlag(Pos: OPT_allow_multiple_definition,
530 Neg: OPT_no_allow_multiple_definition, Default: false);
531 ctx.arg.bsymbolic = args.hasArg(Ids: OPT_Bsymbolic);
532 ctx.arg.checkFeatures =
533 args.hasFlag(Pos: OPT_check_features, Neg: OPT_no_check_features, Default: true);
534 ctx.arg.compressRelocations = args.hasArg(Ids: OPT_compress_relocations);
535 ctx.arg.demangle = args.hasFlag(Pos: OPT_demangle, Neg: OPT_no_demangle, Default: true);
536 ctx.arg.disableVerify = args.hasArg(Ids: OPT_disable_verify);
537 ctx.arg.emitRelocs = args.hasArg(Ids: OPT_emit_relocs);
538 ctx.arg.entry = getEntry(args);
539 ctx.arg.exportAll = args.hasArg(Ids: OPT_export_all);
540 ctx.arg.exportTable = args.hasArg(Ids: OPT_export_table);
541 ctx.arg.growableTable = args.hasArg(Ids: OPT_growable_table);
542 ctx.arg.noinhibitExec = args.hasArg(Ids: OPT_noinhibit_exec);
543
544 if (args.hasArg(Ids: OPT_import_memory_with_name)) {
545 auto argValue = args.getLastArgValue(Id: OPT_import_memory_with_name);
546 if (argValue.contains(C: ','))
547 ctx.arg.memoryImport = argValue.split(Separator: ",");
548 else
549 ctx.arg.memoryImport = {defaultModule, argValue};
550 } else if (args.hasArg(Ids: OPT_import_memory)) {
551 ctx.arg.memoryImport = {defaultModule, memoryName};
552 }
553
554 if (args.hasArg(Ids: OPT_export_memory_with_name)) {
555 ctx.arg.memoryExport = args.getLastArgValue(Id: OPT_export_memory_with_name);
556 } else if (args.hasArg(Ids: OPT_export_memory)) {
557 ctx.arg.memoryExport = memoryName;
558 }
559
560 ctx.arg.sharedMemory = args.hasArg(Ids: OPT_shared_memory);
561 ctx.arg.soName = args.getLastArgValue(Id: OPT_soname);
562 ctx.arg.importTable = args.hasArg(Ids: OPT_import_table);
563 ctx.arg.importUndefined = args.hasArg(Ids: OPT_import_undefined);
564 ctx.arg.cooperativeThreading = args.hasArg(Ids: OPT_cooperative_threading);
565 ctx.arg.ltoo = args::getInteger(args, key: OPT_lto_O, Default: 2);
566 if (ctx.arg.ltoo > 3)
567 error(msg: "invalid optimization level for LTO: " + Twine(ctx.arg.ltoo));
568 unsigned ltoCgo =
569 args::getInteger(args, key: OPT_lto_CGO, Default: args::getCGOptLevel(optLevelLTO: ctx.arg.ltoo));
570 if (auto level = CodeGenOpt::getLevel(OL: ltoCgo))
571 ctx.arg.ltoCgo = *level;
572 else
573 error(msg: "invalid codegen optimization level for LTO: " + Twine(ltoCgo));
574 ctx.arg.ltoPartitions = args::getInteger(args, key: OPT_lto_partitions, Default: 1);
575 ctx.arg.ltoObjPath = args.getLastArgValue(Id: OPT_lto_obj_path_eq);
576 ctx.arg.ltoDebugPassManager = args.hasArg(Ids: OPT_lto_debug_pass_manager);
577 ctx.arg.mapFile = args.getLastArgValue(Id: OPT_Map);
578 ctx.arg.optimize = args::getInteger(args, key: OPT_O, Default: 1);
579 ctx.arg.outputFile = args.getLastArgValue(Id: OPT_o);
580 ctx.arg.relocatable = args.hasArg(Ids: OPT_relocatable);
581 ctx.arg.rpath = args::getStrings(args, id: OPT_rpath);
582 ctx.arg.gcSections =
583 args.hasFlag(Pos: OPT_gc_sections, Neg: OPT_no_gc_sections, Default: !ctx.arg.relocatable);
584 for (auto *arg : args.filtered(Ids: OPT_keep_section))
585 ctx.arg.keepSections.insert(key: arg->getValue());
586 ctx.arg.mergeDataSegments =
587 args.hasFlag(Pos: OPT_merge_data_segments, Neg: OPT_no_merge_data_segments,
588 Default: !ctx.arg.relocatable);
589 ctx.arg.pie = args.hasFlag(Pos: OPT_pie, Neg: OPT_no_pie, Default: false);
590 ctx.arg.printGcSections =
591 args.hasFlag(Pos: OPT_print_gc_sections, Neg: OPT_no_print_gc_sections, Default: false);
592 ctx.arg.saveTemps = args.hasArg(Ids: OPT_save_temps);
593 ctx.arg.searchPaths = args::getStrings(args, id: OPT_library_path);
594 ctx.arg.shared = args.hasArg(Ids: OPT_shared);
595 ctx.arg.shlibSigCheck = !args.hasArg(Ids: OPT_no_shlib_sigcheck);
596 ctx.arg.stripAll = args.hasArg(Ids: OPT_strip_all);
597 ctx.arg.stripDebug = args.hasArg(Ids: OPT_strip_debug);
598 ctx.arg.stackFirst = args.hasFlag(Pos: OPT_stack_first, Neg: OPT_no_stack_first, Default: true);
599 ctx.arg.trace = args.hasArg(Ids: OPT_trace);
600 ctx.arg.thinLTOCacheDir = args.getLastArgValue(Id: OPT_thinlto_cache_dir);
601 ctx.arg.thinLTOCachePolicy = CHECK(
602 parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
603 "--thinlto-cache-policy: invalid cache policy");
604 ctx.arg.thinLTOEmitImportsFiles = args.hasArg(Ids: OPT_thinlto_emit_imports_files);
605 ctx.arg.thinLTOEmitIndexFiles = args.hasArg(Ids: OPT_thinlto_emit_index_files) ||
606 args.hasArg(Ids: OPT_thinlto_index_only) ||
607 args.hasArg(Ids: OPT_thinlto_index_only_eq);
608 ctx.arg.thinLTOIndexOnly = args.hasArg(Ids: OPT_thinlto_index_only) ||
609 args.hasArg(Ids: OPT_thinlto_index_only_eq);
610 ctx.arg.thinLTOIndexOnlyArg = args.getLastArgValue(Id: OPT_thinlto_index_only_eq);
611 ctx.arg.thinLTOObjectSuffixReplace =
612 getOldNewOptions(args, id: OPT_thinlto_object_suffix_replace_eq);
613 std::tie(args&: ctx.arg.thinLTOPrefixReplaceOld, args&: ctx.arg.thinLTOPrefixReplaceNew,
614 args&: ctx.arg.thinLTOPrefixReplaceNativeObject) =
615 getOldNewOptionsExtra(args, id: OPT_thinlto_prefix_replace_eq);
616 if (ctx.arg.thinLTOEmitIndexFiles && !ctx.arg.thinLTOIndexOnly) {
617 if (args.hasArg(Ids: OPT_thinlto_object_suffix_replace_eq))
618 error(msg: "--thinlto-object-suffix-replace is not supported with "
619 "--thinlto-emit-index-files");
620 else if (args.hasArg(Ids: OPT_thinlto_prefix_replace_eq))
621 error(msg: "--thinlto-prefix-replace is not supported with "
622 "--thinlto-emit-index-files");
623 }
624 if (!ctx.arg.thinLTOPrefixReplaceNativeObject.empty() &&
625 ctx.arg.thinLTOIndexOnlyArg.empty()) {
626 error(msg: "--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
627 "--thinlto-index-only=");
628 }
629 ctx.arg.unresolvedSymbols = getUnresolvedSymbolPolicy(args);
630 ctx.arg.whyExtract = args.getLastArgValue(Id: OPT_why_extract);
631 errorHandler().verbose = args.hasArg(Ids: OPT_verbose);
632 LLVM_DEBUG(errorHandler().verbose = true);
633
634 ctx.arg.tableBase = args::getInteger(args, key: OPT_table_base, Default: 0);
635 ctx.arg.globalBase = args::getInteger(args, key: OPT_global_base, Default: 0);
636 ctx.arg.initialHeap = args::getInteger(args, key: OPT_initial_heap, Default: 0);
637 ctx.arg.initialMemory = args::getInteger(args, key: OPT_initial_memory, Default: 0);
638 ctx.arg.maxMemory = args::getInteger(args, key: OPT_max_memory, Default: 0);
639 ctx.arg.noGrowableMemory = args.hasArg(Ids: OPT_no_growable_memory);
640 ctx.arg.zStackSize =
641 args::getZOptionValue(args, id: OPT_z, key: "stack-size", Default: WasmDefaultPageSize);
642 ctx.arg.pageSize = args::getInteger(args, key: OPT_page_size, Default: WasmDefaultPageSize);
643 if (ctx.arg.pageSize != 1 && ctx.arg.pageSize != WasmDefaultPageSize)
644 error(msg: "--page_size=N must be either 1 or 65536");
645
646 // -Bdynamic by default if -pie or -shared is specified.
647 if (ctx.arg.pie || ctx.arg.shared)
648 ctx.arg.isStatic = false;
649
650 if (ctx.arg.maxMemory != 0 && ctx.arg.noGrowableMemory) {
651 // Erroring out here is simpler than defining precedence rules.
652 error(msg: "--max-memory is incompatible with --no-growable-memory");
653 }
654
655 // Default value of exportDynamic depends on `-shared`
656 ctx.arg.exportDynamic =
657 args.hasFlag(Pos: OPT_export_dynamic, Neg: OPT_no_export_dynamic, Default: ctx.arg.shared);
658
659 // Parse wasm32/64.
660 if (auto *arg = args.getLastArg(Ids: OPT_m)) {
661 StringRef s = arg->getValue();
662 if (s == "wasm32")
663 ctx.arg.is64 = false;
664 else if (s == "wasm64")
665 ctx.arg.is64 = true;
666 else
667 error(msg: "invalid target architecture: " + s);
668 }
669
670 // --threads= takes a positive integer and provides the default value for
671 // --thinlto-jobs=.
672 if (auto *arg = args.getLastArg(Ids: OPT_threads)) {
673 StringRef v(arg->getValue());
674 unsigned threads = 0;
675 if (!llvm::to_integer(S: v, Num&: threads, Base: 0) || threads == 0)
676 error(msg: arg->getSpelling() + ": expected a positive integer, but got '" +
677 arg->getValue() + "'");
678 parallel::strategy = hardware_concurrency(ThreadCount: threads);
679 ctx.arg.thinLTOJobs = v;
680 }
681 if (auto *arg = args.getLastArg(Ids: OPT_thinlto_jobs))
682 ctx.arg.thinLTOJobs = arg->getValue();
683
684 if (auto *arg = args.getLastArg(Ids: OPT_features)) {
685 ctx.arg.features =
686 std::optional<std::vector<std::string>>(std::vector<std::string>());
687 for (StringRef s : arg->getValues())
688 ctx.arg.features->push_back(x: std::string(s));
689 }
690
691 if (auto *arg = args.getLastArg(Ids: OPT_extra_features)) {
692 ctx.arg.extraFeatures =
693 std::optional<std::vector<std::string>>(std::vector<std::string>());
694 for (StringRef s : arg->getValues())
695 ctx.arg.extraFeatures->push_back(x: std::string(s));
696 }
697
698 // Legacy --allow-undefined flag which is equivalent to
699 // --unresolve-symbols=ignore + --import-undefined
700 if (args.hasArg(Ids: OPT_allow_undefined)) {
701 ctx.arg.importUndefined = true;
702 ctx.arg.unresolvedSymbols = UnresolvedPolicy::Ignore;
703 }
704
705 if (args.hasArg(Ids: OPT_print_map))
706 ctx.arg.mapFile = "-";
707
708 std::tie(args&: ctx.arg.buildId, args&: ctx.arg.buildIdVector) = getBuildId(args);
709}
710
711// Some Config members do not directly correspond to any particular
712// command line options, but computed based on other Config values.
713// This function initialize such members. See Config.h for the details
714// of these values.
715static void setConfigs() {
716 ctx.isPic = ctx.arg.pie || ctx.arg.shared;
717
718 if (ctx.isPic) {
719 if (ctx.arg.exportTable)
720 error(msg: "-shared/-pie is incompatible with --export-table");
721 ctx.arg.importTable = true;
722 } else {
723 // Default table base. Defaults to 1, reserving 0 for the NULL function
724 // pointer.
725 if (!ctx.arg.tableBase)
726 ctx.arg.tableBase = 1;
727 // The default offset for static/global data, for when --global-base is
728 // not specified on the command line. The precise value of 1024 is
729 // somewhat arbitrary, and pre-dates wasm-ld (Its the value that
730 // emscripten used prior to wasm-ld).
731 if (!ctx.arg.globalBase && !ctx.arg.relocatable && !ctx.arg.stackFirst)
732 ctx.arg.globalBase = 1024;
733 }
734
735 if (ctx.arg.relocatable) {
736 if (ctx.arg.exportTable)
737 error(msg: "--relocatable is incompatible with --export-table");
738 if (ctx.arg.growableTable)
739 error(msg: "--relocatable is incompatible with --growable-table");
740 // Ignore any --import-table, as it's redundant.
741 ctx.arg.importTable = true;
742 }
743
744 if (ctx.arg.shared) {
745 if (ctx.arg.memoryExport.has_value()) {
746 error(msg: "--export-memory is incompatible with --shared");
747 }
748 if (!ctx.arg.memoryImport.has_value()) {
749 ctx.arg.memoryImport = {defaultModule, memoryName};
750 }
751 }
752
753 // If neither export-memory nor import-memory is specified, default to
754 // exporting memory under its default name.
755 if (!ctx.arg.memoryExport.has_value() && !ctx.arg.memoryImport.has_value()) {
756 ctx.arg.memoryExport = memoryName;
757 }
758 if (ctx.arg.cooperativeThreading) {
759 if (ctx.arg.sharedMemory)
760 error(msg: "--cooperative-threading is incompatible with --shared-memory");
761 ctx.arg.libcallThreadContext = true;
762 }
763}
764
765// Some command line options or some combinations of them are not allowed.
766// This function checks for such errors.
767static void checkOptions(opt::InputArgList &args) {
768 if (!ctx.arg.stripDebug && !ctx.arg.stripAll && ctx.arg.compressRelocations)
769 error(msg: "--compress-relocations is incompatible with output debug"
770 " information. Please pass --strip-debug or --strip-all");
771
772 if (ctx.arg.ltoPartitions == 0)
773 error(msg: "--lto-partitions: number of threads must be > 0");
774 if (!get_threadpool_strategy(Num: ctx.arg.thinLTOJobs))
775 error(msg: "--thinlto-jobs: invalid job count: " + ctx.arg.thinLTOJobs);
776
777 if (ctx.arg.pie && ctx.arg.shared)
778 error(msg: "-shared and -pie may not be used together");
779
780 if (ctx.arg.outputFile.empty() && !ctx.arg.thinLTOIndexOnly)
781 error(msg: "no output file specified");
782
783 if (ctx.arg.importTable && ctx.arg.exportTable)
784 error(msg: "--import-table and --export-table may not be used together");
785
786 if (ctx.arg.relocatable) {
787 if (!ctx.arg.entry.empty())
788 error(msg: "entry point specified for relocatable output file");
789 if (ctx.arg.gcSections)
790 error(msg: "-r and --gc-sections may not be used together");
791 if (ctx.arg.compressRelocations)
792 error(msg: "-r -and --compress-relocations may not be used together");
793 if (args.hasArg(Ids: OPT_undefined))
794 error(msg: "-r -and --undefined may not be used together");
795 if (ctx.arg.pie)
796 error(msg: "-r and -pie may not be used together");
797 if (ctx.arg.sharedMemory)
798 error(msg: "-r and --shared-memory may not be used together");
799 if (ctx.arg.globalBase)
800 error(msg: "-r and --global-base may not by used together");
801 }
802
803 if (ctx.arg.bsymbolic && !ctx.arg.shared) {
804 warn(msg: "-Bsymbolic is only meaningful when combined with -shared");
805 }
806
807 if (ctx.isPic) {
808 if (ctx.arg.globalBase)
809 error(msg: "--global-base may not be used with -shared/-pie");
810 if (ctx.arg.tableBase)
811 error(msg: "--table-base may not be used with -shared/-pie");
812 }
813}
814
815static const char *getReproduceOption(opt::InputArgList &args) {
816 if (auto *arg = args.getLastArg(Ids: OPT_reproduce))
817 return arg->getValue();
818 return getenv(name: "LLD_REPRODUCE");
819}
820
821// Force Sym to be entered in the output. Used for -u or equivalent.
822static Symbol *handleUndefined(StringRef name, const char *option) {
823 Symbol *sym = symtab->find(name);
824 if (!sym)
825 return nullptr;
826
827 // Since symbol S may not be used inside the program, LTO may
828 // eliminate it. Mark the symbol as "used" to prevent it.
829 sym->isUsedInRegularObj = true;
830
831 if (auto *lazySym = dyn_cast<LazySymbol>(Val: sym)) {
832 lazySym->extract();
833 if (!ctx.arg.whyExtract.empty())
834 ctx.whyExtractRecords.emplace_back(Args&: option, Args: sym->getFile(), Args&: *sym);
835 }
836
837 return sym;
838}
839
840static void handleLibcall(StringRef name) {
841 Symbol *sym = symtab->find(name);
842 if (sym && sym->isLazy() && isa<BitcodeFile>(Val: sym->getFile())) {
843 if (!ctx.arg.whyExtract.empty())
844 ctx.whyExtractRecords.emplace_back(Args: "<libcall>", Args: sym->getFile(), Args&: *sym);
845 cast<LazySymbol>(Val: sym)->extract();
846 }
847}
848
849static void writeWhyExtract() {
850 if (ctx.arg.whyExtract.empty())
851 return;
852
853 std::error_code ec;
854 raw_fd_ostream os(ctx.arg.whyExtract, ec, sys::fs::OF_None);
855 if (ec) {
856 error(msg: "cannot open --why-extract= file " + ctx.arg.whyExtract + ": " +
857 ec.message());
858 return;
859 }
860
861 os << "reference\textracted\tsymbol\n";
862 for (auto &entry : ctx.whyExtractRecords) {
863 os << std::get<0>(t&: entry) << '\t' << toString(file: std::get<1>(t&: entry)) << '\t'
864 << toString(sym: std::get<2>(t&: entry)) << '\n';
865 }
866}
867
868// Equivalent of demote demoteSharedAndLazySymbols() in the ELF linker
869static void demoteLazySymbols() {
870 for (Symbol *sym : symtab->symbols()) {
871 if (auto *s = dyn_cast<LazySymbol>(Val: sym)) {
872 if (s->signature) {
873 LLVM_DEBUG(llvm::dbgs()
874 << "demoting lazy func: " << s->getName() << "\n");
875 replaceSymbol<UndefinedFunction>(s, arg: s->getName(), arg: std::nullopt,
876 arg: std::nullopt, arg: WASM_SYMBOL_BINDING_WEAK,
877 arg: s->getFile(), arg&: s->signature);
878 }
879 }
880 }
881}
882
883static UndefinedGlobal *
884createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
885 auto *sym = cast<UndefinedGlobal>(Val: symtab->addUndefinedGlobal(
886 name, importName: std::nullopt, importModule: std::nullopt, flags: WASM_SYMBOL_UNDEFINED, file: nullptr, type));
887 ctx.arg.allowUndefinedSymbols.insert(key: sym->getName());
888 sym->isUsedInRegularObj = true;
889 return sym;
890}
891
892static UndefinedFunction *createUndefinedFunction(StringRef name,
893 WasmSignature *signature) {
894 auto *sym = cast<UndefinedFunction>(Val: symtab->addUndefinedFunction(
895 name, importName: std::nullopt, importModule: std::nullopt, flags: WASM_SYMBOL_UNDEFINED, file: nullptr,
896 signature, isCalledDirectly: true));
897 ctx.arg.allowUndefinedSymbols.insert(key: sym->getName());
898 sym->isUsedInRegularObj = true;
899 return sym;
900}
901
902static InputGlobal *createGlobal(StringRef name, bool isMutable) {
903 llvm::wasm::WasmGlobal wasmGlobal;
904 bool is64 = ctx.arg.is64.value_or(u: false);
905 wasmGlobal.Type = {.Type: uint8_t(is64 ? WASM_TYPE_I64 : WASM_TYPE_I32), .Mutable: isMutable};
906 wasmGlobal.InitExpr = intConst(value: 0, is64);
907 wasmGlobal.SymbolName = name;
908 return make<InputGlobal>(args&: wasmGlobal, args: nullptr);
909}
910
911static DefinedGlobal *createGlobalVariable(StringRef name, bool isMutable,
912 uint32_t flags = 0) {
913 InputGlobal *g = createGlobal(name, isMutable);
914 return symtab->addSyntheticGlobal(name, flags, global: g);
915}
916
917static DefinedGlobal *createOptionalGlobal(StringRef name, bool isMutable) {
918 InputGlobal *g = createGlobal(name, isMutable);
919 return symtab->addOptionalGlobalSymbol(name, global: g);
920}
921
922// Create ABI-defined synthetic symbols
923static void createSyntheticSymbols() {
924 if (ctx.arg.relocatable)
925 return;
926
927 static WasmSignature nullSignature = {{}, {}};
928 static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
929 static WasmSignature i64ArgSignature = {{}, {ValType::I64}};
930 static llvm::wasm::WasmGlobalType globalTypeI32 = {.Type: WASM_TYPE_I32, .Mutable: false};
931 static llvm::wasm::WasmGlobalType globalTypeI64 = {.Type: WASM_TYPE_I64, .Mutable: false};
932 static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {.Type: WASM_TYPE_I32,
933 .Mutable: true};
934 static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {.Type: WASM_TYPE_I64,
935 .Mutable: true};
936
937 ctx.sym.callCtors = symtab->addSyntheticFunction(
938 name: "__wasm_call_ctors", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
939 function: make<SyntheticFunction>(args&: nullSignature, args: "__wasm_call_ctors"));
940
941 bool is64 = ctx.arg.is64.value_or(u: false);
942
943 auto stack_pointer_name =
944 ctx.arg.libcallThreadContext ? "__init_stack_pointer" : "__stack_pointer";
945 if (ctx.isPic) {
946 if (ctx.arg.libcallThreadContext) {
947 ctx.sym.stackPointer = createUndefinedGlobal(
948 name: stack_pointer_name,
949 type: ctx.arg.is64.value_or(u: false) ? &globalTypeI64 : &globalTypeI32);
950 } else {
951 ctx.sym.stackPointer = createUndefinedGlobal(name: stack_pointer_name,
952 type: ctx.arg.is64.value_or(u: false)
953 ? &mutableGlobalTypeI64
954 : &mutableGlobalTypeI32);
955 }
956 // For PIC code, we import two global variables (__memory_base and
957 // __table_base) from the environment and use these as the offset at
958 // which to load our static data and function table.
959 // See:
960 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
961 auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32;
962 ctx.sym.memoryBase = createUndefinedGlobal(name: "__memory_base", type: globalType);
963 ctx.sym.tableBase = createUndefinedGlobal(name: "__table_base", type: globalType);
964 ctx.sym.memoryBase->markLive();
965 ctx.sym.tableBase->markLive();
966 } else {
967 // For non-PIC code
968 ctx.sym.stackPointer =
969 createGlobalVariable(name: stack_pointer_name, isMutable: !ctx.arg.libcallThreadContext);
970 }
971
972 if (ctx.arg.isMultithreaded()) {
973 // TLS symbols are all hidden/dso-local
974 auto tls_base_name =
975 ctx.arg.libcallThreadContext ? "__init_tls_base" : "__tls_base";
976 ctx.sym.tlsBase =
977 createGlobalVariable(name: tls_base_name, isMutable: !ctx.arg.libcallThreadContext,
978 flags: WASM_SYMBOL_VISIBILITY_HIDDEN);
979 ctx.sym.tlsSize = createGlobalVariable(name: "__tls_size", isMutable: false,
980 flags: WASM_SYMBOL_VISIBILITY_HIDDEN);
981 ctx.sym.tlsAlign = createGlobalVariable(name: "__tls_align", isMutable: false,
982 flags: WASM_SYMBOL_VISIBILITY_HIDDEN);
983 ctx.sym.initTLS = symtab->addSyntheticFunction(
984 name: "__wasm_init_tls", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
985 function: make<SyntheticFunction>(args&: is64 ? i64ArgSignature : i32ArgSignature,
986 args: "__wasm_init_tls"));
987 if (ctx.arg.libcallThreadContext) {
988 ctx.sym.tlsBase->markLive();
989 ctx.sym.tlsSize->markLive();
990 ctx.sym.tlsAlign->markLive();
991 static WasmSignature setTLSBaseSignature{{}, {ValType::I32}};
992 ctx.sym.setTLSBase =
993 createUndefinedFunction(name: "__wasm_set_tls_base", signature: &setTLSBaseSignature);
994 ctx.sym.setTLSBase->markLive();
995 static WasmSignature getTLSBaseSignature{{ValType::I32}, {}};
996 ctx.sym.getTLSBase =
997 createUndefinedFunction(name: "__wasm_get_tls_base", signature: &getTLSBaseSignature);
998 ctx.sym.getTLSBase->markLive();
999 }
1000 }
1001}
1002
1003static void createOptionalSymbols() {
1004 if (ctx.arg.relocatable)
1005 return;
1006
1007 ctx.sym.dsoHandle = symtab->addOptionalDataSymbol(name: "__dso_handle");
1008
1009 if (!ctx.arg.shared) {
1010 ctx.sym.dataEnd = symtab->addOptionalDataSymbol(name: "__data_end");
1011 ctx.sym.rodataStart = symtab->addOptionalDataSymbol(name: "__rodata_start");
1012 ctx.sym.rodataEnd = symtab->addOptionalDataSymbol(name: "__rodata_end");
1013 }
1014
1015 if (!ctx.isPic) {
1016 ctx.sym.stackLow = symtab->addOptionalDataSymbol(name: "__stack_low");
1017 ctx.sym.stackHigh = symtab->addOptionalDataSymbol(name: "__stack_high");
1018 ctx.sym.globalBase = symtab->addOptionalDataSymbol(name: "__global_base");
1019 ctx.sym.heapBase = symtab->addOptionalDataSymbol(name: "__heap_base");
1020 ctx.sym.heapEnd = symtab->addOptionalDataSymbol(name: "__heap_end");
1021 ctx.sym.memoryBase = createOptionalGlobal(name: "__memory_base", isMutable: false);
1022 ctx.sym.tableBase = createOptionalGlobal(name: "__table_base", isMutable: false);
1023 }
1024
1025 ctx.sym.firstPageEnd = symtab->addOptionalDataSymbol(name: "__wasm_first_page_end");
1026 if (ctx.sym.firstPageEnd)
1027 ctx.sym.firstPageEnd->setVA(ctx.arg.pageSize);
1028
1029 // TLS object files may be linked into single-threaded programs, so
1030 // __tls_base must always be defined. In this case it is immutable and points
1031 // directly to the start of the `.tdata` segment. __tls_size and __tls_align
1032 // are omitted since they are only used by __wasm_init_tls, which is not
1033 // created in this case.
1034 if (!ctx.sym.tlsBase)
1035 ctx.sym.tlsBase = createOptionalGlobal(name: "__tls_base", isMutable: false);
1036}
1037
1038static void processStubLibrariesPreLTO() {
1039 log(msg: "-- processStubLibrariesPreLTO");
1040 for (auto &stub_file : ctx.stubFiles) {
1041 LLVM_DEBUG(llvm::dbgs()
1042 << "processing stub file: " << stub_file->getName() << "\n");
1043 for (auto [name, deps] : stub_file->symbolDependencies) {
1044 auto *sym = symtab->find(name);
1045 // If the symbol is not present at all (yet), or if it is present but
1046 // undefined, then mark the dependent symbols as used by a regular
1047 // object so they will be preserved and exported by the LTO process.
1048 if (!sym || sym->isUndefined()) {
1049 for (const auto dep : deps) {
1050 auto *needed = symtab->find(name: dep);
1051 if (needed) {
1052 needed->isUsedInRegularObj = true;
1053 // Like with handleLibcall we have to extract any LTO archive
1054 // members that might need to be exported due to stub library
1055 // symbols being referenced. Without this the LTO object could be
1056 // extracted during processStubLibraries, which is too late since
1057 // LTO has already being performed at that point.
1058 if (needed->isLazy() && isa<BitcodeFile>(Val: needed->getFile())) {
1059 if (!ctx.arg.whyExtract.empty())
1060 ctx.whyExtractRecords.emplace_back(Args: toString(file: stub_file),
1061 Args: needed->getFile(), Args&: *needed);
1062 cast<LazySymbol>(Val: needed)->extract();
1063 }
1064 }
1065 }
1066 }
1067 }
1068 }
1069}
1070
1071static bool addStubSymbolDeps(const StubFile *stub_file, Symbol *sym,
1072 ArrayRef<StringRef> deps) {
1073 // The first stub library to define a given symbol sets this and
1074 // definitions in later stub libraries are ignored.
1075 if (sym->forceImport)
1076 return false; // Already handled
1077 sym->forceImport = true;
1078 if (sym->traced)
1079 message(msg: toString(file: stub_file) + ": importing " + sym->getName());
1080 else
1081 LLVM_DEBUG(llvm::dbgs() << toString(stub_file) << ": importing "
1082 << sym->getName() << "\n");
1083 bool depsAdded = false;
1084 for (const auto dep : deps) {
1085 auto *needed = symtab->find(name: dep);
1086 if (!needed) {
1087 error(msg: toString(file: stub_file) + ": undefined symbol: " + dep +
1088 ". Required by " + toString(sym: *sym));
1089 } else if (needed->isUndefined()) {
1090 error(msg: toString(file: stub_file) + ": undefined symbol: " + toString(sym: *needed) +
1091 ". Required by " + toString(sym: *sym));
1092 } else {
1093 if (needed->traced)
1094 message(msg: toString(file: stub_file) + ": exported " + toString(sym: *needed) +
1095 " due to import of " + sym->getName());
1096 else
1097 LLVM_DEBUG(llvm::dbgs()
1098 << "force export: " << toString(*needed) << "\n");
1099 needed->forceExport = true;
1100 if (auto *lazy = dyn_cast<LazySymbol>(Val: needed)) {
1101 depsAdded = true;
1102 lazy->extract();
1103 if (!ctx.arg.whyExtract.empty())
1104 ctx.whyExtractRecords.emplace_back(Args: toString(file: stub_file),
1105 Args: sym->getFile(), Args&: *sym);
1106 }
1107 }
1108 }
1109 return depsAdded;
1110}
1111
1112static void processStubLibraries() {
1113 log(msg: "-- processStubLibraries");
1114 bool depsAdded = false;
1115 do {
1116 depsAdded = false;
1117 for (auto &stub_file : ctx.stubFiles) {
1118 LLVM_DEBUG(llvm::dbgs()
1119 << "processing stub file: " << stub_file->getName() << "\n");
1120
1121 // First look for any imported symbols that directly match
1122 // the names of the stub imports
1123 for (auto [name, deps] : stub_file->symbolDependencies) {
1124 auto *sym = symtab->find(name);
1125 if (sym && sym->isUndefined() && sym->isUsedInRegularObj) {
1126 depsAdded |= addStubSymbolDeps(stub_file, sym, deps);
1127 } else {
1128 if (sym && sym->traced)
1129 message(msg: toString(file: stub_file) + ": stub symbol not needed: " + name);
1130 else
1131 LLVM_DEBUG(llvm::dbgs()
1132 << "stub symbol not needed: `" << name << "`\n");
1133 }
1134 }
1135
1136 // Secondly looks for any symbols with an `importName` that matches
1137 for (Symbol *sym : symtab->symbols()) {
1138 if (sym->isUndefined() && sym->importName.has_value()) {
1139 auto it = stub_file->symbolDependencies.find(Val: sym->importName.value());
1140 if (it != stub_file->symbolDependencies.end()) {
1141 depsAdded |= addStubSymbolDeps(stub_file, sym, deps: it->second);
1142 }
1143 }
1144 }
1145 }
1146 } while (depsAdded);
1147
1148 log(msg: "-- done processStubLibraries");
1149}
1150
1151// Reconstructs command line arguments so that so that you can re-run
1152// the same command with the same inputs. This is for --reproduce.
1153static std::string createResponseFile(const opt::InputArgList &args) {
1154 SmallString<0> data;
1155 raw_svector_ostream os(data);
1156
1157 // Copy the command line to the output while rewriting paths.
1158 for (auto *arg : args) {
1159 switch (arg->getOption().getID()) {
1160 case OPT_reproduce:
1161 break;
1162 case OPT_INPUT:
1163 os << quote(s: relativeToRoot(path: arg->getValue())) << "\n";
1164 break;
1165 case OPT_o:
1166 // If -o path contains directories, "lld @response.txt" will likely
1167 // fail because the archive we are creating doesn't contain empty
1168 // directories for the output path (-o doesn't create directories).
1169 // Strip directories to prevent the issue.
1170 os << "-o " << quote(s: sys::path::filename(path: arg->getValue())) << "\n";
1171 break;
1172 default:
1173 os << toString(arg: *arg) << "\n";
1174 }
1175 }
1176 return std::string(data);
1177}
1178
1179// The --wrap option is a feature to rename symbols so that you can write
1180// wrappers for existing functions. If you pass `-wrap=foo`, all
1181// occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
1182// expected to write `wrap_foo` function as a wrapper). The original
1183// symbol becomes accessible as `real_foo`, so you can call that from your
1184// wrapper.
1185//
1186// This data structure is instantiated for each -wrap option.
1187struct WrappedSymbol {
1188 Symbol *sym;
1189 Symbol *real;
1190 Symbol *wrap;
1191};
1192
1193static Symbol *addUndefined(StringRef name,
1194 const WasmSignature *signature = nullptr) {
1195 return symtab->addUndefinedFunction(name, importName: std::nullopt, importModule: std::nullopt,
1196 flags: WASM_SYMBOL_UNDEFINED, file: nullptr, signature,
1197 isCalledDirectly: false);
1198}
1199
1200// Handles -wrap option.
1201//
1202// This function instantiates wrapper symbols. At this point, they seem
1203// like they are not being used at all, so we explicitly set some flags so
1204// that LTO won't eliminate them.
1205static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
1206 std::vector<WrappedSymbol> v;
1207 DenseSet<StringRef> seen;
1208
1209 for (auto *arg : args.filtered(Ids: OPT_wrap)) {
1210 StringRef name = arg->getValue();
1211 if (!seen.insert(V: name).second)
1212 continue;
1213
1214 Symbol *sym = symtab->find(name);
1215 if (!sym)
1216 continue;
1217
1218 Symbol *real = addUndefined(name: saver().save(S: "__real_" + name));
1219 Symbol *wrap =
1220 addUndefined(name: saver().save(S: "__wrap_" + name), signature: sym->getSignature());
1221 v.push_back(x: {.sym: sym, .real: real, .wrap: wrap});
1222
1223 // We want to tell LTO not to inline symbols to be overwritten
1224 // because LTO doesn't know the final symbol contents after renaming.
1225 real->canInline = false;
1226 sym->canInline = false;
1227
1228 // Tell LTO not to eliminate these symbols.
1229 sym->isUsedInRegularObj = true;
1230 wrap->isUsedInRegularObj = true;
1231 real->isUsedInRegularObj = false;
1232 }
1233 return v;
1234}
1235
1236// Do renaming for -wrap by updating pointers to symbols.
1237//
1238// When this function is executed, only InputFiles and symbol table
1239// contain pointers to symbol objects. We visit them to replace pointers,
1240// so that wrapped symbols are swapped as instructed by the command line.
1241static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
1242 DenseMap<Symbol *, Symbol *> map;
1243 for (const WrappedSymbol &w : wrapped) {
1244 map[w.sym] = w.wrap;
1245 map[w.real] = w.sym;
1246 }
1247
1248 // Update pointers in input files.
1249 parallelForEach(R&: ctx.objectFiles, Fn: [&](InputFile *file) {
1250 MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
1251 for (Symbol *&sym : syms)
1252 if (Symbol *s = map.lookup(Val: sym))
1253 sym = s;
1254 });
1255
1256 // Update pointers in the symbol table.
1257 for (const WrappedSymbol &w : wrapped)
1258 symtab->wrap(sym: w.sym, real: w.real, wrap: w.wrap);
1259}
1260
1261static void splitSections() {
1262 // splitIntoPieces needs to be called on each MergeInputChunk
1263 // before calling finalizeContents().
1264 LLVM_DEBUG(llvm::dbgs() << "splitSections\n");
1265 parallelForEach(R&: ctx.objectFiles, Fn: [](ObjFile *file) {
1266 for (InputChunk *seg : file->segments) {
1267 if (auto *s = dyn_cast<MergeInputChunk>(Val: seg))
1268 s->splitIntoPieces();
1269 }
1270 for (InputChunk *sec : file->customSections) {
1271 if (auto *s = dyn_cast<MergeInputChunk>(Val: sec))
1272 s->splitIntoPieces();
1273 }
1274 });
1275}
1276
1277static bool isKnownZFlag(StringRef s) {
1278 // For now, we only support a very limited set of -z flags
1279 return s.starts_with(Prefix: "stack-size=") || s.starts_with(Prefix: "muldefs");
1280}
1281
1282// Report a warning for an unknown -z option.
1283static void checkZOptions(opt::InputArgList &args) {
1284 for (auto *arg : args.filtered(Ids: OPT_z))
1285 if (!isKnownZFlag(s: arg->getValue()))
1286 warn(msg: "unknown -z value: " + StringRef(arg->getValue()));
1287}
1288
1289LinkerDriver::LinkerDriver(Ctx &ctx) : ctx(ctx) {}
1290
1291void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
1292 WasmOptTable parser;
1293 opt::InputArgList args = parser.parse(argv: argsArr.slice(N: 1));
1294
1295 // Interpret these flags early because error()/warn() depend on them.
1296 auto &errHandler = errorHandler();
1297 errHandler.errorLimit = args::getInteger(args, key: OPT_error_limit, Default: 20);
1298 errHandler.fatalWarnings =
1299 args.hasFlag(Pos: OPT_fatal_warnings, Neg: OPT_no_fatal_warnings, Default: false);
1300 checkZOptions(args);
1301
1302 // Handle --help
1303 if (args.hasArg(Ids: OPT_help)) {
1304 parser.printHelp(OS&: errHandler.outs(),
1305 Usage: (std::string(argsArr[0]) + " [options] file...").c_str(),
1306 Title: "LLVM Linker", ShowHidden: false);
1307 return;
1308 }
1309
1310 // Handle -v or -version.
1311 if (args.hasArg(Ids: OPT_v) || args.hasArg(Ids: OPT_version))
1312 errHandler.outs() << getLLDVersion() << "\n";
1313
1314 // Handle --reproduce
1315 if (const char *path = getReproduceOption(args)) {
1316 Expected<std::unique_ptr<TarWriter>> errOrWriter =
1317 TarWriter::create(OutputPath: path, BaseDir: path::stem(path));
1318 if (errOrWriter) {
1319 tar = std::move(*errOrWriter);
1320 tar->append(Path: "response.txt", Data: createResponseFile(args));
1321 tar->append(Path: "version.txt", Data: getLLDVersion() + "\n");
1322 } else {
1323 error(msg: "--reproduce: " + toString(E: errOrWriter.takeError()));
1324 }
1325 }
1326
1327 // Parse and evaluate -mllvm options.
1328 std::vector<const char *> v;
1329 v.push_back(x: "wasm-ld (LLVM option parsing)");
1330 for (auto *arg : args.filtered(Ids: OPT_mllvm))
1331 v.push_back(x: arg->getValue());
1332 cl::ResetAllOptionOccurrences();
1333 cl::ParseCommandLineOptions(argc: v.size(), argv: v.data());
1334
1335 readConfigs(args);
1336 setConfigs();
1337
1338 // The behavior of -v or --version is a bit strange, but this is
1339 // needed for compatibility with GNU linkers.
1340 if (args.hasArg(Ids: OPT_v) && !args.hasArg(Ids: OPT_INPUT))
1341 return;
1342 if (args.hasArg(Ids: OPT_version))
1343 return;
1344
1345 createFiles(args);
1346 if (errorCount())
1347 return;
1348
1349 checkOptions(args);
1350 if (errorCount())
1351 return;
1352
1353 if (auto *arg = args.getLastArg(Ids: OPT_allow_undefined_file))
1354 readImportFile(filename: arg->getValue());
1355
1356 // Fail early if the output file or map file is not writable. If a user has a
1357 // long link, e.g. due to a large LTO link, they do not wish to run it and
1358 // find that it failed because there was a mistake in their command-line.
1359 if (auto e = tryCreateFile(path: ctx.arg.outputFile))
1360 error(msg: "cannot open output file " + ctx.arg.outputFile + ": " + e.message());
1361 if (auto e = tryCreateFile(path: ctx.arg.mapFile))
1362 error(msg: "cannot open map file " + ctx.arg.mapFile + ": " + e.message());
1363 if (errorCount())
1364 return;
1365
1366 // Handle --trace-symbol.
1367 for (auto *arg : args.filtered(Ids: OPT_trace_symbol))
1368 symtab->trace(name: arg->getValue());
1369
1370 for (auto *arg : args.filtered(Ids: OPT_export_if_defined))
1371 ctx.arg.exportedSymbols.insert(key: arg->getValue());
1372
1373 for (auto *arg : args.filtered(Ids: OPT_export)) {
1374 ctx.arg.exportedSymbols.insert(key: arg->getValue());
1375 ctx.arg.requiredExports.push_back(x: arg->getValue());
1376 }
1377
1378 createSyntheticSymbols();
1379
1380 // Add all files to the symbol table. This will add almost all
1381 // symbols that we need to the symbol table.
1382 for (InputFile *f : files)
1383 symtab->addFile(file: f);
1384 if (errorCount())
1385 return;
1386
1387 // Handle the `--undefined <sym>` options.
1388 for (auto *arg : args.filtered(Ids: OPT_undefined))
1389 handleUndefined(name: arg->getValue(), option: "<internal>");
1390
1391 // Handle the `--export <sym>` options
1392 // This works like --undefined but also exports the symbol if its found
1393 for (auto &iter : ctx.arg.exportedSymbols)
1394 handleUndefined(name: iter.first(), option: "--export");
1395
1396 Symbol *entrySym = nullptr;
1397 if (!ctx.arg.relocatable && !ctx.arg.entry.empty()) {
1398 entrySym = handleUndefined(name: ctx.arg.entry, option: "--entry");
1399 if (entrySym && entrySym->isDefined())
1400 entrySym->forceExport = true;
1401 else
1402 error(msg: "entry symbol not defined (pass --no-entry to suppress): " +
1403 ctx.arg.entry);
1404 }
1405
1406 // If the user code defines a `__wasm_call_dtors` function, remember it so
1407 // that we can call it from the command export wrappers. Unlike
1408 // `__wasm_call_ctors` which we synthesize, `__wasm_call_dtors` is defined
1409 // by libc/etc., because destructors are registered dynamically with
1410 // `__cxa_atexit` and friends.
1411 if (!ctx.arg.relocatable && !ctx.arg.shared &&
1412 !ctx.sym.callCtors->isUsedInRegularObj &&
1413 ctx.sym.callCtors->getName() != ctx.arg.entry &&
1414 !ctx.arg.exportedSymbols.contains(key: ctx.sym.callCtors->getName())) {
1415 if (Symbol *callDtors =
1416 handleUndefined(name: "__wasm_call_dtors", option: "<internal>")) {
1417 if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(Val: callDtors)) {
1418 if (callDtorsFunc->signature &&
1419 (!callDtorsFunc->signature->Params.empty() ||
1420 !callDtorsFunc->signature->Returns.empty())) {
1421 error(msg: "__wasm_call_dtors must have no argument or return values");
1422 }
1423 ctx.sym.callDtors = callDtorsFunc;
1424 } else {
1425 error(msg: "__wasm_call_dtors must be a function");
1426 }
1427 }
1428 }
1429
1430 if (errorCount())
1431 return;
1432
1433 // Create wrapped symbols for -wrap option.
1434 std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
1435
1436 // If any of our inputs are bitcode files, the LTO code generator may create
1437 // references to certain library functions that might not be explicit in the
1438 // bitcode file's symbol table. If any of those library functions are defined
1439 // in a bitcode file in an archive member, we need to arrange to use LTO to
1440 // compile those archive members by adding them to the link beforehand.
1441 //
1442 // We only need to add libcall symbols to the link before LTO if the symbol's
1443 // definition is in bitcode. Any other required libcall symbols will be added
1444 // to the link after LTO when we add the LTO object file to the link.
1445 if (!ctx.bitcodeFiles.empty()) {
1446 llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple());
1447 for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
1448 handleLibcall(name: s);
1449 }
1450 if (errorCount())
1451 return;
1452
1453 // We process the stub libraries once beofore LTO to ensure that any possible
1454 // required exports are preserved by the LTO process.
1455 processStubLibrariesPreLTO();
1456
1457 // Do link-time optimization if given files are LLVM bitcode files.
1458 // This compiles bitcode files into real object files.
1459 symtab->compileBitcodeFiles();
1460 if (errorCount())
1461 return;
1462
1463 // The LTO process can generate new undefined symbols, specifically libcall
1464 // functions. Because those symbols might be declared in a stub library we
1465 // need the process the stub libraries once again after LTO to handle all
1466 // undefined symbols, including ones that didn't exist prior to LTO.
1467 processStubLibraries();
1468
1469 writeWhyExtract();
1470
1471 // Bail out if normal linked output is skipped due to LTO.
1472 if (ctx.arg.thinLTOIndexOnly)
1473 return;
1474
1475 createOptionalSymbols();
1476
1477 // Resolve any variant symbols that were created due to signature
1478 // mismatchs.
1479 symtab->handleSymbolVariants();
1480 if (errorCount())
1481 return;
1482
1483 // Apply symbol renames for -wrap.
1484 if (!wrapped.empty())
1485 wrapSymbols(wrapped);
1486
1487 for (auto &iter : ctx.arg.exportedSymbols) {
1488 Symbol *sym = symtab->find(name: iter.first());
1489 if (sym && sym->isDefined())
1490 sym->forceExport = true;
1491 }
1492
1493 if (!ctx.arg.relocatable && !ctx.isPic) {
1494 // Add synthetic dummies for weak undefined functions. Must happen
1495 // after LTO otherwise functions may not yet have signatures.
1496 symtab->handleWeakUndefines();
1497 }
1498
1499 if (entrySym)
1500 entrySym->setHidden(false);
1501
1502 if (errorCount())
1503 return;
1504
1505 // Split WASM_SEG_FLAG_STRINGS sections into pieces in preparation for garbage
1506 // collection.
1507 splitSections();
1508
1509 // Any remaining lazy symbols should be demoted to Undefined
1510 demoteLazySymbols();
1511
1512 // Do size optimizations: garbage collection
1513 markLive();
1514
1515 // Provide the indirect function table if needed.
1516 ctx.sym.indirectFunctionTable =
1517 symtab->resolveIndirectFunctionTable(/*required =*/false);
1518
1519 if (errorCount())
1520 return;
1521
1522 // Write the result to the file.
1523 writeResult();
1524}
1525
1526} // namespace lld::wasm
1527