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 // Cooperative threading requires the table is either imported or exported
764 // or otherwise there's no way for embedders to read spawned functions from
765 // the table. If we've gotten this far and the table isn't otherwise
766 // imported (e.g in `isPic` mode) then export the table instead to ensure
767 // that it's visible to the outside world.
768 if (!ctx.arg.importTable)
769 ctx.arg.exportTable = true;
770 }
771}
772
773// Some command line options or some combinations of them are not allowed.
774// This function checks for such errors.
775static void checkOptions(opt::InputArgList &args) {
776 if (!ctx.arg.stripDebug && !ctx.arg.stripAll && ctx.arg.compressRelocations)
777 error(msg: "--compress-relocations is incompatible with output debug"
778 " information. Please pass --strip-debug or --strip-all");
779
780 if (ctx.arg.ltoPartitions == 0)
781 error(msg: "--lto-partitions: number of threads must be > 0");
782 if (!get_threadpool_strategy(Num: ctx.arg.thinLTOJobs))
783 error(msg: "--thinlto-jobs: invalid job count: " + ctx.arg.thinLTOJobs);
784
785 if (ctx.arg.pie && ctx.arg.shared)
786 error(msg: "-shared and -pie may not be used together");
787
788 if (ctx.arg.outputFile.empty() && !ctx.arg.thinLTOIndexOnly)
789 error(msg: "no output file specified");
790
791 if (ctx.arg.importTable && ctx.arg.exportTable)
792 error(msg: "--import-table and --export-table may not be used together");
793
794 if (ctx.arg.relocatable) {
795 if (!ctx.arg.entry.empty())
796 error(msg: "entry point specified for relocatable output file");
797 if (ctx.arg.gcSections)
798 error(msg: "-r and --gc-sections may not be used together");
799 if (ctx.arg.compressRelocations)
800 error(msg: "-r -and --compress-relocations may not be used together");
801 if (args.hasArg(Ids: OPT_undefined))
802 error(msg: "-r -and --undefined may not be used together");
803 if (ctx.arg.pie)
804 error(msg: "-r and -pie may not be used together");
805 if (ctx.arg.sharedMemory)
806 error(msg: "-r and --shared-memory may not be used together");
807 if (ctx.arg.globalBase)
808 error(msg: "-r and --global-base may not by used together");
809 }
810
811 if (ctx.arg.bsymbolic && !ctx.arg.shared) {
812 warn(msg: "-Bsymbolic is only meaningful when combined with -shared");
813 }
814
815 if (ctx.isPic) {
816 if (ctx.arg.globalBase)
817 error(msg: "--global-base may not be used with -shared/-pie");
818 if (ctx.arg.tableBase)
819 error(msg: "--table-base may not be used with -shared/-pie");
820 }
821}
822
823static const char *getReproduceOption(opt::InputArgList &args) {
824 if (auto *arg = args.getLastArg(Ids: OPT_reproduce))
825 return arg->getValue();
826 return getenv(name: "LLD_REPRODUCE");
827}
828
829// Force Sym to be entered in the output. Used for -u or equivalent.
830static Symbol *handleUndefined(StringRef name, const char *option) {
831 Symbol *sym = symtab->find(name);
832 if (!sym)
833 return nullptr;
834
835 // Since symbol S may not be used inside the program, LTO may
836 // eliminate it. Mark the symbol as "used" to prevent it.
837 sym->isUsedInRegularObj = true;
838
839 if (auto *lazySym = dyn_cast<LazySymbol>(Val: sym)) {
840 lazySym->extract();
841 if (!ctx.arg.whyExtract.empty())
842 ctx.whyExtractRecords.emplace_back(Args&: option, Args: sym->getFile(), Args&: *sym);
843 }
844
845 return sym;
846}
847
848static void handleLibcall(StringRef name) {
849 Symbol *sym = symtab->find(name);
850 if (sym && sym->isLazy() && isa<BitcodeFile>(Val: sym->getFile())) {
851 if (!ctx.arg.whyExtract.empty())
852 ctx.whyExtractRecords.emplace_back(Args: "<libcall>", Args: sym->getFile(), Args&: *sym);
853 cast<LazySymbol>(Val: sym)->extract();
854 }
855}
856
857static void writeWhyExtract() {
858 if (ctx.arg.whyExtract.empty())
859 return;
860
861 std::error_code ec;
862 raw_fd_ostream os(ctx.arg.whyExtract, ec, sys::fs::OF_None);
863 if (ec) {
864 error(msg: "cannot open --why-extract= file " + ctx.arg.whyExtract + ": " +
865 ec.message());
866 return;
867 }
868
869 os << "reference\textracted\tsymbol\n";
870 for (auto &entry : ctx.whyExtractRecords) {
871 os << std::get<0>(t&: entry) << '\t' << toString(file: std::get<1>(t&: entry)) << '\t'
872 << toString(sym: std::get<2>(t&: entry)) << '\n';
873 }
874}
875
876// Equivalent of demote demoteSharedAndLazySymbols() in the ELF linker
877static void demoteLazySymbols() {
878 for (Symbol *sym : symtab->symbols()) {
879 if (auto *s = dyn_cast<LazySymbol>(Val: sym)) {
880 if (s->signature) {
881 LLVM_DEBUG(llvm::dbgs()
882 << "demoting lazy func: " << s->getName() << "\n");
883 replaceSymbol<UndefinedFunction>(s, arg: s->getName(), arg: std::nullopt,
884 arg: std::nullopt, arg: WASM_SYMBOL_BINDING_WEAK,
885 arg: s->getFile(), arg&: s->signature);
886 }
887 }
888 }
889}
890
891static UndefinedGlobal *
892createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
893 auto *sym = cast<UndefinedGlobal>(Val: symtab->addUndefinedGlobal(
894 name, importName: std::nullopt, importModule: std::nullopt, flags: WASM_SYMBOL_UNDEFINED, file: nullptr, type));
895 ctx.arg.allowUndefinedSymbols.insert(key: sym->getName());
896 sym->isUsedInRegularObj = true;
897 return sym;
898}
899
900static UndefinedFunction *createUndefinedFunction(StringRef name,
901 WasmSignature *signature) {
902 auto *sym = cast<UndefinedFunction>(Val: symtab->addUndefinedFunction(
903 name, importName: std::nullopt, importModule: std::nullopt, flags: WASM_SYMBOL_UNDEFINED, file: nullptr,
904 signature, isCalledDirectly: true));
905 ctx.arg.allowUndefinedSymbols.insert(key: sym->getName());
906 sym->isUsedInRegularObj = true;
907 return sym;
908}
909
910static InputGlobal *createGlobal(StringRef name, bool isMutable) {
911 llvm::wasm::WasmGlobal wasmGlobal;
912 bool is64 = ctx.arg.is64.value_or(u: false);
913 wasmGlobal.Type = {.Type: uint8_t(is64 ? WASM_TYPE_I64 : WASM_TYPE_I32), .Mutable: isMutable};
914 wasmGlobal.InitExpr = intConst(value: 0, is64);
915 wasmGlobal.SymbolName = name;
916 return make<InputGlobal>(args&: wasmGlobal, args: nullptr);
917}
918
919static DefinedGlobal *createGlobalVariable(StringRef name, bool isMutable,
920 uint32_t flags = 0) {
921 InputGlobal *g = createGlobal(name, isMutable);
922 return symtab->addSyntheticGlobal(name, flags, global: g);
923}
924
925static DefinedGlobal *createOptionalGlobal(StringRef name, bool isMutable) {
926 InputGlobal *g = createGlobal(name, isMutable);
927 return symtab->addOptionalGlobalSymbol(name, global: g);
928}
929
930// Create ABI-defined synthetic symbols
931static void createSyntheticSymbols() {
932 if (ctx.arg.relocatable)
933 return;
934
935 static WasmSignature nullSignature = {{}, {}};
936 static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
937 static WasmSignature i64ArgSignature = {{}, {ValType::I64}};
938 static llvm::wasm::WasmGlobalType globalTypeI32 = {.Type: WASM_TYPE_I32, .Mutable: false};
939 static llvm::wasm::WasmGlobalType globalTypeI64 = {.Type: WASM_TYPE_I64, .Mutable: false};
940 static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {.Type: WASM_TYPE_I32,
941 .Mutable: true};
942 static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {.Type: WASM_TYPE_I64,
943 .Mutable: true};
944
945 ctx.sym.callCtors = symtab->addSyntheticFunction(
946 name: "__wasm_call_ctors", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
947 function: make<SyntheticFunction>(args&: nullSignature, args: "__wasm_call_ctors"));
948
949 bool is64 = ctx.arg.is64.value_or(u: false);
950
951 auto stack_pointer_name =
952 ctx.arg.libcallThreadContext ? "__init_stack_pointer" : "__stack_pointer";
953 if (ctx.isPic) {
954 if (ctx.arg.libcallThreadContext) {
955 ctx.sym.stackPointer = createUndefinedGlobal(
956 name: stack_pointer_name,
957 type: ctx.arg.is64.value_or(u: false) ? &globalTypeI64 : &globalTypeI32);
958 } else {
959 ctx.sym.stackPointer = createUndefinedGlobal(name: stack_pointer_name,
960 type: ctx.arg.is64.value_or(u: false)
961 ? &mutableGlobalTypeI64
962 : &mutableGlobalTypeI32);
963 }
964 // For PIC code, we import two global variables (__memory_base and
965 // __table_base) from the environment and use these as the offset at
966 // which to load our static data and function table.
967 // See:
968 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
969 auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32;
970 ctx.sym.memoryBase = createUndefinedGlobal(name: "__memory_base", type: globalType);
971 ctx.sym.tableBase = createUndefinedGlobal(name: "__table_base", type: globalType);
972 ctx.sym.memoryBase->markLive();
973 ctx.sym.tableBase->markLive();
974 } else {
975 // For non-PIC code
976 ctx.sym.stackPointer =
977 createGlobalVariable(name: stack_pointer_name, isMutable: !ctx.arg.libcallThreadContext);
978 }
979
980 if (ctx.arg.isMultithreaded()) {
981 // TLS symbols are all hidden/dso-local
982 auto tls_base_name =
983 ctx.arg.libcallThreadContext ? "__init_tls_base" : "__tls_base";
984 ctx.sym.tlsBase = createGlobalVariable(name: tls_base_name, isMutable: true,
985 flags: WASM_SYMBOL_VISIBILITY_HIDDEN);
986 ctx.sym.tlsSize = createGlobalVariable(name: "__tls_size", isMutable: false,
987 flags: WASM_SYMBOL_VISIBILITY_HIDDEN);
988 ctx.sym.tlsAlign = createGlobalVariable(name: "__tls_align", isMutable: false,
989 flags: WASM_SYMBOL_VISIBILITY_HIDDEN);
990 ctx.sym.initTLS = symtab->addSyntheticFunction(
991 name: "__wasm_init_tls", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
992 function: make<SyntheticFunction>(args&: is64 ? i64ArgSignature : i32ArgSignature,
993 args: "__wasm_init_tls"));
994 if (ctx.arg.libcallThreadContext) {
995 ctx.sym.tlsBase->markLive();
996 ctx.sym.tlsSize->markLive();
997 ctx.sym.tlsAlign->markLive();
998 static WasmSignature setTLSBaseSignature{{}, {ValType::I32}};
999 ctx.sym.setTLSBase =
1000 createUndefinedFunction(name: "__wasm_set_tls_base", signature: &setTLSBaseSignature);
1001 ctx.sym.setTLSBase->markLive();
1002 static WasmSignature getTLSBaseSignature{{ValType::I32}, {}};
1003 ctx.sym.getTLSBase =
1004 createUndefinedFunction(name: "__wasm_get_tls_base", signature: &getTLSBaseSignature);
1005 ctx.sym.getTLSBase->markLive();
1006 }
1007 }
1008}
1009
1010static void createOptionalSymbols() {
1011 if (ctx.arg.relocatable)
1012 return;
1013
1014 ctx.sym.dsoHandle = symtab->addOptionalDataSymbol(name: "__dso_handle");
1015
1016 auto addDataLayoutSymbol = [&](StringRef s) -> DefinedData * {
1017 // Data layout symbols are either defined by lld, or (in the case
1018 // of PIC code) defined by the dynamic linker / embedder.
1019 if (ctx.isPic) {
1020 ctx.arg.allowUndefinedSymbols.insert(key: s);
1021 return nullptr;
1022 } else {
1023 return symtab->addOptionalDataSymbol(name: s);
1024 }
1025 };
1026
1027 ctx.sym.dataEnd = addDataLayoutSymbol("__data_end");
1028 ctx.sym.rodataStart = addDataLayoutSymbol("__rodata_start");
1029 ctx.sym.rodataEnd = addDataLayoutSymbol("__rodata_end");
1030 ctx.sym.stackLow = addDataLayoutSymbol("__stack_low");
1031 ctx.sym.stackHigh = addDataLayoutSymbol("__stack_high");
1032 ctx.sym.globalBase = addDataLayoutSymbol("__global_base");
1033 ctx.sym.heapBase = addDataLayoutSymbol("__heap_base");
1034 ctx.sym.heapEnd = addDataLayoutSymbol("__heap_end");
1035
1036 // for pic, __memory_base and __table_base are handled in
1037 // createSyntheticSymbols.
1038 if (!ctx.isPic) {
1039 ctx.sym.memoryBase = createOptionalGlobal(name: "__memory_base", isMutable: false);
1040 ctx.sym.tableBase = createOptionalGlobal(name: "__table_base", isMutable: false);
1041 }
1042
1043 ctx.sym.firstPageEnd = symtab->addOptionalDataSymbol(name: "__wasm_first_page_end");
1044 if (ctx.sym.firstPageEnd)
1045 ctx.sym.firstPageEnd->setVA(ctx.arg.pageSize);
1046
1047 // TLS object files may be linked into single-threaded programs, so
1048 // __tls_base must always be defined. In this case it is immutable and points
1049 // directly to the start of the `.tdata` segment. __tls_size and __tls_align
1050 // are omitted since they are only used by __wasm_init_tls, which is not
1051 // created in this case.
1052 if (!ctx.sym.tlsBase)
1053 ctx.sym.tlsBase = createOptionalGlobal(name: "__tls_base", isMutable: false);
1054}
1055
1056static void processStubLibrariesPreLTO() {
1057 log(msg: "-- processStubLibrariesPreLTO");
1058 for (auto &stub_file : ctx.stubFiles) {
1059 LLVM_DEBUG(llvm::dbgs()
1060 << "processing stub file: " << stub_file->getName() << "\n");
1061 for (auto [name, deps] : stub_file->symbolDependencies) {
1062 auto *sym = symtab->find(name);
1063 // If the symbol is not present at all (yet), or if it is present but
1064 // undefined, then mark the dependent symbols as used by a regular
1065 // object so they will be preserved and exported by the LTO process.
1066 if (!sym || sym->isUndefined()) {
1067 for (const auto dep : deps) {
1068 auto *needed = symtab->find(name: dep);
1069 if (needed) {
1070 needed->isUsedInRegularObj = true;
1071 // Like with handleLibcall we have to extract any LTO archive
1072 // members that might need to be exported due to stub library
1073 // symbols being referenced. Without this the LTO object could be
1074 // extracted during processStubLibraries, which is too late since
1075 // LTO has already being performed at that point.
1076 if (needed->isLazy() && isa<BitcodeFile>(Val: needed->getFile())) {
1077 if (!ctx.arg.whyExtract.empty())
1078 ctx.whyExtractRecords.emplace_back(Args: toString(file: stub_file),
1079 Args: needed->getFile(), Args&: *needed);
1080 cast<LazySymbol>(Val: needed)->extract();
1081 }
1082 }
1083 }
1084 }
1085 }
1086 }
1087}
1088
1089static bool addStubSymbolDeps(const StubFile *stub_file, Symbol *sym,
1090 ArrayRef<StringRef> deps) {
1091 // The first stub library to define a given symbol sets this and
1092 // definitions in later stub libraries are ignored.
1093 if (sym->forceImport)
1094 return false; // Already handled
1095 sym->forceImport = true;
1096 if (sym->traced)
1097 message(msg: toString(file: stub_file) + ": importing " + sym->getName());
1098 else
1099 LLVM_DEBUG(llvm::dbgs() << toString(stub_file) << ": importing "
1100 << sym->getName() << "\n");
1101 bool depsAdded = false;
1102 for (const auto dep : deps) {
1103 auto *needed = symtab->find(name: dep);
1104 if (!needed) {
1105 error(msg: toString(file: stub_file) + ": undefined symbol: " + dep +
1106 ". Required by " + toString(sym: *sym));
1107 } else if (needed->isUndefined()) {
1108 error(msg: toString(file: stub_file) + ": undefined symbol: " + toString(sym: *needed) +
1109 ". Required by " + toString(sym: *sym));
1110 } else {
1111 if (needed->traced)
1112 message(msg: toString(file: stub_file) + ": exported " + toString(sym: *needed) +
1113 " due to import of " + sym->getName());
1114 else
1115 LLVM_DEBUG(llvm::dbgs()
1116 << "force export: " << toString(*needed) << "\n");
1117 needed->forceExport = true;
1118 if (auto *lazy = dyn_cast<LazySymbol>(Val: needed)) {
1119 depsAdded = true;
1120 lazy->extract();
1121 if (!ctx.arg.whyExtract.empty())
1122 ctx.whyExtractRecords.emplace_back(Args: toString(file: stub_file),
1123 Args: sym->getFile(), Args&: *sym);
1124 }
1125 }
1126 }
1127 return depsAdded;
1128}
1129
1130static void processStubLibraries() {
1131 log(msg: "-- processStubLibraries");
1132 bool depsAdded = false;
1133 do {
1134 depsAdded = false;
1135 for (auto &stub_file : ctx.stubFiles) {
1136 LLVM_DEBUG(llvm::dbgs()
1137 << "processing stub file: " << stub_file->getName() << "\n");
1138
1139 // First look for any imported symbols that directly match
1140 // the names of the stub imports
1141 for (auto [name, deps] : stub_file->symbolDependencies) {
1142 auto *sym = symtab->find(name);
1143 if (sym && sym->isUndefined() && sym->isUsedInRegularObj) {
1144 depsAdded |= addStubSymbolDeps(stub_file, sym, deps);
1145 } else {
1146 if (sym && sym->traced)
1147 message(msg: toString(file: stub_file) + ": stub symbol not needed: " + name);
1148 else
1149 LLVM_DEBUG(llvm::dbgs()
1150 << "stub symbol not needed: `" << name << "`\n");
1151 }
1152 }
1153
1154 // Secondly looks for any symbols with an `importName` that matches
1155 for (Symbol *sym : symtab->symbols()) {
1156 if (sym->isUndefined() && sym->importName.has_value()) {
1157 auto it = stub_file->symbolDependencies.find(Val: sym->importName.value());
1158 if (it != stub_file->symbolDependencies.end()) {
1159 depsAdded |= addStubSymbolDeps(stub_file, sym, deps: it->second);
1160 }
1161 }
1162 }
1163 }
1164 } while (depsAdded);
1165
1166 log(msg: "-- done processStubLibraries");
1167}
1168
1169// Reconstructs command line arguments so that so that you can re-run
1170// the same command with the same inputs. This is for --reproduce.
1171static std::string createResponseFile(const opt::InputArgList &args) {
1172 SmallString<0> data;
1173 raw_svector_ostream os(data);
1174
1175 // Copy the command line to the output while rewriting paths.
1176 for (auto *arg : args) {
1177 switch (arg->getOption().getID()) {
1178 case OPT_reproduce:
1179 break;
1180 case OPT_INPUT:
1181 os << quote(s: relativeToRoot(path: arg->getValue())) << "\n";
1182 break;
1183 case OPT_o:
1184 // If -o path contains directories, "lld @response.txt" will likely
1185 // fail because the archive we are creating doesn't contain empty
1186 // directories for the output path (-o doesn't create directories).
1187 // Strip directories to prevent the issue.
1188 os << "-o " << quote(s: sys::path::filename(path: arg->getValue())) << "\n";
1189 break;
1190 default:
1191 os << toString(arg: *arg) << "\n";
1192 }
1193 }
1194 return std::string(data);
1195}
1196
1197// The --wrap option is a feature to rename symbols so that you can write
1198// wrappers for existing functions. If you pass `-wrap=foo`, all
1199// occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
1200// expected to write `wrap_foo` function as a wrapper). The original
1201// symbol becomes accessible as `real_foo`, so you can call that from your
1202// wrapper.
1203//
1204// This data structure is instantiated for each -wrap option.
1205struct WrappedSymbol {
1206 Symbol *sym;
1207 Symbol *real;
1208 Symbol *wrap;
1209};
1210
1211static Symbol *addUndefined(StringRef name,
1212 const WasmSignature *signature = nullptr) {
1213 return symtab->addUndefinedFunction(name, importName: std::nullopt, importModule: std::nullopt,
1214 flags: WASM_SYMBOL_UNDEFINED, file: nullptr, signature,
1215 isCalledDirectly: false);
1216}
1217
1218// Handles -wrap option.
1219//
1220// This function instantiates wrapper symbols. At this point, they seem
1221// like they are not being used at all, so we explicitly set some flags so
1222// that LTO won't eliminate them.
1223static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
1224 std::vector<WrappedSymbol> v;
1225 DenseSet<StringRef> seen;
1226
1227 for (auto *arg : args.filtered(Ids: OPT_wrap)) {
1228 StringRef name = arg->getValue();
1229 if (!seen.insert(V: name).second)
1230 continue;
1231
1232 Symbol *sym = symtab->find(name);
1233 if (!sym)
1234 continue;
1235
1236 Symbol *real = addUndefined(name: saver().save(S: "__real_" + name));
1237 Symbol *wrap =
1238 addUndefined(name: saver().save(S: "__wrap_" + name), signature: sym->getSignature());
1239 v.push_back(x: {.sym: sym, .real: real, .wrap: wrap});
1240
1241 // We want to tell LTO not to inline symbols to be overwritten
1242 // because LTO doesn't know the final symbol contents after renaming.
1243 real->canInline = false;
1244 sym->canInline = false;
1245
1246 // Tell LTO not to eliminate these symbols.
1247 sym->isUsedInRegularObj = true;
1248 wrap->isUsedInRegularObj = true;
1249 real->isUsedInRegularObj = false;
1250 }
1251 return v;
1252}
1253
1254// Do renaming for -wrap by updating pointers to symbols.
1255//
1256// When this function is executed, only InputFiles and symbol table
1257// contain pointers to symbol objects. We visit them to replace pointers,
1258// so that wrapped symbols are swapped as instructed by the command line.
1259static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
1260 DenseMap<Symbol *, Symbol *> map;
1261 for (const WrappedSymbol &w : wrapped) {
1262 map[w.sym] = w.wrap;
1263 map[w.real] = w.sym;
1264 }
1265
1266 // Update pointers in input files.
1267 parallelForEach(R&: ctx.objectFiles, Fn: [&](InputFile *file) {
1268 MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
1269 for (Symbol *&sym : syms)
1270 if (Symbol *s = map.lookup(Val: sym))
1271 sym = s;
1272 });
1273
1274 // Update pointers in the symbol table.
1275 for (const WrappedSymbol &w : wrapped)
1276 symtab->wrap(sym: w.sym, real: w.real, wrap: w.wrap);
1277}
1278
1279static void splitSections() {
1280 // splitIntoPieces needs to be called on each MergeInputChunk
1281 // before calling finalizeContents().
1282 LLVM_DEBUG(llvm::dbgs() << "splitSections\n");
1283 parallelForEach(R&: ctx.objectFiles, Fn: [](ObjFile *file) {
1284 for (InputChunk *seg : file->segments) {
1285 if (auto *s = dyn_cast<MergeInputChunk>(Val: seg))
1286 s->splitIntoPieces();
1287 }
1288 for (InputChunk *sec : file->customSections) {
1289 if (auto *s = dyn_cast<MergeInputChunk>(Val: sec))
1290 s->splitIntoPieces();
1291 }
1292 });
1293}
1294
1295static bool isKnownZFlag(StringRef s) {
1296 // For now, we only support a very limited set of -z flags
1297 return s.starts_with(Prefix: "stack-size=") || s.starts_with(Prefix: "muldefs");
1298}
1299
1300// Report a warning for an unknown -z option.
1301static void checkZOptions(opt::InputArgList &args) {
1302 for (auto *arg : args.filtered(Ids: OPT_z))
1303 if (!isKnownZFlag(s: arg->getValue()))
1304 warn(msg: "unknown -z value: " + StringRef(arg->getValue()));
1305}
1306
1307LinkerDriver::LinkerDriver(Ctx &ctx) : ctx(ctx) {}
1308
1309void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
1310 WasmOptTable parser;
1311 opt::InputArgList args = parser.parse(argv: argsArr.slice(N: 1));
1312
1313 // Interpret these flags early because error()/warn() depend on them.
1314 auto &errHandler = errorHandler();
1315 errHandler.errorLimit = args::getInteger(args, key: OPT_error_limit, Default: 20);
1316 errHandler.fatalWarnings =
1317 args.hasFlag(Pos: OPT_fatal_warnings, Neg: OPT_no_fatal_warnings, Default: false);
1318 checkZOptions(args);
1319
1320 // Handle --help
1321 if (args.hasArg(Ids: OPT_help)) {
1322 parser.printHelp(OS&: errHandler.outs(),
1323 Usage: (std::string(argsArr[0]) + " [options] file...").c_str(),
1324 Title: "LLVM Linker", ShowHidden: false);
1325 return;
1326 }
1327
1328 // Handle -v or -version.
1329 if (args.hasArg(Ids: OPT_v) || args.hasArg(Ids: OPT_version))
1330 errHandler.outs() << getLLDVersion() << "\n";
1331
1332 // Handle --reproduce
1333 if (const char *path = getReproduceOption(args)) {
1334 Expected<std::unique_ptr<TarWriter>> errOrWriter =
1335 TarWriter::create(OutputPath: path, BaseDir: path::stem(path));
1336 if (errOrWriter) {
1337 tar = std::move(*errOrWriter);
1338 tar->append(Path: "response.txt", Data: createResponseFile(args));
1339 tar->append(Path: "version.txt", Data: getLLDVersion() + "\n");
1340 } else {
1341 error(msg: "--reproduce: " + toString(E: errOrWriter.takeError()));
1342 }
1343 }
1344
1345 // Parse and evaluate -mllvm options.
1346 std::vector<const char *> v;
1347 v.push_back(x: "wasm-ld (LLVM option parsing)");
1348 for (auto *arg : args.filtered(Ids: OPT_mllvm))
1349 v.push_back(x: arg->getValue());
1350 cl::ResetAllOptionOccurrences();
1351 cl::ParseCommandLineOptions(argc: v.size(), argv: v.data());
1352
1353 readConfigs(args);
1354 setConfigs();
1355
1356 // The behavior of -v or --version is a bit strange, but this is
1357 // needed for compatibility with GNU linkers.
1358 if (args.hasArg(Ids: OPT_v) && !args.hasArg(Ids: OPT_INPUT))
1359 return;
1360 if (args.hasArg(Ids: OPT_version))
1361 return;
1362
1363 createFiles(args);
1364 if (errorCount())
1365 return;
1366
1367 checkOptions(args);
1368 if (errorCount())
1369 return;
1370
1371 if (auto *arg = args.getLastArg(Ids: OPT_allow_undefined_file))
1372 readImportFile(filename: arg->getValue());
1373
1374 // Fail early if the output file or map file is not writable. If a user has a
1375 // long link, e.g. due to a large LTO link, they do not wish to run it and
1376 // find that it failed because there was a mistake in their command-line.
1377 if (auto e = tryCreateFile(path: ctx.arg.outputFile))
1378 error(msg: "cannot open output file " + ctx.arg.outputFile + ": " + e.message());
1379 if (auto e = tryCreateFile(path: ctx.arg.mapFile))
1380 error(msg: "cannot open map file " + ctx.arg.mapFile + ": " + e.message());
1381 if (errorCount())
1382 return;
1383
1384 // Handle --trace-symbol.
1385 for (auto *arg : args.filtered(Ids: OPT_trace_symbol))
1386 symtab->trace(name: arg->getValue());
1387
1388 for (auto *arg : args.filtered(Ids: OPT_export_if_defined))
1389 ctx.arg.exportedSymbols.insert(key: arg->getValue());
1390
1391 for (auto *arg : args.filtered(Ids: OPT_export)) {
1392 ctx.arg.exportedSymbols.insert(key: arg->getValue());
1393 ctx.arg.requiredExports.push_back(x: arg->getValue());
1394 }
1395
1396 createSyntheticSymbols();
1397
1398 // Add all files to the symbol table. This will add almost all
1399 // symbols that we need to the symbol table.
1400 for (InputFile *f : files)
1401 symtab->addFile(file: f);
1402 if (errorCount())
1403 return;
1404
1405 // Handle the `--undefined <sym>` options.
1406 for (auto *arg : args.filtered(Ids: OPT_undefined))
1407 handleUndefined(name: arg->getValue(), option: "<internal>");
1408
1409 // Handle the `--export <sym>` options
1410 // This works like --undefined but also exports the symbol if its found
1411 for (auto &iter : ctx.arg.exportedSymbols)
1412 handleUndefined(name: iter.first(), option: "--export");
1413
1414 Symbol *entrySym = nullptr;
1415 if (!ctx.arg.relocatable && !ctx.arg.entry.empty()) {
1416 entrySym = handleUndefined(name: ctx.arg.entry, option: "--entry");
1417 if (entrySym && entrySym->isDefined())
1418 entrySym->forceExport = true;
1419 else
1420 error(msg: "entry symbol not defined (pass --no-entry to suppress): " +
1421 ctx.arg.entry);
1422 }
1423
1424 // If the user code defines a `__wasm_call_dtors` function, remember it so
1425 // that we can call it from the command export wrappers. Unlike
1426 // `__wasm_call_ctors` which we synthesize, `__wasm_call_dtors` is defined
1427 // by libc/etc., because destructors are registered dynamically with
1428 // `__cxa_atexit` and friends.
1429 if (!ctx.arg.relocatable && !ctx.arg.shared &&
1430 !ctx.sym.callCtors->isUsedInRegularObj &&
1431 ctx.sym.callCtors->getName() != ctx.arg.entry &&
1432 !ctx.arg.exportedSymbols.contains(key: ctx.sym.callCtors->getName())) {
1433 if (Symbol *callDtors =
1434 handleUndefined(name: "__wasm_call_dtors", option: "<internal>")) {
1435 if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(Val: callDtors)) {
1436 if (callDtorsFunc->signature &&
1437 (!callDtorsFunc->signature->Params.empty() ||
1438 !callDtorsFunc->signature->Returns.empty())) {
1439 error(msg: "__wasm_call_dtors must have no argument or return values");
1440 }
1441 ctx.sym.callDtors = callDtorsFunc;
1442 } else {
1443 error(msg: "__wasm_call_dtors must be a function");
1444 }
1445 }
1446 }
1447
1448 if (errorCount())
1449 return;
1450
1451 // Create wrapped symbols for -wrap option.
1452 std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
1453
1454 // If any of our inputs are bitcode files, the LTO code generator may create
1455 // references to certain library functions that might not be explicit in the
1456 // bitcode file's symbol table. If any of those library functions are defined
1457 // in a bitcode file in an archive member, we need to arrange to use LTO to
1458 // compile those archive members by adding them to the link beforehand.
1459 //
1460 // We only need to add libcall symbols to the link before LTO if the symbol's
1461 // definition is in bitcode. Any other required libcall symbols will be added
1462 // to the link after LTO when we add the LTO object file to the link.
1463 if (!ctx.bitcodeFiles.empty()) {
1464 llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple());
1465 for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
1466 handleLibcall(name: s);
1467 }
1468 if (errorCount())
1469 return;
1470
1471 // We process the stub libraries once beofore LTO to ensure that any possible
1472 // required exports are preserved by the LTO process.
1473 processStubLibrariesPreLTO();
1474
1475 // Do link-time optimization if given files are LLVM bitcode files.
1476 // This compiles bitcode files into real object files.
1477 symtab->compileBitcodeFiles();
1478 if (errorCount())
1479 return;
1480
1481 // The LTO process can generate new undefined symbols, specifically libcall
1482 // functions. Because those symbols might be declared in a stub library we
1483 // need the process the stub libraries once again after LTO to handle all
1484 // undefined symbols, including ones that didn't exist prior to LTO.
1485 processStubLibraries();
1486
1487 writeWhyExtract();
1488
1489 // Bail out if normal linked output is skipped due to LTO.
1490 if (ctx.arg.thinLTOIndexOnly)
1491 return;
1492
1493 createOptionalSymbols();
1494
1495 // Resolve any variant symbols that were created due to signature
1496 // mismatches.
1497 symtab->handleSymbolVariants();
1498 if (errorCount())
1499 return;
1500
1501 // Apply symbol renames for -wrap.
1502 if (!wrapped.empty())
1503 wrapSymbols(wrapped);
1504
1505 for (auto &iter : ctx.arg.exportedSymbols) {
1506 Symbol *sym = symtab->find(name: iter.first());
1507 if (sym && sym->isDefined())
1508 sym->forceExport = true;
1509 }
1510
1511 if (!ctx.arg.relocatable && !ctx.isPic) {
1512 // Add synthetic dummies for weak undefined functions. Must happen
1513 // after LTO otherwise functions may not yet have signatures.
1514 symtab->handleWeakUndefines();
1515 }
1516
1517 if (entrySym)
1518 entrySym->setHidden(false);
1519
1520 if (errorCount())
1521 return;
1522
1523 // Split WASM_SEG_FLAG_STRINGS sections into pieces in preparation for garbage
1524 // collection.
1525 splitSections();
1526
1527 // Any remaining lazy symbols should be demoted to Undefined
1528 demoteLazySymbols();
1529
1530 // Do size optimizations: garbage collection
1531 markLive();
1532
1533 // Provide the indirect function table if needed.
1534 ctx.sym.indirectFunctionTable =
1535 symtab->resolveIndirectFunctionTable(/*required =*/false);
1536
1537 if (errorCount())
1538 return;
1539
1540 // Write the result to the file.
1541 writeResult();
1542}
1543
1544} // namespace lld::wasm
1545