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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of lld/wasm/Driver.cpp