blob: 095aef575824b4f0a3ec870483cac51780489340 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:091//===- Driver.cpp ---------------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// 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
Sam Cleggc94d3932017-11-17 18:14:096//
7//===----------------------------------------------------------------------===//
8
9#include "lld/Common/Driver.h"
Sam Clegg78f766a2018-02-20 21:08:2810#include "Config.h"
Nicholas Wilsonebda41f2018-03-09 16:43:0511#include "InputChunks.h"
Andy Wingoa56e5742021-02-11 11:15:2412#include "InputElement.h"
Sam Clegg03626332018-01-31 01:45:4713#include "MarkLive.h"
Sam Cleggc94d3932017-11-17 18:14:0914#include "SymbolTable.h"
15#include "Writer.h"
Rui Ueyama3e039442017-11-28 19:58:4516#include "lld/Common/Args.h"
Sam Cleggc94d3932017-11-17 18:14:0917#include "lld/Common/ErrorHandler.h"
Sam Cleggb5767012020-03-28 00:03:3218#include "lld/Common/Filesystem.h"
Rui Ueyama2017d522017-11-28 20:39:1719#include "lld/Common/Memory.h"
Rui Ueyama35150bb2019-05-21 11:52:1420#include "lld/Common/Reproduce.h"
Nicholas Wilson531769b2018-03-13 13:30:0421#include "lld/Common/Strings.h"
Sam Cleggc94d3932017-11-17 18:14:0922#include "lld/Common/Version.h"
23#include "llvm/ADT/Twine.h"
Arthur Eubankse8140132020-12-14 17:56:2224#include "llvm/Config/llvm-config.h"
Sam Cleggc94d3932017-11-17 18:14:0925#include "llvm/Object/Wasm.h"
Thomas Lively82de51a2019-03-26 04:11:0526#include "llvm/Option/Arg.h"
Sam Cleggc94d3932017-11-17 18:14:0927#include "llvm/Option/ArgList.h"
28#include "llvm/Support/CommandLine.h"
Reid Kleckner213aea42020-03-11 22:39:2829#include "llvm/Support/Host.h"
Reid Kleckner932f0272020-05-05 03:03:1930#include "llvm/Support/Parallel.h"
Sam Cleggc94d3932017-11-17 18:14:0931#include "llvm/Support/Path.h"
32#include "llvm/Support/Process.h"
Rui Ueyama35150bb2019-05-21 11:52:1433#include "llvm/Support/TarWriter.h"
Sam Cleggc729c1b2018-05-30 18:07:5234#include "llvm/Support/TargetSelect.h"
Sam Cleggc94d3932017-11-17 18:14:0935
Sam Clegg03626332018-01-31 01:45:4736#define DEBUG_TYPE "lld"
37
Sam Cleggc94d3932017-11-17 18:14:0938using namespace llvm;
Sam Clegg45218f42018-11-27 01:08:1639using namespace llvm::object;
Sam Cleggc94d3932017-11-17 18:14:0940using namespace llvm::sys;
41using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:0942
Fangrui Song33c59ab2019-10-10 05:25:3943namespace lld {
44namespace wasm {
45Configuration *config;
Sam Cleggc94d3932017-11-17 18:14:0946
Rui Ueyama39049c02018-02-23 20:13:3847namespace {
Sam Cleggc94d3932017-11-17 18:14:0948
49// Create enum with OPT_xxx values for each option in Options.td
50enum {
51 OPT_INVALID = 0,
52#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
53#include "Options.inc"
54#undef OPTION
55};
56
Sam Cleggc729c1b2018-05-30 18:07:5257// This function is called on startup. We need this for LTO since
58// LTO calls LLVM functions to compile bitcode files to native code.
59// Technically this can be delayed until we read bitcode files, but
60// we don't bother to do lazily because the initialization is fast.
61static void initLLVM() {
62 InitializeAllTargets();
63 InitializeAllTargetMCs();
64 InitializeAllAsmPrinters();
65 InitializeAllAsmParsers();
66}
67
Sam Cleggc94d3932017-11-17 18:14:0968class LinkerDriver {
69public:
Reshabh Sharmafdd6ed82020-12-18 06:39:0170 void linkerMain(ArrayRef<const char *> argsArr);
Sam Cleggc94d3932017-11-17 18:14:0971
72private:
Rui Ueyama136d27a2019-07-11 05:40:3073 void createFiles(opt::InputArgList &args);
74 void addFile(StringRef path);
75 void addLibrary(StringRef name);
Sam Clegg8adf7ac2018-07-23 23:51:1976
77 // True if we are in --whole-archive and --no-whole-archive.
Rui Ueyama136d27a2019-07-11 05:40:3078 bool inWholeArchive = false;
Sam Clegg8adf7ac2018-07-23 23:51:1979
Rui Ueyama136d27a2019-07-11 05:40:3080 std::vector<InputFile *> files;
Sam Cleggc94d3932017-11-17 18:14:0981};
Sam Cleggc94d3932017-11-17 18:14:0982} // anonymous namespace
83
Rui Ueyamab11386f2019-11-15 05:06:5784bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
85 raw_ostream &stderrOS) {
James Y Knightd3fec7f2019-11-20 15:08:1886 lld::stdoutOS = &stdoutOS;
87 lld::stderrOS = &stderrOS;
88
Alexandre Ganeaf2efb572020-09-24 19:00:4389 errorHandler().cleanupCallback = []() { freeArena(); };
90
Rui Ueyama136d27a2019-07-11 05:40:3091 errorHandler().logName = args::getFilenameWithoutExe(args[0]);
Rui Ueyama136d27a2019-07-11 05:40:3092 errorHandler().errorLimitExceededMsg =
Sam Cleggc94d3932017-11-17 18:14:0993 "too many errors emitted, stopping now (use "
94 "-error-limit=0 to see all errors)";
James Y Knightd3fec7f2019-11-20 15:08:1895 stderrOS.enable_colors(stderrOS.has_colors());
Sam Cleggc94d3932017-11-17 18:14:0996
Rui Ueyama136d27a2019-07-11 05:40:3097 config = make<Configuration>();
98 symtab = make<SymbolTable>();
Sam Cleggc94d3932017-11-17 18:14:0999
Sam Cleggc729c1b2018-05-30 18:07:52100 initLLVM();
Reshabh Sharmafdd6ed82020-12-18 06:39:01101 LinkerDriver().linkerMain(args);
Sam Cleggc94d3932017-11-17 18:14:09102
103 // Exit immediately if we don't need to return to the caller.
104 // This saves time because the overhead of calling destructors
105 // for all globally-allocated objects is not negligible.
Rui Ueyama136d27a2019-07-11 05:40:30106 if (canExitEarly)
Sam Cleggc94d3932017-11-17 18:14:09107 exitLld(errorCount() ? 1 : 0);
108
Sam Cleggc94d3932017-11-17 18:14:09109 return !errorCount();
110}
111
Sam Cleggc94d3932017-11-17 18:14:09112// Create prefix string literals used in Options.td
113#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
114#include "Options.inc"
115#undef PREFIX
116
117// Create table mapping all options defined in Options.td
Rui Ueyama136d27a2019-07-11 05:40:30118static const opt::OptTable::Info optInfo[] = {
Sam Cleggc94d3932017-11-17 18:14:09119#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
120 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
121 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
122#include "Options.inc"
123#undef OPTION
124};
125
Benjamin Kramer54550382018-05-15 22:01:54126namespace {
Rui Ueyama39049c02018-02-23 20:13:38127class WasmOptTable : public llvm::opt::OptTable {
128public:
Rui Ueyama136d27a2019-07-11 05:40:30129 WasmOptTable() : OptTable(optInfo) {}
130 opt::InputArgList parse(ArrayRef<const char *> argv);
Rui Ueyama39049c02018-02-23 20:13:38131};
Benjamin Kramer54550382018-05-15 22:01:54132} // namespace
Rui Ueyama39049c02018-02-23 20:13:38133
Sam Cleggc94d3932017-11-17 18:14:09134// Set color diagnostics according to -color-diagnostics={auto,always,never}
135// or -no-color-diagnostics flags.
Rui Ueyama136d27a2019-07-11 05:40:30136static void handleColorDiagnostics(opt::InputArgList &args) {
137 auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
Sam Cleggc94d3932017-11-17 18:14:09138 OPT_no_color_diagnostics);
Rui Ueyama136d27a2019-07-11 05:40:30139 if (!arg)
Sam Cleggc94d3932017-11-17 18:14:09140 return;
Rui Ueyama136d27a2019-07-11 05:40:30141 if (arg->getOption().getID() == OPT_color_diagnostics) {
James Y Knightd3fec7f2019-11-20 15:08:18142 lld::errs().enable_colors(true);
Rui Ueyama136d27a2019-07-11 05:40:30143 } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
James Y Knightd3fec7f2019-11-20 15:08:18144 lld::errs().enable_colors(false);
Nico Webercac2b332018-05-10 18:19:02145 } else {
Rui Ueyama136d27a2019-07-11 05:40:30146 StringRef s = arg->getValue();
147 if (s == "always")
James Y Knightd3fec7f2019-11-20 15:08:18148 lld::errs().enable_colors(true);
Rui Ueyama136d27a2019-07-11 05:40:30149 else if (s == "never")
James Y Knightd3fec7f2019-11-20 15:08:18150 lld::errs().enable_colors(false);
Rui Ueyama136d27a2019-07-11 05:40:30151 else if (s != "auto")
152 error("unknown option: --color-diagnostics=" + s);
Sam Cleggc94d3932017-11-17 18:14:09153 }
154}
155
Sam Clegg928e9e12020-03-04 19:29:45156static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) {
157 if (auto *arg = args.getLastArg(OPT_rsp_quoting)) {
158 StringRef s = arg->getValue();
159 if (s != "windows" && s != "posix")
160 error("invalid response file quoting: " + s);
161 if (s == "windows")
162 return cl::TokenizeWindowsCommandLine;
163 return cl::TokenizeGNUCommandLine;
164 }
165 if (Triple(sys::getProcessTriple()).isOSWindows())
166 return cl::TokenizeWindowsCommandLine;
167 return cl::TokenizeGNUCommandLine;
168}
169
Sam Cleggc94d3932017-11-17 18:14:09170// Find a file by concatenating given paths.
Rui Ueyama136d27a2019-07-11 05:40:30171static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
172 SmallString<128> s;
173 path::append(s, path1, path2);
174 if (fs::exists(s))
Jonas Devlieghere3e242422020-01-30 05:30:21175 return std::string(s);
Sam Cleggc94d3932017-11-17 18:14:09176 return None;
177}
178
Rui Ueyama136d27a2019-07-11 05:40:30179opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) {
180 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
Sam Cleggc94d3932017-11-17 18:14:09181
Rui Ueyama136d27a2019-07-11 05:40:30182 unsigned missingIndex;
183 unsigned missingCount;
Sam Clegge9ce6612018-05-30 03:51:56184
Sam Clegg928e9e12020-03-04 19:29:45185 // We need to get the quoting style for response files before parsing all
186 // options so we parse here before and ignore all the options but
187 // --rsp-quoting.
Rui Ueyama136d27a2019-07-11 05:40:30188 opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
Sam Cleggc94d3932017-11-17 18:14:09189
Sam Clegg928e9e12020-03-04 19:29:45190 // Expand response files (arguments in the form of @<filename>)
191 // and then parse the argument again.
192 cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec);
193 args = this->ParseArgs(vec, missingIndex, missingCount);
194
Rui Ueyama136d27a2019-07-11 05:40:30195 handleColorDiagnostics(args);
196 for (auto *arg : args.filtered(OPT_UNKNOWN))
197 error("unknown argument: " + arg->getAsString(args));
198 return args;
Sam Cleggc94d3932017-11-17 18:14:09199}
200
Sam Clegg31efdcd2018-01-11 22:31:35201// Currently we allow a ".imports" to live alongside a library. This can
202// be used to specify a list of symbols which can be undefined at link
203// time (imported from the environment. For example libc.a include an
204// import file that lists the syscall functions it relies on at runtime.
205// In the long run this information would be better stored as a symbol
206// attribute/flag in the object file itself.
207// See: https://github.com/WebAssembly/tool-conventions/issues/35
Rui Ueyama136d27a2019-07-11 05:40:30208static void readImportFile(StringRef filename) {
209 if (Optional<MemoryBufferRef> buf = readFile(filename))
210 for (StringRef sym : args::getLines(*buf))
211 config->allowUndefinedSymbols.insert(sym);
Sam Clegg31efdcd2018-01-11 22:31:35212}
213
Sam Clegg8adf7ac2018-07-23 23:51:19214// Returns slices of MB by parsing MB as an archive file.
215// Each slice consists of a member file in the archive.
Rui Ueyama136d27a2019-07-11 05:40:30216std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef mb) {
217 std::unique_ptr<Archive> file =
218 CHECK(Archive::create(mb),
219 mb.getBufferIdentifier() + ": failed to parse archive");
Sam Clegg8adf7ac2018-07-23 23:51:19220
Rui Ueyama136d27a2019-07-11 05:40:30221 std::vector<MemoryBufferRef> v;
222 Error err = Error::success();
Fangrui Song681b1be2020-01-01 23:28:48223 for (const Archive::Child &c : file->children(err)) {
Rui Ueyama136d27a2019-07-11 05:40:30224 MemoryBufferRef mbref =
225 CHECK(c.getMemoryBufferRef(),
226 mb.getBufferIdentifier() +
Sam Clegg8adf7ac2018-07-23 23:51:19227 ": could not get the buffer for a child of the archive");
Rui Ueyama136d27a2019-07-11 05:40:30228 v.push_back(mbref);
Sam Clegg8adf7ac2018-07-23 23:51:19229 }
Rui Ueyama136d27a2019-07-11 05:40:30230 if (err)
231 fatal(mb.getBufferIdentifier() +
232 ": Archive::children failed: " + toString(std::move(err)));
Sam Clegg8adf7ac2018-07-23 23:51:19233
234 // Take ownership of memory buffers created for members of thin archives.
Rui Ueyama136d27a2019-07-11 05:40:30235 for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
236 make<std::unique_ptr<MemoryBuffer>>(std::move(mb));
Sam Clegg8adf7ac2018-07-23 23:51:19237
Rui Ueyama136d27a2019-07-11 05:40:30238 return v;
Sam Clegg8adf7ac2018-07-23 23:51:19239}
240
Rui Ueyama136d27a2019-07-11 05:40:30241void LinkerDriver::addFile(StringRef path) {
242 Optional<MemoryBufferRef> buffer = readFile(path);
243 if (!buffer.hasValue())
Sam Cleggc94d3932017-11-17 18:14:09244 return;
Rui Ueyama136d27a2019-07-11 05:40:30245 MemoryBufferRef mbref = *buffer;
Sam Cleggc94d3932017-11-17 18:14:09246
Rui Ueyama136d27a2019-07-11 05:40:30247 switch (identify_magic(mbref.getBuffer())) {
Sam Cleggc729c1b2018-05-30 18:07:52248 case file_magic::archive: {
Rui Ueyama136d27a2019-07-11 05:40:30249 SmallString<128> importFile = path;
250 path::replace_extension(importFile, ".imports");
251 if (fs::exists(importFile))
252 readImportFile(importFile.str());
Sam Clegg61d70e42019-06-25 17:49:35253
Sam Clegg8adf7ac2018-07-23 23:51:19254 // Handle -whole-archive.
Rui Ueyama136d27a2019-07-11 05:40:30255 if (inWholeArchive) {
Sam Cleggb3b4cda2020-10-13 03:45:20256 for (MemoryBufferRef &m : getArchiveMembers(mbref)) {
257 auto *object = createObjectFile(m, path);
258 // Mark object as live; object members are normally not
259 // live by default but -whole-archive is designed to treat
260 // them as such.
261 object->markLive();
262 files.push_back(object);
263 }
264
Sam Clegg8adf7ac2018-07-23 23:51:19265 return;
266 }
267
Rui Ueyama136d27a2019-07-11 05:40:30268 std::unique_ptr<Archive> file =
269 CHECK(Archive::create(mbref), path + ": failed to parse archive");
Sam Clegg61d70e42019-06-25 17:49:35270
Rui Ueyama136d27a2019-07-11 05:40:30271 if (!file->isEmpty() && !file->hasSymbolTable()) {
272 error(mbref.getBufferIdentifier() +
Sam Clegg61d70e42019-06-25 17:49:35273 ": archive has no index; run ranlib to add one");
274 }
Sam Clegg31efdcd2018-01-11 22:31:35275
Rui Ueyama136d27a2019-07-11 05:40:30276 files.push_back(make<ArchiveFile>(mbref));
Sam Clegg31efdcd2018-01-11 22:31:35277 return;
278 }
Sam Cleggc729c1b2018-05-30 18:07:52279 case file_magic::bitcode:
Sam Clegg8adf7ac2018-07-23 23:51:19280 case file_magic::wasm_object:
Rui Ueyama136d27a2019-07-11 05:40:30281 files.push_back(createObjectFile(mbref));
Sam Cleggc729c1b2018-05-30 18:07:52282 break;
283 default:
Rui Ueyama136d27a2019-07-11 05:40:30284 error("unknown file type: " + mbref.getBufferIdentifier());
Sam Cleggc729c1b2018-05-30 18:07:52285 }
Sam Cleggc94d3932017-11-17 18:14:09286}
287
288// Add a given library by searching it from input search paths.
Rui Ueyama136d27a2019-07-11 05:40:30289void LinkerDriver::addLibrary(StringRef name) {
290 for (StringRef dir : config->searchPaths) {
291 if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) {
292 addFile(*s);
Sam Cleggc94d3932017-11-17 18:14:09293 return;
294 }
295 }
296
Rui Ueyama136d27a2019-07-11 05:40:30297 error("unable to find library -l" + name);
Sam Cleggc94d3932017-11-17 18:14:09298}
299
Rui Ueyama136d27a2019-07-11 05:40:30300void LinkerDriver::createFiles(opt::InputArgList &args) {
301 for (auto *arg : args) {
302 switch (arg->getOption().getID()) {
Sam Cleggc94d3932017-11-17 18:14:09303 case OPT_l:
Rui Ueyama136d27a2019-07-11 05:40:30304 addLibrary(arg->getValue());
Sam Cleggc94d3932017-11-17 18:14:09305 break;
306 case OPT_INPUT:
Rui Ueyama136d27a2019-07-11 05:40:30307 addFile(arg->getValue());
Sam Cleggc94d3932017-11-17 18:14:09308 break;
Sam Clegg8adf7ac2018-07-23 23:51:19309 case OPT_whole_archive:
Rui Ueyama136d27a2019-07-11 05:40:30310 inWholeArchive = true;
Sam Clegg8adf7ac2018-07-23 23:51:19311 break;
312 case OPT_no_whole_archive:
Rui Ueyama136d27a2019-07-11 05:40:30313 inWholeArchive = false;
Sam Clegg8adf7ac2018-07-23 23:51:19314 break;
Sam Cleggc94d3932017-11-17 18:14:09315 }
316 }
Sam Cleggb5767012020-03-28 00:03:32317 if (files.empty() && errorCount() == 0)
318 error("no input files");
Sam Cleggc94d3932017-11-17 18:14:09319}
320
Rui Ueyama136d27a2019-07-11 05:40:30321static StringRef getEntry(opt::InputArgList &args) {
322 auto *arg = args.getLastArg(OPT_entry, OPT_no_entry);
323 if (!arg) {
324 if (args.hasArg(OPT_relocatable))
Sam Clegg09137be2019-04-04 18:40:51325 return "";
Rui Ueyama136d27a2019-07-11 05:40:30326 if (args.hasArg(OPT_shared))
Sam Clegg09137be2019-04-04 18:40:51327 return "__wasm_call_ctors";
328 return "_start";
329 }
Rui Ueyama136d27a2019-07-11 05:40:30330 if (arg->getOption().getID() == OPT_no_entry)
Sam Clegg2c096ba2017-12-08 17:58:25331 return "";
Rui Ueyama136d27a2019-07-11 05:40:30332 return arg->getValue();
Sam Clegg2c096ba2017-12-08 17:58:25333}
334
Sam Clegg206884b2020-05-01 16:14:59335// Determines what we should do if there are remaining unresolved
336// symbols after the name resolution.
337static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &args) {
338 UnresolvedPolicy errorOrWarn = args.hasFlag(OPT_error_unresolved_symbols,
339 OPT_warn_unresolved_symbols, true)
340 ? UnresolvedPolicy::ReportError
341 : UnresolvedPolicy::Warn;
342
343 if (auto *arg = args.getLastArg(OPT_unresolved_symbols)) {
344 StringRef s = arg->getValue();
345 if (s == "ignore-all")
346 return UnresolvedPolicy::Ignore;
347 if (s == "import-functions")
348 return UnresolvedPolicy::ImportFuncs;
349 if (s == "report-all")
350 return errorOrWarn;
351 error("unknown --unresolved-symbols value: " + s);
352 }
353
354 // Legacy --allow-undefined flag which is equivalent to
355 // --unresolve-symbols=ignore-all
356 if (args.hasArg(OPT_allow_undefined))
357 return UnresolvedPolicy::ImportFuncs;
358
359 return errorOrWarn;
360}
361
Sam Clegga1282a32019-05-08 16:20:05362// Initializes Config members by the command line options.
Rui Ueyama136d27a2019-07-11 05:40:30363static void readConfigs(opt::InputArgList &args) {
Sam Clegg25134072020-10-07 21:48:37364 config->bsymbolic = args.hasArg(OPT_Bsymbolic);
Rui Ueyama136d27a2019-07-11 05:40:30365 config->checkFeatures =
366 args.hasFlag(OPT_check_features, OPT_no_check_features, true);
367 config->compressRelocations = args.hasArg(OPT_compress_relocations);
368 config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
369 config->disableVerify = args.hasArg(OPT_disable_verify);
370 config->emitRelocs = args.hasArg(OPT_emit_relocs);
Dan Gohman46a32682020-06-12 19:05:40371 config->experimentalPic = args.hasArg(OPT_experimental_pic);
Rui Ueyama136d27a2019-07-11 05:40:30372 config->entry = getEntry(args);
373 config->exportAll = args.hasArg(OPT_export_all);
Rui Ueyama136d27a2019-07-11 05:40:30374 config->exportTable = args.hasArg(OPT_export_table);
Jacob Gravelle92ed86d2019-08-27 22:58:21375 config->growableTable = args.hasArg(OPT_growable_table);
Rui Ueyama136d27a2019-07-11 05:40:30376 errorHandler().fatalWarnings =
377 args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
378 config->importMemory = args.hasArg(OPT_import_memory);
379 config->sharedMemory = args.hasArg(OPT_shared_memory);
Rui Ueyama136d27a2019-07-11 05:40:30380 config->importTable = args.hasArg(OPT_import_table);
381 config->ltoo = args::getInteger(args, OPT_lto_O, 2);
382 config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
Arthur Eubankse8140132020-12-14 17:56:22383 config->ltoNewPassManager =
Arthur Eubanksa2317862020-12-14 23:03:28384 args.hasFlag(OPT_no_lto_legacy_pass_manager, OPT_lto_legacy_pass_manager,
Arthur Eubankse8140132020-12-14 17:56:22385 LLVM_ENABLE_NEW_PASS_MANAGER);
Arthur Eubanks1314a492020-12-01 20:22:27386 config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
Sam Cleggcc2da552020-03-27 23:52:27387 config->mapFile = args.getLastArgValue(OPT_Map);
Rui Ueyama136d27a2019-07-11 05:40:30388 config->optimize = args::getInteger(args, OPT_O, 0);
389 config->outputFile = args.getLastArgValue(OPT_o);
390 config->relocatable = args.hasArg(OPT_relocatable);
391 config->gcSections =
392 args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable);
393 config->mergeDataSegments =
394 args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
395 !config->relocatable);
396 config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
397 config->printGcSections =
398 args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
399 config->saveTemps = args.hasArg(OPT_save_temps);
400 config->searchPaths = args::getStrings(args, OPT_L);
401 config->shared = args.hasArg(OPT_shared);
402 config->stripAll = args.hasArg(OPT_strip_all);
403 config->stripDebug = args.hasArg(OPT_strip_debug);
404 config->stackFirst = args.hasArg(OPT_stack_first);
405 config->trace = args.hasArg(OPT_trace);
406 config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
407 config->thinLTOCachePolicy = CHECK(
408 parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
Sam Cleggc729c1b2018-05-30 18:07:52409 "--thinlto-cache-policy: invalid cache policy");
Sam Clegg206884b2020-05-01 16:14:59410 config->unresolvedSymbols = getUnresolvedSymbolPolicy(args);
Rui Ueyama136d27a2019-07-11 05:40:30411 errorHandler().verbose = args.hasArg(OPT_verbose);
412 LLVM_DEBUG(errorHandler().verbose = true);
Sam Cleggc94d3932017-11-17 18:14:09413
Rui Ueyama136d27a2019-07-11 05:40:30414 config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
415 config->globalBase = args::getInteger(args, OPT_global_base, 1024);
416 config->maxMemory = args::getInteger(args, OPT_max_memory, 0);
417 config->zStackSize =
418 args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize);
Thomas Lively82de51a2019-03-26 04:11:05419
Sam Clegge8e914e2019-08-19 16:34:51420 // Default value of exportDynamic depends on `-shared`
421 config->exportDynamic =
422 args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared);
423
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10424 // Parse wasm32/64.
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10425 if (auto *arg = args.getLastArg(OPT_m)) {
426 StringRef s = arg->getValue();
427 if (s == "wasm32")
428 config->is64 = false;
429 else if (s == "wasm64")
430 config->is64 = true;
431 else
432 error("invalid target architecture: " + s);
433 }
434
Fangrui Songeb4663d2020-03-17 19:40:19435 // --threads= takes a positive integer and provides the default value for
436 // --thinlto-jobs=.
437 if (auto *arg = args.getLastArg(OPT_threads)) {
438 StringRef v(arg->getValue());
439 unsigned threads = 0;
440 if (!llvm::to_integer(v, threads, 0) || threads == 0)
441 error(arg->getSpelling() + ": expected a positive integer, but got '" +
442 arg->getValue() + "'");
443 parallel::strategy = hardware_concurrency(threads);
444 config->thinLTOJobs = v;
445 }
446 if (auto *arg = args.getLastArg(OPT_thinlto_jobs))
447 config->thinLTOJobs = arg->getValue();
448
Rui Ueyama136d27a2019-07-11 05:40:30449 if (auto *arg = args.getLastArg(OPT_features)) {
450 config->features =
Thomas Lively82de51a2019-03-26 04:11:05451 llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
Rui Ueyama136d27a2019-07-11 05:40:30452 for (StringRef s : arg->getValues())
Benjamin Krameradcd0262020-01-28 19:23:46453 config->features->push_back(std::string(s));
Thomas Lively82de51a2019-03-26 04:11:05454 }
Sam Cleggcc2da552020-03-27 23:52:27455
456 if (args.hasArg(OPT_print_map))
457 config->mapFile = "-";
Sam Cleggd5f65062018-11-15 18:09:41458}
Sam Cleggc94d3932017-11-17 18:14:09459
Sam Clegga1282a32019-05-08 16:20:05460// Some Config members do not directly correspond to any particular
461// command line options, but computed based on other Config values.
462// This function initialize such members. See Config.h for the details
463// of these values.
464static void setConfigs() {
Rui Ueyama136d27a2019-07-11 05:40:30465 config->isPic = config->pie || config->shared;
Sam Clegga1282a32019-05-08 16:20:05466
Rui Ueyama136d27a2019-07-11 05:40:30467 if (config->isPic) {
468 if (config->exportTable)
Sam Clegga1282a32019-05-08 16:20:05469 error("-shared/-pie is incompatible with --export-table");
Rui Ueyama136d27a2019-07-11 05:40:30470 config->importTable = true;
Sam Clegga1282a32019-05-08 16:20:05471 }
472
Andy Wingo48219d02021-02-16 12:28:44473 if (config->relocatable) {
474 if (config->exportTable)
475 error("--relocatable is incompatible with --export-table");
476 if (config->growableTable)
477 error("--relocatable is incompatible with --growable-table");
478 // Ignore any --import-table, as it's redundant.
479 config->importTable = true;
480 }
481
Rui Ueyama136d27a2019-07-11 05:40:30482 if (config->shared) {
483 config->importMemory = true;
Sam Clegg206884b2020-05-01 16:14:59484 config->unresolvedSymbols = UnresolvedPolicy::ImportFuncs;
Sam Clegga1282a32019-05-08 16:20:05485 }
486}
487
Sam Cleggd5f65062018-11-15 18:09:41488// Some command line options or some combinations of them are not allowed.
489// This function checks for such errors.
Rui Ueyama136d27a2019-07-11 05:40:30490static void checkOptions(opt::InputArgList &args) {
491 if (!config->stripDebug && !config->stripAll && config->compressRelocations)
Sam Clegg30161dc2018-08-17 19:42:46492 error("--compress-relocations is incompatible with output debug"
493 " information. Please pass --strip-debug or --strip-all");
Sam Cleggfb983cd2018-05-18 23:28:05494
Rui Ueyama136d27a2019-07-11 05:40:30495 if (config->ltoo > 3)
496 error("invalid optimization level for LTO: " + Twine(config->ltoo));
497 if (config->ltoPartitions == 0)
Sam Cleggc729c1b2018-05-30 18:07:52498 error("--lto-partitions: number of threads must be > 0");
Alexandre Ganea09158252020-03-27 14:20:39499 if (!get_threadpool_strategy(config->thinLTOJobs))
500 error("--thinlto-jobs: invalid job count: " + config->thinLTOJobs);
Sam Cleggc729c1b2018-05-30 18:07:52501
Rui Ueyama136d27a2019-07-11 05:40:30502 if (config->pie && config->shared)
Sam Cleggbfb75342018-11-15 00:37:21503 error("-shared and -pie may not be used together");
504
Rui Ueyama136d27a2019-07-11 05:40:30505 if (config->outputFile.empty())
Sam Cleggc94d3932017-11-17 18:14:09506 error("no output file specified");
507
Rui Ueyama136d27a2019-07-11 05:40:30508 if (config->importTable && config->exportTable)
Rui Ueyama09612182018-03-30 16:06:14509 error("--import-table and --export-table may not be used together");
510
Rui Ueyama136d27a2019-07-11 05:40:30511 if (config->relocatable) {
512 if (!config->entry.empty())
Sam Clegg03626332018-01-31 01:45:47513 error("entry point specified for relocatable output file");
Rui Ueyama136d27a2019-07-11 05:40:30514 if (config->gcSections)
Sam Clegg03626332018-01-31 01:45:47515 error("-r and --gc-sections may not be used together");
Rui Ueyama136d27a2019-07-11 05:40:30516 if (config->compressRelocations)
Sam Clegg30161dc2018-08-17 19:42:46517 error("-r -and --compress-relocations may not be used together");
Rui Ueyama136d27a2019-07-11 05:40:30518 if (args.hasArg(OPT_undefined))
Sam Clegg03626332018-01-31 01:45:47519 error("-r -and --undefined may not be used together");
Rui Ueyama136d27a2019-07-11 05:40:30520 if (config->pie)
Sam Cleggbfb75342018-11-15 00:37:21521 error("-r and -pie may not be used together");
Thomas Lively6474d1b2020-04-14 02:16:20522 if (config->sharedMemory)
523 error("-r and --shared-memory may not be used together");
Sam Clegg03626332018-01-31 01:45:47524 }
Dan Gohman46a32682020-06-12 19:05:40525
526 // To begin to prepare for Module Linking-style shared libraries, start
527 // warning about uses of `-shared` and related flags outside of Experimental
528 // mode, to give anyone using them a heads-up that they will be changing.
529 //
530 // Also, warn about flags which request explicit exports.
531 if (!config->experimentalPic) {
532 // -shared will change meaning when Module Linking is implemented.
533 if (config->shared) {
534 warn("creating shared libraries, with -shared, is not yet stable");
535 }
536
537 // -pie will change meaning when Module Linking is implemented.
538 if (config->pie) {
539 warn("creating PIEs, with -pie, is not yet stable");
540 }
541 }
Sam Clegg25134072020-10-07 21:48:37542
543 if (config->bsymbolic && !config->shared) {
544 warn("-Bsymbolic is only meaningful when combined with -shared");
545 }
Sam Cleggd5f65062018-11-15 18:09:41546}
547
548// Force Sym to be entered in the output. Used for -u or equivalent.
Rui Ueyama136d27a2019-07-11 05:40:30549static Symbol *handleUndefined(StringRef name) {
550 Symbol *sym = symtab->find(name);
551 if (!sym)
Sam Cleggd5f65062018-11-15 18:09:41552 return nullptr;
553
554 // Since symbol S may not be used inside the program, LTO may
555 // eliminate it. Mark the symbol as "used" to prevent it.
Rui Ueyama136d27a2019-07-11 05:40:30556 sym->isUsedInRegularObj = true;
Sam Cleggd5f65062018-11-15 18:09:41557
Rui Ueyama136d27a2019-07-11 05:40:30558 if (auto *lazySym = dyn_cast<LazySymbol>(sym))
559 lazySym->fetch();
Sam Cleggd5f65062018-11-15 18:09:41560
Rui Ueyama136d27a2019-07-11 05:40:30561 return sym;
Sam Cleggd5f65062018-11-15 18:09:41562}
563
Sam Clegg9cd98582019-12-20 01:23:59564static void handleLibcall(StringRef name) {
565 Symbol *sym = symtab->find(name);
566 if (!sym)
567 return;
568
569 if (auto *lazySym = dyn_cast<LazySymbol>(sym)) {
570 MemoryBufferRef mb = lazySym->getMemberBuffer();
571 if (isBitcode(mb))
572 lazySym->fetch();
573 }
574}
575
Sam Clegg2dad4e22018-11-15 18:15:54576static UndefinedGlobal *
Rui Ueyama136d27a2019-07-11 05:40:30577createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
Sam Cleggf6f4b982019-09-23 21:28:29578 auto *sym = cast<UndefinedGlobal>(symtab->addUndefinedGlobal(
Sam Cleggbd481272020-02-06 05:18:55579 name, None, None, WASM_SYMBOL_UNDEFINED, nullptr, type));
Rui Ueyama136d27a2019-07-11 05:40:30580 config->allowUndefinedSymbols.insert(sym->getName());
581 sym->isUsedInRegularObj = true;
582 return sym;
Sam Clegg2dad4e22018-11-15 18:15:54583}
584
Sam Clegg29a30562020-11-10 01:52:39585static InputGlobal *createGlobal(StringRef name, bool isMutable) {
Guanzhong Chen5204f762019-07-19 23:34:16586 llvm::wasm::WasmGlobal wasmGlobal;
Wouter van Oortmerssen29f8c9f2020-07-06 20:34:16587 if (config->is64.getValueOr(false)) {
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10588 wasmGlobal.Type = {WASM_TYPE_I64, isMutable};
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10589 wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I64_CONST;
Sam Clegg29a30562020-11-10 01:52:39590 wasmGlobal.InitExpr.Value.Int64 = 0;
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10591 } else {
592 wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10593 wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
Sam Clegg29a30562020-11-10 01:52:39594 wasmGlobal.InitExpr.Value.Int32 = 0;
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10595 }
Guanzhong Chen5204f762019-07-19 23:34:16596 wasmGlobal.SymbolName = name;
Sam Clegg29a30562020-11-10 01:52:39597 return make<InputGlobal>(wasmGlobal, nullptr);
598}
599
600static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable) {
601 InputGlobal *g = createGlobal(name, isMutable);
602 return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN, g);
603}
604
605static GlobalSymbol *createOptionalGlobal(StringRef name, bool isMutable) {
606 InputGlobal *g = createGlobal(name, isMutable);
Sam Clegg88e40562021-02-09 01:12:23607 return symtab->addOptionalGlobalSymbol(name, g);
Guanzhong Chen5204f762019-07-19 23:34:16608}
609
Sam Clegg2dad4e22018-11-15 18:15:54610// Create ABI-defined synthetic symbols
611static void createSyntheticSymbols() {
Sam Cleggdbfea282019-08-08 23:56:21612 if (config->relocatable)
613 return;
614
Rui Ueyama136d27a2019-07-11 05:40:30615 static WasmSignature nullSignature = {{}, {}};
Guanzhong Chen42bba4b2019-07-16 22:00:45616 static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10617 static WasmSignature i64ArgSignature = {{}, {ValType::I64}};
Rui Ueyama136d27a2019-07-11 05:40:30618 static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10619 static llvm::wasm::WasmGlobalType globalTypeI64 = {WASM_TYPE_I64, false};
Rui Ueyama136d27a2019-07-11 05:40:30620 static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
Sam Clegg2dad4e22018-11-15 18:15:54621 true};
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10622 static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64,
623 true};
Sam Cleggdbfea282019-08-08 23:56:21624 WasmSym::callCtors = symtab->addSyntheticFunction(
625 "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
626 make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
Sam Clegg2dad4e22018-11-15 18:15:54627
Sam Cleggdbfea282019-08-08 23:56:21628 if (config->isPic) {
Wouter van Oortmerssen29f8c9f2020-07-06 20:34:16629 WasmSym::stackPointer =
630 createUndefinedGlobal("__stack_pointer", config->is64.getValueOr(false)
631 ? &mutableGlobalTypeI64
632 : &mutableGlobalTypeI32);
Sam Cleggfd11ce32019-07-11 13:13:25633 // For PIC code, we import two global variables (__memory_base and
634 // __table_base) from the environment and use these as the offset at
635 // which to load our static data and function table.
636 // See:
637 // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
Wouter van Oortmerssenb9a539c2020-06-15 22:31:10638 WasmSym::memoryBase = createUndefinedGlobal(
Wouter van Oortmerssen29f8c9f2020-07-06 20:34:16639 "__memory_base",
640 config->is64.getValueOr(false) ? &globalTypeI64 : &globalTypeI32);
Sam Cleggfd11ce32019-07-11 13:13:25641 WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32);
642 WasmSym::memoryBase->markLive();
643 WasmSym::tableBase->markLive();
Sam Clegg2dad4e22018-11-15 18:15:54644 } else {
Sam Clegg2dad4e22018-11-15 18:15:54645 // For non-PIC code
Sam Clegg29a30562020-11-10 01:52:39646 WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true);
Sam Cleggad1cc142019-08-08 18:22:03647 WasmSym::stackPointer->markLive();
Sam Clegg2dad4e22018-11-15 18:15:54648 }
649
Sam Clegg07b6aeb2020-12-18 18:02:29650 if (config->sharedMemory && !config->relocatable) {
Sam Clegg29a30562020-11-10 01:52:39651 WasmSym::tlsBase = createGlobalVariable("__tls_base", true);
652 WasmSym::tlsSize = createGlobalVariable("__tls_size", false);
653 WasmSym::tlsAlign = createGlobalVariable("__tls_align", false);
Guanzhong Chen42bba4b2019-07-16 22:00:45654 WasmSym::initTLS = symtab->addSyntheticFunction(
655 "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
Wouter van Oortmerssen29f8c9f2020-07-06 20:34:16656 make<SyntheticFunction>(
657 config->is64.getValueOr(false) ? i64ArgSignature : i32ArgSignature,
658 "__wasm_init_tls"));
Guanzhong Chen42bba4b2019-07-16 22:00:45659 }
Sam Cleggcaa0db12019-08-08 16:58:36660}
Guanzhong Chen42bba4b2019-07-16 22:00:45661
Sam Cleggcaa0db12019-08-08 16:58:36662static void createOptionalSymbols() {
Sam Cleggdbfea282019-08-08 23:56:21663 if (config->relocatable)
664 return;
665
666 WasmSym::dsoHandle = symtab->addOptionalDataSymbol("__dso_handle");
Sam Cleggcaa0db12019-08-08 16:58:36667
Guanzhong Chenc5ccbf52019-08-08 22:40:04668 if (!config->shared)
Sam Cleggcaa0db12019-08-08 16:58:36669 WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
Guanzhong Chenc5ccbf52019-08-08 22:40:04670
671 if (!config->isPic) {
Sam Cleggcaa0db12019-08-08 16:58:36672 WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
673 WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
Sam Clegg7185a732019-08-13 17:02:02674 WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base");
675 WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base");
Sam Cleggcaa0db12019-08-08 16:58:36676 }
Sam Clegg29a30562020-11-10 01:52:39677
678 // For non-shared memory programs we still need to define __tls_base since we
679 // allow object files built with TLS to be linked into single threaded
680 // programs, and such object files can contains refernced to this symbol.
681 //
682 // However, in this case __tls_base is immutable and points directly to the
683 // start of the `.tdata` static segment.
684 //
685 // __tls_size and __tls_align are not needed in this case since they are only
686 // needed for __wasm_init_tls (which we do not create in this case).
687 if (!config->sharedMemory)
688 WasmSym::tlsBase = createOptionalGlobal("__tls_base", false);
Sam Clegg2dad4e22018-11-15 18:15:54689}
690
Rui Ueyama35150bb2019-05-21 11:52:14691// Reconstructs command line arguments so that so that you can re-run
692// the same command with the same inputs. This is for --reproduce.
Rui Ueyama136d27a2019-07-11 05:40:30693static std::string createResponseFile(const opt::InputArgList &args) {
694 SmallString<0> data;
695 raw_svector_ostream os(data);
Rui Ueyama35150bb2019-05-21 11:52:14696
697 // Copy the command line to the output while rewriting paths.
Rui Ueyama136d27a2019-07-11 05:40:30698 for (auto *arg : args) {
699 switch (arg->getOption().getID()) {
Rui Ueyama35150bb2019-05-21 11:52:14700 case OPT_reproduce:
701 break;
702 case OPT_INPUT:
Rui Ueyama136d27a2019-07-11 05:40:30703 os << quote(relativeToRoot(arg->getValue())) << "\n";
Rui Ueyama35150bb2019-05-21 11:52:14704 break;
705 case OPT_o:
706 // If -o path contains directories, "lld @response.txt" will likely
707 // fail because the archive we are creating doesn't contain empty
708 // directories for the output path (-o doesn't create directories).
709 // Strip directories to prevent the issue.
Rui Ueyama136d27a2019-07-11 05:40:30710 os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
Rui Ueyama35150bb2019-05-21 11:52:14711 break;
712 default:
Rui Ueyama136d27a2019-07-11 05:40:30713 os << toString(*arg) << "\n";
Rui Ueyama35150bb2019-05-21 11:52:14714 }
715 }
Benjamin Krameradcd0262020-01-28 19:23:46716 return std::string(data.str());
Rui Ueyama35150bb2019-05-21 11:52:14717}
718
Sam Clegga5ca34e2019-05-24 14:14:25719// The --wrap option is a feature to rename symbols so that you can write
720// wrappers for existing functions. If you pass `-wrap=foo`, all
721// occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
722// expected to write `wrap_foo` function as a wrapper). The original
723// symbol becomes accessible as `real_foo`, so you can call that from your
724// wrapper.
725//
726// This data structure is instantiated for each -wrap option.
727struct WrappedSymbol {
Rui Ueyama136d27a2019-07-11 05:40:30728 Symbol *sym;
729 Symbol *real;
730 Symbol *wrap;
Sam Clegga5ca34e2019-05-24 14:14:25731};
732
Rui Ueyama136d27a2019-07-11 05:40:30733static Symbol *addUndefined(StringRef name) {
Sam Cleggbd481272020-02-06 05:18:55734 return symtab->addUndefinedFunction(name, None, None, WASM_SYMBOL_UNDEFINED,
Sam Cleggf6f4b982019-09-23 21:28:29735 nullptr, nullptr, false);
Sam Clegga5ca34e2019-05-24 14:14:25736}
737
738// Handles -wrap option.
739//
740// This function instantiates wrapper symbols. At this point, they seem
741// like they are not being used at all, so we explicitly set some flags so
742// that LTO won't eliminate them.
Rui Ueyama136d27a2019-07-11 05:40:30743static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
744 std::vector<WrappedSymbol> v;
745 DenseSet<StringRef> seen;
Sam Clegga5ca34e2019-05-24 14:14:25746
Rui Ueyama136d27a2019-07-11 05:40:30747 for (auto *arg : args.filtered(OPT_wrap)) {
748 StringRef name = arg->getValue();
749 if (!seen.insert(name).second)
Sam Clegga5ca34e2019-05-24 14:14:25750 continue;
751
Rui Ueyama136d27a2019-07-11 05:40:30752 Symbol *sym = symtab->find(name);
753 if (!sym)
Sam Clegga5ca34e2019-05-24 14:14:25754 continue;
755
Rui Ueyama136d27a2019-07-11 05:40:30756 Symbol *real = addUndefined(saver.save("__real_" + name));
757 Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
758 v.push_back({sym, real, wrap});
Sam Clegga5ca34e2019-05-24 14:14:25759
760 // We want to tell LTO not to inline symbols to be overwritten
761 // because LTO doesn't know the final symbol contents after renaming.
Rui Ueyama136d27a2019-07-11 05:40:30762 real->canInline = false;
763 sym->canInline = false;
Sam Clegga5ca34e2019-05-24 14:14:25764
765 // Tell LTO not to eliminate these symbols.
Rui Ueyama136d27a2019-07-11 05:40:30766 sym->isUsedInRegularObj = true;
767 wrap->isUsedInRegularObj = true;
768 real->isUsedInRegularObj = false;
Sam Clegga5ca34e2019-05-24 14:14:25769 }
Rui Ueyama136d27a2019-07-11 05:40:30770 return v;
Sam Clegga5ca34e2019-05-24 14:14:25771}
772
773// Do renaming for -wrap by updating pointers to symbols.
774//
775// When this function is executed, only InputFiles and symbol table
776// contain pointers to symbol objects. We visit them to replace pointers,
777// so that wrapped symbols are swapped as instructed by the command line.
Rui Ueyama136d27a2019-07-11 05:40:30778static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
779 DenseMap<Symbol *, Symbol *> map;
780 for (const WrappedSymbol &w : wrapped) {
781 map[w.sym] = w.wrap;
782 map[w.real] = w.sym;
Sam Clegga5ca34e2019-05-24 14:14:25783 }
784
785 // Update pointers in input files.
Rui Ueyama136d27a2019-07-11 05:40:30786 parallelForEach(symtab->objectFiles, [&](InputFile *file) {
787 MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
788 for (size_t i = 0, e = syms.size(); i != e; ++i)
789 if (Symbol *s = map.lookup(syms[i]))
790 syms[i] = s;
Sam Clegga5ca34e2019-05-24 14:14:25791 });
792
793 // Update pointers in the symbol table.
Rui Ueyama136d27a2019-07-11 05:40:30794 for (const WrappedSymbol &w : wrapped)
795 symtab->wrap(w.sym, w.real, w.wrap);
Sam Clegga5ca34e2019-05-24 14:14:25796}
797
Reshabh Sharmafdd6ed82020-12-18 06:39:01798void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
Rui Ueyama136d27a2019-07-11 05:40:30799 WasmOptTable parser;
800 opt::InputArgList args = parser.parse(argsArr.slice(1));
Sam Cleggd5f65062018-11-15 18:09:41801
802 // Handle --help
Rui Ueyama136d27a2019-07-11 05:40:30803 if (args.hasArg(OPT_help)) {
Rui Ueyamab11386f2019-11-15 05:06:57804 parser.PrintHelp(lld::outs(),
Rui Ueyama136d27a2019-07-11 05:40:30805 (std::string(argsArr[0]) + " [options] file...").c_str(),
Sam Cleggd5f65062018-11-15 18:09:41806 "LLVM Linker", false);
807 return;
808 }
809
810 // Handle --version
Rui Ueyama136d27a2019-07-11 05:40:30811 if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) {
Rui Ueyamab11386f2019-11-15 05:06:57812 lld::outs() << getLLDVersion() << "\n";
Sam Cleggd5f65062018-11-15 18:09:41813 return;
814 }
815
Rui Ueyama35150bb2019-05-21 11:52:14816 // Handle --reproduce
Rui Ueyama136d27a2019-07-11 05:40:30817 if (auto *arg = args.getLastArg(OPT_reproduce)) {
818 StringRef path = arg->getValue();
819 Expected<std::unique_ptr<TarWriter>> errOrWriter =
820 TarWriter::create(path, path::stem(path));
821 if (errOrWriter) {
822 tar = std::move(*errOrWriter);
823 tar->append("response.txt", createResponseFile(args));
824 tar->append("version.txt", getLLDVersion() + "\n");
Rui Ueyama35150bb2019-05-21 11:52:14825 } else {
Rui Ueyama136d27a2019-07-11 05:40:30826 error("--reproduce: " + toString(errOrWriter.takeError()));
Rui Ueyama35150bb2019-05-21 11:52:14827 }
828 }
829
Sam Cleggd5f65062018-11-15 18:09:41830 // Parse and evaluate -mllvm options.
Rui Ueyama136d27a2019-07-11 05:40:30831 std::vector<const char *> v;
832 v.push_back("wasm-ld (LLVM option parsing)");
833 for (auto *arg : args.filtered(OPT_mllvm))
834 v.push_back(arg->getValue());
Alexandre Ganeaf2efb572020-09-24 19:00:43835 cl::ResetAllOptionOccurrences();
Rui Ueyama136d27a2019-07-11 05:40:30836 cl::ParseCommandLineOptions(v.size(), v.data());
Sam Cleggd5f65062018-11-15 18:09:41837
Rui Ueyama136d27a2019-07-11 05:40:30838 errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
Sam Cleggd5f65062018-11-15 18:09:41839
Rui Ueyama136d27a2019-07-11 05:40:30840 readConfigs(args);
Sam Cleggb5767012020-03-28 00:03:32841
842 createFiles(args);
843 if (errorCount())
844 return;
845
Sam Clegga1282a32019-05-08 16:20:05846 setConfigs();
Rui Ueyama136d27a2019-07-11 05:40:30847 checkOptions(args);
Sam Cleggb5767012020-03-28 00:03:32848 if (errorCount())
849 return;
Sam Cleggd5f65062018-11-15 18:09:41850
Rui Ueyama136d27a2019-07-11 05:40:30851 if (auto *arg = args.getLastArg(OPT_allow_undefined_file))
852 readImportFile(arg->getValue());
Sam Cleggd5f65062018-11-15 18:09:41853
Sam Cleggb5767012020-03-28 00:03:32854 // Fail early if the output file or map file is not writable. If a user has a
855 // long link, e.g. due to a large LTO link, they do not wish to run it and
856 // find that it failed because there was a mistake in their command-line.
857 if (auto e = tryCreateFile(config->outputFile))
858 error("cannot open output file " + config->outputFile + ": " + e.message());
Sam Cleggcc2da552020-03-27 23:52:27859 if (auto e = tryCreateFile(config->mapFile))
860 error("cannot open map file " + config->mapFile + ": " + e.message());
Sam Cleggb5767012020-03-28 00:03:32861 if (errorCount())
Sam Cleggd5f65062018-11-15 18:09:41862 return;
Sam Cleggc94d3932017-11-17 18:14:09863
Sam Clegg1f3f7742019-02-06 02:35:18864 // Handle --trace-symbol.
Rui Ueyama136d27a2019-07-11 05:40:30865 for (auto *arg : args.filtered(OPT_trace_symbol))
866 symtab->trace(arg->getValue());
Sam Clegg1f3f7742019-02-06 02:35:18867
Sam Clegga6f40642021-04-05 15:00:30868 for (auto *arg : args.filtered(OPT_export_if_defined))
Rui Ueyama136d27a2019-07-11 05:40:30869 config->exportedSymbols.insert(arg->getValue());
Sam Clegg7d4ec5a2019-05-31 22:51:59870
Sam Clegga6f40642021-04-05 15:00:30871 for (auto *arg : args.filtered(OPT_export)) {
872 config->exportedSymbols.insert(arg->getValue());
873 config->requiredExports.push_back(arg->getValue());
874 }
875
Sam Cleggdbfea282019-08-08 23:56:21876 createSyntheticSymbols();
Sam Cleggc94d3932017-11-17 18:14:09877
Sam Cleggc94d3932017-11-17 18:14:09878 // Add all files to the symbol table. This will add almost all
879 // symbols that we need to the symbol table.
Rui Ueyama136d27a2019-07-11 05:40:30880 for (InputFile *f : files)
881 symtab->addFile(f);
Sam Cleggc729c1b2018-05-30 18:07:52882 if (errorCount())
883 return;
Sam Cleggc94d3932017-11-17 18:14:09884
Sam Clegg47e2b6b2018-08-04 00:04:06885 // Handle the `--undefined <sym>` options.
Rui Ueyama136d27a2019-07-11 05:40:30886 for (auto *arg : args.filtered(OPT_undefined))
887 handleUndefined(arg->getValue());
Sam Clegg47e2b6b2018-08-04 00:04:06888
Sam Clegg7d4ec5a2019-05-31 22:51:59889 // Handle the `--export <sym>` options
890 // This works like --undefined but also exports the symbol if its found
Sam Clegga6f40642021-04-05 15:00:30891 for (auto &iter : config->exportedSymbols)
892 handleUndefined(iter.first());
Sam Clegg7d4ec5a2019-05-31 22:51:59893
Rui Ueyama136d27a2019-07-11 05:40:30894 Symbol *entrySym = nullptr;
895 if (!config->relocatable && !config->entry.empty()) {
896 entrySym = handleUndefined(config->entry);
897 if (entrySym && entrySym->isDefined())
898 entrySym->forceExport = true;
Sam Clegg09137be2019-04-04 18:40:51899 else
Kazuaki Ishizaki7c5fcb32020-04-01 16:21:08900 error("entry symbol not defined (pass --no-entry to suppress): " +
Rui Ueyama136d27a2019-07-11 05:40:30901 config->entry);
Sam Clegg47e2b6b2018-08-04 00:04:06902 }
903
Dan Gohman6cd85112020-10-01 00:21:57904 // If the user code defines a `__wasm_call_dtors` function, remember it so
905 // that we can call it from the command export wrappers. Unlike
906 // `__wasm_call_ctors` which we synthesize, `__wasm_call_dtors` is defined
907 // by libc/etc., because destructors are registered dynamically with
908 // `__cxa_atexit` and friends.
909 if (!config->relocatable && !config->shared &&
910 !WasmSym::callCtors->isUsedInRegularObj &&
911 WasmSym::callCtors->getName() != config->entry &&
912 !config->exportedSymbols.count(WasmSym::callCtors->getName())) {
913 if (Symbol *callDtors = handleUndefined("__wasm_call_dtors")) {
914 if (auto *callDtorsFunc = dyn_cast<DefinedFunction>(callDtors)) {
915 if (callDtorsFunc->signature &&
916 (!callDtorsFunc->signature->Params.empty() ||
917 !callDtorsFunc->signature->Returns.empty())) {
918 error("__wasm_call_dtors must have no argument or return values");
919 }
920 WasmSym::callDtors = callDtorsFunc;
921 } else {
922 error("__wasm_call_dtors must be a function");
923 }
924 }
925 }
926
Sam Clegg040ef102019-08-27 04:27:57927 createOptionalSymbols();
928
Sam Clegg47e2b6b2018-08-04 00:04:06929 if (errorCount())
930 return;
931
Sam Clegga5ca34e2019-05-24 14:14:25932 // Create wrapped symbols for -wrap option.
Rui Ueyama136d27a2019-07-11 05:40:30933 std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
Sam Clegga5ca34e2019-05-24 14:14:25934
Sam Clegg9cd98582019-12-20 01:23:59935 // If any of our inputs are bitcode files, the LTO code generator may create
936 // references to certain library functions that might not be explicit in the
937 // bitcode file's symbol table. If any of those library functions are defined
938 // in a bitcode file in an archive member, we need to arrange to use LTO to
939 // compile those archive members by adding them to the link beforehand.
940 //
941 // We only need to add libcall symbols to the link before LTO if the symbol's
942 // definition is in bitcode. Any other required libcall symbols will be added
943 // to the link after LTO when we add the LTO object file to the link.
944 if (!symtab->bitcodeFiles.empty())
945 for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
946 handleLibcall(s);
947 if (errorCount())
948 return;
949
Sam Cleggc729c1b2018-05-30 18:07:52950 // Do link-time optimization if given files are LLVM bitcode files.
951 // This compiles bitcode files into real object files.
Rui Ueyama136d27a2019-07-11 05:40:30952 symtab->addCombinedLTOObject();
Sam Cleggc729c1b2018-05-30 18:07:52953 if (errorCount())
954 return;
955
Sam Clegg6540e572019-02-20 23:19:31956 // Resolve any variant symbols that were created due to signature
957 // mismatchs.
Rui Ueyama136d27a2019-07-11 05:40:30958 symtab->handleSymbolVariants();
Sam Clegg6540e572019-02-20 23:19:31959 if (errorCount())
960 return;
961
Sam Clegga5ca34e2019-05-24 14:14:25962 // Apply symbol renames for -wrap.
Rui Ueyama136d27a2019-07-11 05:40:30963 if (!wrapped.empty())
964 wrapSymbols(wrapped);
Sam Clegga5ca34e2019-05-24 14:14:25965
Sam Clegga6f40642021-04-05 15:00:30966 for (auto &iter : config->exportedSymbols) {
967 Symbol *sym = symtab->find(iter.first());
Rui Ueyama136d27a2019-07-11 05:40:30968 if (sym && sym->isDefined())
969 sym->forceExport = true;
Sam Clegg6540e572019-02-20 23:19:31970 }
971
Sam Clegge1617d22021-02-12 16:59:21972 if (!config->relocatable && !config->isPic) {
Sam Clegg6540e572019-02-20 23:19:31973 // Add synthetic dummies for weak undefined functions. Must happen
974 // after LTO otherwise functions may not yet have signatures.
Rui Ueyama136d27a2019-07-11 05:40:30975 symtab->handleWeakUndefines();
Sam Clegg6540e572019-02-20 23:19:31976 }
977
Rui Ueyama136d27a2019-07-11 05:40:30978 if (entrySym)
979 entrySym->setHidden(false);
Sam Clegg0f0a4282018-01-20 01:44:45980
Sam Clegg2c096ba2017-12-08 17:58:25981 if (errorCount())
982 return;
Sam Cleggc94d3932017-11-17 18:14:09983
Sam Clegg03626332018-01-31 01:45:47984 // Do size optimizations: garbage collection
Sam Cleggffd0aaf2018-06-22 15:13:10985 markLive();
Sam Clegg03626332018-01-31 01:45:47986
Andy Wingoe638d8b2021-03-03 10:13:25987 // Provide the indirect function table if needed.
988 WasmSym::indirectFunctionTable =
989 symtab->resolveIndirectFunctionTable(/*required =*/false);
Andy Wingo63393822021-01-14 09:15:56990
Andy Wingo48219d02021-02-16 12:28:44991 if (errorCount())
992 return;
Andy Wingo63393822021-01-14 09:15:56993
Sam Cleggc94d3932017-11-17 18:14:09994 // Write the result to the file.
995 writeResult();
996}
Fangrui Song33c59ab2019-10-10 05:25:39997
998} // namespace wasm
999} // namespace lld