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 ctx.sym.rodataStart = symtab->addOptionalDataSymbol(name: "__rodata_start");
994 ctx.sym.rodataEnd = symtab->addOptionalDataSymbol(name: "__rodata_end");
995 }
996
997 if (!ctx.isPic) {
998 ctx.sym.stackLow = symtab->addOptionalDataSymbol(name: "__stack_low");
999 ctx.sym.stackHigh = symtab->addOptionalDataSymbol(name: "__stack_high");
1000 ctx.sym.globalBase = symtab->addOptionalDataSymbol(name: "__global_base");
1001 ctx.sym.heapBase = symtab->addOptionalDataSymbol(name: "__heap_base");
1002 ctx.sym.heapEnd = symtab->addOptionalDataSymbol(name: "__heap_end");
1003 ctx.sym.memoryBase = createOptionalGlobal(name: "__memory_base", isMutable: false);
1004 ctx.sym.tableBase = createOptionalGlobal(name: "__table_base", isMutable: false);
1005 }
1006
1007 ctx.sym.firstPageEnd = symtab->addOptionalDataSymbol(name: "__wasm_first_page_end");
1008 if (ctx.sym.firstPageEnd)
1009 ctx.sym.firstPageEnd->setVA(ctx.arg.pageSize);
1010
1011 // For non-shared memory programs we still need to define __tls_base since we
1012 // allow object files built with TLS to be linked into single threaded
1013 // programs, and such object files can contain references to this symbol.
1014 //
1015 // However, in this case __tls_base is immutable and points directly to the
1016 // start of the `.tdata` static segment.
1017 //
1018 // __tls_size and __tls_align are not needed in this case since they are only
1019 // needed for __wasm_init_tls (which we do not create in this case).
1020 if (!ctx.arg.sharedMemory)
1021 ctx.sym.tlsBase = createOptionalGlobal(name: "__tls_base", isMutable: false);
1022}
1023
1024static void processStubLibrariesPreLTO() {
1025 log(msg: "-- processStubLibrariesPreLTO");
1026 for (auto &stub_file : ctx.stubFiles) {
1027 LLVM_DEBUG(llvm::dbgs()
1028 << "processing stub file: " << stub_file->getName() << "\n");
1029 for (auto [name, deps] : stub_file->symbolDependencies) {
1030 auto *sym = symtab->find(name);
1031 // If the symbol is not present at all (yet), or if it is present but
1032 // undefined, then mark the dependent symbols as used by a regular
1033 // object so they will be preserved and exported by the LTO process.
1034 if (!sym || sym->isUndefined()) {
1035 for (const auto dep : deps) {
1036 auto *needed = symtab->find(name: dep);
1037 if (needed) {
1038 needed->isUsedInRegularObj = true;
1039 // Like with handleLibcall we have to extract any LTO archive
1040 // members that might need to be exported due to stub library
1041 // symbols being referenced. Without this the LTO object could be
1042 // extracted during processStubLibraries, which is too late since
1043 // LTO has already being performed at that point.
1044 if (needed->isLazy() && isa<BitcodeFile>(Val: needed->getFile())) {
1045 if (!ctx.arg.whyExtract.empty())
1046 ctx.whyExtractRecords.emplace_back(Args: toString(file: stub_file),
1047 Args: needed->getFile(), Args&: *needed);
1048 cast<LazySymbol>(Val: needed)->extract();
1049 }
1050 }
1051 }
1052 }
1053 }
1054 }
1055}
1056
1057static bool addStubSymbolDeps(const StubFile *stub_file, Symbol *sym,
1058 ArrayRef<StringRef> deps) {
1059 // The first stub library to define a given symbol sets this and
1060 // definitions in later stub libraries are ignored.
1061 if (sym->forceImport)
1062 return false; // Already handled
1063 sym->forceImport = true;
1064 if (sym->traced)
1065 message(msg: toString(file: stub_file) + ": importing " + sym->getName());
1066 else
1067 LLVM_DEBUG(llvm::dbgs() << toString(stub_file) << ": importing "
1068 << sym->getName() << "\n");
1069 bool depsAdded = false;
1070 for (const auto dep : deps) {
1071 auto *needed = symtab->find(name: dep);
1072 if (!needed) {
1073 error(msg: toString(file: stub_file) + ": undefined symbol: " + dep +
1074 ". Required by " + toString(sym: *sym));
1075 } else if (needed->isUndefined()) {
1076 error(msg: toString(file: stub_file) + ": undefined symbol: " + toString(sym: *needed) +
1077 ". Required by " + toString(sym: *sym));
1078 } else {
1079 if (needed->traced)
1080 message(msg: toString(file: stub_file) + ": exported " + toString(sym: *needed) +
1081 " due to import of " + sym->getName());
1082 else
1083 LLVM_DEBUG(llvm::dbgs()
1084 << "force export: " << toString(*needed) << "\n");
1085 needed->forceExport = true;
1086 if (auto *lazy = dyn_cast<LazySymbol>(Val: needed)) {
1087 depsAdded = true;
1088 lazy->extract();
1089 if (!ctx.arg.whyExtract.empty())
1090 ctx.whyExtractRecords.emplace_back(Args: toString(file: stub_file),
1091 Args: sym->getFile(), Args&: *sym);
1092 }
1093 }
1094 }
1095 return depsAdded;
1096}
1097
1098static void processStubLibraries() {
1099 log(msg: "-- processStubLibraries");
1100 bool depsAdded = false;
1101 do {
1102 depsAdded = false;
1103 for (auto &stub_file : ctx.stubFiles) {
1104 LLVM_DEBUG(llvm::dbgs()
1105 << "processing stub file: " << stub_file->getName() << "\n");
1106
1107 // First look for any imported symbols that directly match
1108 // the names of the stub imports
1109 for (auto [name, deps] : stub_file->symbolDependencies) {
1110 auto *sym = symtab->find(name);
1111 if (sym && sym->isUndefined() && sym->isUsedInRegularObj) {
1112 depsAdded |= addStubSymbolDeps(stub_file, sym, deps);
1113 } else {
1114 if (sym && sym->traced)
1115 message(msg: toString(file: stub_file) + ": stub symbol not needed: " + name);
1116 else
1117 LLVM_DEBUG(llvm::dbgs()
1118 << "stub symbol not needed: `" << name << "`\n");
1119 }
1120 }
1121
1122 // Secondly looks for any symbols with an `importName` that matches
1123 for (Symbol *sym : symtab->symbols()) {
1124 if (sym->isUndefined() && sym->importName.has_value()) {
1125 auto it = stub_file->symbolDependencies.find(Val: sym->importName.value());
1126 if (it != stub_file->symbolDependencies.end()) {
1127 depsAdded |= addStubSymbolDeps(stub_file, sym, deps: it->second);
1128 }
1129 }
1130 }
1131 }
1132 } while (depsAdded);
1133
1134 log(msg: "-- done processStubLibraries");
1135}
1136
1137// Reconstructs command line arguments so that so that you can re-run
1138// the same command with the same inputs. This is for --reproduce.
1139static std::string createResponseFile(const opt::InputArgList &args) {
1140 SmallString<0> data;
1141 raw_svector_ostream os(data);
1142
1143 // Copy the command line to the output while rewriting paths.
1144 for (auto *arg : args) {
1145 switch (arg->getOption().getID()) {
1146 case OPT_reproduce:
1147 break;
1148 case OPT_INPUT:
1149 os << quote(s: relativeToRoot(path: arg->getValue())) << "\n";
1150 break;
1151 case OPT_o:
1152 // If -o path contains directories, "lld @response.txt" will likely
1153 // fail because the archive we are creating doesn't contain empty
1154 // directories for the output path (-o doesn't create directories).
1155 // Strip directories to prevent the issue.
1156 os << "-o " << quote(s: sys::path::filename(path: arg->getValue())) << "\n";
1157 break;
1158 default:
1159 os << toString(arg: *arg) << "\n";
1160 }
1161 }
1162 return std::string(data);
1163}
1164
1165// The --wrap option is a feature to rename symbols so that you can write
1166// wrappers for existing functions. If you pass `-wrap=foo`, all
1167// occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
1168// expected to write `wrap_foo` function as a wrapper). The original
1169// symbol becomes accessible as `real_foo`, so you can call that from your
1170// wrapper.
1171//
1172// This data structure is instantiated for each -wrap option.
1173struct WrappedSymbol {
1174 Symbol *sym;
1175 Symbol *real;
1176 Symbol *wrap;
1177};
1178
1179static Symbol *addUndefined(StringRef name,
1180 const WasmSignature *signature = nullptr) {
1181 return symtab->addUndefinedFunction(name, importName: std::nullopt, importModule: std::nullopt,
1182 flags: WASM_SYMBOL_UNDEFINED, file: nullptr, signature,
1183 isCalledDirectly: false);
1184}
1185
1186// Handles -wrap option.
1187//
1188// This function instantiates wrapper symbols. At this point, they seem
1189// like they are not being used at all, so we explicitly set some flags so
1190// that LTO won't eliminate them.
1191static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
1192 std::vector<WrappedSymbol> v;
1193 DenseSet<StringRef> seen;
1194
1195 for (auto *arg : args.filtered(Ids: OPT_wrap)) {
1196 StringRef name = arg->getValue();
1197 if (!seen.insert(V: name).second)
1198 continue;
1199
1200 Symbol *sym = symtab->find(name);
1201 if (!sym)
1202 continue;
1203
1204 Symbol *real = addUndefined(name: saver().save(S: "__real_" + name));
1205 Symbol *wrap =
1206 addUndefined(name: saver().save(S: "__wrap_" + name), signature: sym->getSignature());
1207 v.push_back(x: {.sym: sym, .real: real, .wrap: wrap});
1208
1209 // We want to tell LTO not to inline symbols to be overwritten
1210 // because LTO doesn't know the final symbol contents after renaming.
1211 real->canInline = false;
1212 sym->canInline = false;
1213
1214 // Tell LTO not to eliminate these symbols.
1215 sym->isUsedInRegularObj = true;
1216 wrap->isUsedInRegularObj = true;
1217 real->isUsedInRegularObj = false;
1218 }
1219 return v;
1220}
1221
1222// Do renaming for -wrap by updating pointers to symbols.
1223//
1224// When this function is executed, only InputFiles and symbol table
1225// contain pointers to symbol objects. We visit them to replace pointers,
1226// so that wrapped symbols are swapped as instructed by the command line.
1227static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
1228 DenseMap<Symbol *, Symbol *> map;
1229 for (const WrappedSymbol &w : wrapped) {
1230 map[w.sym] = w.wrap;
1231 map[w.real] = w.sym;
1232 }
1233
1234 // Update pointers in input files.
1235 parallelForEach(R&: ctx.objectFiles, Fn: [&](InputFile *file) {
1236 MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
1237 for (Symbol *&sym : syms)
1238 if (Symbol *s = map.lookup(Val: sym))
1239 sym = s;
1240 });
1241
1242 // Update pointers in the symbol table.
1243 for (const WrappedSymbol &w : wrapped)
1244 symtab->wrap(sym: w.sym, real: w.real, wrap: w.wrap);
1245}
1246
1247static void splitSections() {
1248 // splitIntoPieces needs to be called on each MergeInputChunk
1249 // before calling finalizeContents().
1250 LLVM_DEBUG(llvm::dbgs() << "splitSections\n");
1251 parallelForEach(R&: ctx.objectFiles, Fn: [](ObjFile *file) {
1252 for (InputChunk *seg : file->segments) {
1253 if (auto *s = dyn_cast<MergeInputChunk>(Val: seg))
1254 s->splitIntoPieces();
1255 }
1256 for (InputChunk *sec : file->customSections) {
1257 if (auto *s = dyn_cast<MergeInputChunk>(Val: sec))
1258 s->splitIntoPieces();
1259 }
1260 });
1261}
1262
1263static bool isKnownZFlag(StringRef s) {
1264 // For now, we only support a very limited set of -z flags
1265 return s.starts_with(Prefix: "stack-size=") || s.starts_with(Prefix: "muldefs");
1266}
1267
1268// Report a warning for an unknown -z option.
1269static void checkZOptions(opt::InputArgList &args) {
1270 for (auto *arg : args.filtered(Ids: OPT_z))
1271 if (!isKnownZFlag(s: arg->getValue()))
1272 warn(msg: "unknown -z value: " + StringRef(arg->getValue()));
1273}
1274
1275LinkerDriver::LinkerDriver(Ctx &ctx) : ctx(ctx) {}
1276
1277void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
1278 WasmOptTable parser;
1279 opt::InputArgList args = parser.parse(argv: argsArr.slice(N: 1));
1280
1281 // Interpret these flags early because error()/warn() depend on them.
1282 auto &errHandler = errorHandler();
1283 errHandler.errorLimit = args::getInteger(args, key: OPT_error_limit, Default: 20);
1284 errHandler.fatalWarnings =
1285 args.hasFlag(Pos: OPT_fatal_warnings, Neg: OPT_no_fatal_warnings, Default: false);
1286 checkZOptions(args);
1287
1288 // Handle --help
1289 if (args.hasArg(Ids: OPT_help)) {
1290 parser.printHelp(OS&: errHandler.outs(),
1291 Usage: (std::string(argsArr[0]) + " [options] file...").c_str(),
1292 Title: "LLVM Linker", ShowHidden: false);
1293 return;
1294 }
1295
1296 // Handle -v or -version.
1297 if (args.hasArg(Ids: OPT_v) || args.hasArg(Ids: OPT_version))
1298 errHandler.outs() << getLLDVersion() << "\n";
1299
1300 // Handle --reproduce
1301 if (const char *path = getReproduceOption(args)) {
1302 Expected<std::unique_ptr<TarWriter>> errOrWriter =
1303 TarWriter::create(OutputPath: path, BaseDir: path::stem(path));
1304 if (errOrWriter) {
1305 tar = std::move(*errOrWriter);
1306 tar->append(Path: "response.txt", Data: createResponseFile(args));
1307 tar->append(Path: "version.txt", Data: getLLDVersion() + "\n");
1308 } else {
1309 error(msg: "--reproduce: " + toString(E: errOrWriter.takeError()));
1310 }
1311 }
1312
1313 // Parse and evaluate -mllvm options.
1314 std::vector<const char *> v;
1315 v.push_back(x: "wasm-ld (LLVM option parsing)");
1316 for (auto *arg : args.filtered(Ids: OPT_mllvm))
1317 v.push_back(x: arg->getValue());
1318 cl::ResetAllOptionOccurrences();
1319 cl::ParseCommandLineOptions(argc: v.size(), argv: v.data());
1320
1321 readConfigs(args);
1322 setConfigs();
1323
1324 // The behavior of -v or --version is a bit strange, but this is
1325 // needed for compatibility with GNU linkers.
1326 if (args.hasArg(Ids: OPT_v) && !args.hasArg(Ids: OPT_INPUT))
1327 return;
1328 if (args.hasArg(Ids: OPT_version))
1329 return;
1330
1331 createFiles(args);
1332 if (errorCount())
1333 return;
1334
1335 checkOptions(args);
1336 if (errorCount())
1337 return;
1338
1339 if (auto *arg = args.getLastArg(Ids: OPT_allow_undefined_file))
1340 readImportFile(filename: arg->getValue());
1341
1342 // Fail early if the output file or map file is not writable. If a user has a
1343 // long link, e.g. due to a large LTO link, they do not wish to run it and
1344 // find that it failed because there was a mistake in their command-line.
1345 if (auto e = tryCreateFile(path: ctx.arg.outputFile))
1346 error(msg: "cannot open output file " + ctx.arg.outputFile + ": " + e.message());
1347 if (auto e = tryCreateFile(path: ctx.arg.mapFile))
1348 error(msg: "cannot open map file " + ctx.arg.mapFile + ": " + e.message());
1349 if (errorCount())
1350 return;
1351
1352 // Handle --trace-symbol.
1353 for (auto *arg : args.filtered(Ids: OPT_trace_symbol))
1354 symtab->trace(name: arg->getValue());
1355
1356 for (auto *arg : args.filtered(Ids: OPT_export_if_defined))
1357 ctx.arg.exportedSymbols.insert(key: arg->getValue());
1358
1359 for (auto *arg : args.filtered(Ids: OPT_export)) {
1360 ctx.arg.exportedSymbols.insert(key: arg->getValue());
1361 ctx.arg.requiredExports.push_back(x: arg->getValue());
1362 }
1363
1364 createSyntheticSymbols();
1365
1366 // Add all files to the symbol table. This will add almost all
1367 // symbols that we need to the symbol table.
1368 for (InputFile *f : files)
1369 symtab->addFile(file: f);
1370 if (errorCount())
1371 return;
1372
1373 // Handle the `--undefined <sym>` options.
1374 for (auto *arg : args.filtered(Ids: OPT_undefined))
1375 handleUndefined(name: arg->getValue(), option: "<internal>");
1376
1377 // Handle the `--export <sym>` options
1378 // This works like --undefined but also exports the symbol if its found
1379 for (auto &iter : ctx.arg.exportedSymbols)
1380 handleUndefined(name: iter.first(), option: "--export");
1381
1382 Symbol *entrySym = nullptr;
1383 if (!ctx.arg.relocatable && !ctx.arg.entry.empty()) {
1384 entrySym = handleUndefined(name: ctx.arg.entry, option: "--entry");
1385 if (entrySym && entrySym->isDefined())
1386 entrySym->forceExport = true;
1387 else
1388 error(msg: "entry symbol not defined (pass --no-entry to suppress): " +
1389 ctx.arg.entry);
1390 }
1391
1392 // If the user code defines a `__wasm_call_dtors` function, remember it so
1393 // that we can call it from the command export wrappers. Unlike
1394 // `__wasm_call_ctors` which we synthesize, `__wasm_call_dtors` is defined
1395 // by libc/etc., because destructors are registered dynamically with
1396 // `__cxa_atexit` and friends.
1397 if (!ctx.arg.relocatable && !ctx.arg.shared &&
1398 !ctx.sym.callCtors->isUsedInRegularObj &&
1399 ctx.sym.callCtors->getName() != ctx.arg.entry &&
1400 !ctx.arg.exportedSymbols.contains(key: ctx.sym.callCtors->getName())) {
1401 if (Symbol *callDtors =
1402 handleUndefined(name: "__wasm_call_dtors", option: "<internal>")) {
1403 if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(Val: callDtors)) {
1404 if (callDtorsFunc->signature &&
1405 (!callDtorsFunc->signature->Params.empty() ||
1406 !callDtorsFunc->signature->Returns.empty())) {
1407 error(msg: "__wasm_call_dtors must have no argument or return values");
1408 }
1409 ctx.sym.callDtors = callDtorsFunc;
1410 } else {
1411 error(msg: "__wasm_call_dtors must be a function");
1412 }
1413 }
1414 }
1415
1416 if (errorCount())
1417 return;
1418
1419 // Create wrapped symbols for -wrap option.
1420 std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
1421
1422 // If any of our inputs are bitcode files, the LTO code generator may create
1423 // references to certain library functions that might not be explicit in the
1424 // bitcode file's symbol table. If any of those library functions are defined
1425 // in a bitcode file in an archive member, we need to arrange to use LTO to
1426 // compile those archive members by adding them to the link beforehand.
1427 //
1428 // We only need to add libcall symbols to the link before LTO if the symbol's
1429 // definition is in bitcode. Any other required libcall symbols will be added
1430 // to the link after LTO when we add the LTO object file to the link.
1431 if (!ctx.bitcodeFiles.empty()) {
1432 llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple());
1433 for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
1434 handleLibcall(name: s);
1435 }
1436 if (errorCount())
1437 return;
1438
1439 // We process the stub libraries once beofore LTO to ensure that any possible
1440 // required exports are preserved by the LTO process.
1441 processStubLibrariesPreLTO();
1442
1443 // Do link-time optimization if given files are LLVM bitcode files.
1444 // This compiles bitcode files into real object files.
1445 symtab->compileBitcodeFiles();
1446 if (errorCount())
1447 return;
1448
1449 // The LTO process can generate new undefined symbols, specifically libcall
1450 // functions. Because those symbols might be declared in a stub library we
1451 // need the process the stub libraries once again after LTO to handle all
1452 // undefined symbols, including ones that didn't exist prior to LTO.
1453 processStubLibraries();
1454
1455 writeWhyExtract();
1456
1457 // Bail out if normal linked output is skipped due to LTO.
1458 if (ctx.arg.thinLTOIndexOnly)
1459 return;
1460
1461 createOptionalSymbols();
1462
1463 // Resolve any variant symbols that were created due to signature
1464 // mismatchs.
1465 symtab->handleSymbolVariants();
1466 if (errorCount())
1467 return;
1468
1469 // Apply symbol renames for -wrap.
1470 if (!wrapped.empty())
1471 wrapSymbols(wrapped);
1472
1473 for (auto &iter : ctx.arg.exportedSymbols) {
1474 Symbol *sym = symtab->find(name: iter.first());
1475 if (sym && sym->isDefined())
1476 sym->forceExport = true;
1477 }
1478
1479 if (!ctx.arg.relocatable && !ctx.isPic) {
1480 // Add synthetic dummies for weak undefined functions. Must happen
1481 // after LTO otherwise functions may not yet have signatures.
1482 symtab->handleWeakUndefines();
1483 }
1484
1485 if (entrySym)
1486 entrySym->setHidden(false);
1487
1488 if (errorCount())
1489 return;
1490
1491 // Split WASM_SEG_FLAG_STRINGS sections into pieces in preparation for garbage
1492 // collection.
1493 splitSections();
1494
1495 // Any remaining lazy symbols should be demoted to Undefined
1496 demoteLazySymbols();
1497
1498 // Do size optimizations: garbage collection
1499 markLive();
1500
1501 // Provide the indirect function table if needed.
1502 ctx.sym.indirectFunctionTable =
1503 symtab->resolveIndirectFunctionTable(/*required =*/false);
1504
1505 if (errorCount())
1506 return;
1507
1508 // Write the result to the file.
1509 writeResult();
1510}
1511
1512} // namespace lld::wasm
1513