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

source code of lld/wasm/Driver.cpp