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

source code of lld/wasm/Driver.cpp