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