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