blob: d780491607413339b90583af727a68594a7a5c25 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- Driver.cpp ---------------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/Common/Driver.h"
11#include "Config.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000012#include "SymbolTable.h"
13#include "Writer.h"
Rui Ueyama3e039442017-11-28 19:58:45 +000014#include "lld/Common/Args.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000015#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:17 +000016#include "lld/Common/Memory.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000017#include "lld/Common/Threads.h"
18#include "lld/Common/Version.h"
19#include "llvm/ADT/Twine.h"
20#include "llvm/Object/Wasm.h"
21#include "llvm/Option/ArgList.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/Process.h"
25
26using namespace llvm;
27using namespace llvm::sys;
28using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:09 +000029
30using namespace lld;
31using namespace lld::wasm;
32
33namespace {
34
35// Parses command line options.
36class WasmOptTable : public llvm::opt::OptTable {
37public:
38 WasmOptTable();
39 llvm::opt::InputArgList parse(ArrayRef<const char *> Argv);
40};
41
42// Create enum with OPT_xxx values for each option in Options.td
43enum {
44 OPT_INVALID = 0,
45#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
46#include "Options.inc"
47#undef OPTION
48};
49
50class LinkerDriver {
51public:
52 void link(ArrayRef<const char *> ArgsArr);
53
54private:
55 void createFiles(llvm::opt::InputArgList &Args);
56 void addFile(StringRef Path);
57 void addLibrary(StringRef Name);
58 std::vector<InputFile *> Files;
59};
60
61} // anonymous namespace
62
Sam Cleggc94d3932017-11-17 18:14:09 +000063Configuration *lld::wasm::Config;
Sam Cleggc94d3932017-11-17 18:14:09 +000064
65bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly,
66 raw_ostream &Error) {
67 errorHandler().LogName = Args[0];
68 errorHandler().ErrorOS = &Error;
69 errorHandler().ColorDiagnostics = Error.has_colors();
70 errorHandler().ErrorLimitExceededMsg =
71 "too many errors emitted, stopping now (use "
72 "-error-limit=0 to see all errors)";
73
74 Config = make<Configuration>();
75 Symtab = make<SymbolTable>();
76
77 LinkerDriver().link(Args);
78
79 // Exit immediately if we don't need to return to the caller.
80 // This saves time because the overhead of calling destructors
81 // for all globally-allocated objects is not negligible.
82 if (CanExitEarly)
83 exitLld(errorCount() ? 1 : 0);
84
85 freeArena();
86 return !errorCount();
87}
88
89// Create OptTable
90
91// Create prefix string literals used in Options.td
92#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
93#include "Options.inc"
94#undef PREFIX
95
96// Create table mapping all options defined in Options.td
97static const opt::OptTable::Info OptInfo[] = {
98#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
99 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
100 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
101#include "Options.inc"
102#undef OPTION
103};
104
Sam Cleggc94d3932017-11-17 18:14:09 +0000105// Set color diagnostics according to -color-diagnostics={auto,always,never}
106// or -no-color-diagnostics flags.
107static void handleColorDiagnostics(opt::InputArgList &Args) {
108 auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
109 OPT_no_color_diagnostics);
110 if (!Arg)
111 return;
112
113 if (Arg->getOption().getID() == OPT_color_diagnostics)
114 errorHandler().ColorDiagnostics = true;
115 else if (Arg->getOption().getID() == OPT_no_color_diagnostics)
116 errorHandler().ColorDiagnostics = false;
117 else {
118 StringRef S = Arg->getValue();
119 if (S == "always")
120 errorHandler().ColorDiagnostics = true;
121 if (S == "never")
122 errorHandler().ColorDiagnostics = false;
123 if (S != "auto")
124 error("unknown option: -color-diagnostics=" + S);
125 }
126}
127
128// Find a file by concatenating given paths.
129static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {
130 SmallString<128> S;
131 path::append(S, Path1, Path2);
132 if (fs::exists(S))
133 return S.str().str();
134 return None;
135}
136
Sam Cleggc94d3932017-11-17 18:14:09 +0000137static void printHelp(const char *Argv0) {
Rui Ueyama6074e6b2017-12-11 23:19:11 +0000138 WasmOptTable().PrintHelp(outs(), Argv0, "LLVM Linker", false);
Sam Cleggc94d3932017-11-17 18:14:09 +0000139}
140
141WasmOptTable::WasmOptTable() : OptTable(OptInfo) {}
142
143opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) {
144 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
145
146 unsigned MissingIndex;
147 unsigned MissingCount;
148 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
149
150 handleColorDiagnostics(Args);
151 for (auto *Arg : Args.filtered(OPT_UNKNOWN))
152 error("unknown argument: " + Arg->getSpelling());
153 return Args;
154}
155
Sam Clegg31efdcd2018-01-11 22:31:35 +0000156// Currently we allow a ".imports" to live alongside a library. This can
157// be used to specify a list of symbols which can be undefined at link
158// time (imported from the environment. For example libc.a include an
159// import file that lists the syscall functions it relies on at runtime.
160// In the long run this information would be better stored as a symbol
161// attribute/flag in the object file itself.
162// See: https://github.com/WebAssembly/tool-conventions/issues/35
163static void readImportFile(StringRef Filename) {
164 if (Optional<MemoryBufferRef> Buf = readFile(Filename))
165 for (StringRef Sym : args::getLines(*Buf))
166 Config->AllowUndefinedSymbols.insert(Sym);
167}
168
Sam Cleggc94d3932017-11-17 18:14:09 +0000169void LinkerDriver::addFile(StringRef Path) {
170 Optional<MemoryBufferRef> Buffer = readFile(Path);
171 if (!Buffer.hasValue())
172 return;
173 MemoryBufferRef MBRef = *Buffer;
174
Sam Clegg31efdcd2018-01-11 22:31:35 +0000175 if (identify_magic(MBRef.getBuffer()) == file_magic::archive) {
176 SmallString<128> ImportFile = Path;
177 path::replace_extension(ImportFile, ".imports");
178 if (fs::exists(ImportFile))
179 readImportFile(ImportFile.str());
180
Sam Cleggc94d3932017-11-17 18:14:09 +0000181 Files.push_back(make<ArchiveFile>(MBRef));
Sam Clegg31efdcd2018-01-11 22:31:35 +0000182 return;
183 }
184
185 Files.push_back(make<ObjFile>(MBRef));
Sam Cleggc94d3932017-11-17 18:14:09 +0000186}
187
188// Add a given library by searching it from input search paths.
189void LinkerDriver::addLibrary(StringRef Name) {
190 for (StringRef Dir : Config->SearchPaths) {
191 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) {
192 addFile(*S);
193 return;
194 }
195 }
196
197 error("unable to find library -l" + Name);
198}
199
200void LinkerDriver::createFiles(opt::InputArgList &Args) {
201 for (auto *Arg : Args) {
202 switch (Arg->getOption().getUnaliasedOption().getID()) {
203 case OPT_l:
204 addLibrary(Arg->getValue());
205 break;
206 case OPT_INPUT:
207 addFile(Arg->getValue());
208 break;
209 }
210 }
211
212 if (Files.empty())
213 error("no input files");
214}
215
Rui Ueyama909d1232017-12-11 17:52:28 +0000216static StringRef getEntry(opt::InputArgList &Args, StringRef Default) {
Sam Clegg2c096ba2017-12-08 17:58:25 +0000217 auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry);
218 if (!Arg)
Rui Ueyama909d1232017-12-11 17:52:28 +0000219 return Default;
Sam Clegg2c096ba2017-12-08 17:58:25 +0000220 if (Arg->getOption().getID() == OPT_no_entry)
221 return "";
222 return Arg->getValue();
223}
224
Sam Cleggc94d3932017-11-17 18:14:09 +0000225void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
226 WasmOptTable Parser;
227 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
228
229 // Handle --help
230 if (Args.hasArg(OPT_help)) {
231 printHelp(ArgsArr[0]);
232 return;
233 }
234
235 // Parse and evaluate -mllvm options.
236 std::vector<const char *> V;
Rui Ueyamaceb15e82017-11-28 22:17:39 +0000237 V.push_back("wasm-ld (LLVM option parsing)");
Sam Cleggc94d3932017-11-17 18:14:09 +0000238 for (auto *Arg : Args.filtered(OPT_mllvm))
239 V.push_back(Arg->getValue());
240 cl::ParseCommandLineOptions(V.size(), V.data());
241
Rui Ueyama3e039442017-11-28 19:58:45 +0000242 errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20);
Sam Cleggc94d3932017-11-17 18:14:09 +0000243
244 if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) {
245 outs() << getLLDVersion() << "\n";
246 return;
247 }
248
249 Config->AllowUndefined = Args.hasArg(OPT_allow_undefined);
Sam Cleggb8621592017-11-30 01:40:08 +0000250 Config->CheckSignatures =
251 Args.hasFlag(OPT_check_signatures, OPT_no_check_signatures, false);
Sam Cleggc94d3932017-11-17 18:14:09 +0000252 Config->EmitRelocs = Args.hasArg(OPT_emit_relocs);
Rui Ueyama8cbb3b52017-12-11 17:52:43 +0000253 Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start");
Sam Cleggc94d3932017-11-17 18:14:09 +0000254 Config->ImportMemory = Args.hasArg(OPT_import_memory);
255 Config->OutputFile = Args.getLastArgValue(OPT_o);
Rui Ueyama8cbb3b52017-12-11 17:52:43 +0000256 Config->Relocatable = Args.hasArg(OPT_relocatable);
Rui Ueyama3e039442017-11-28 19:58:45 +0000257 Config->SearchPaths = args::getStrings(Args, OPT_L);
Sam Cleggc94d3932017-11-17 18:14:09 +0000258 Config->StripAll = Args.hasArg(OPT_strip_all);
259 Config->StripDebug = Args.hasArg(OPT_strip_debug);
Sam Cleggc94d3932017-11-17 18:14:09 +0000260 errorHandler().Verbose = Args.hasArg(OPT_verbose);
261 ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);
Sam Clegg22cfe522017-12-05 16:53:25 +0000262 if (Config->Relocatable)
263 Config->EmitRelocs = true;
Sam Cleggc94d3932017-11-17 18:14:09 +0000264
Rui Ueyama3e039442017-11-28 19:58:45 +0000265 Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0);
266 Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024);
267 Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0);
268 Config->ZStackSize =
269 args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize);
Sam Cleggc94d3932017-11-17 18:14:09 +0000270
271 if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file))
Sam Clegg31efdcd2018-01-11 22:31:35 +0000272 readImportFile(Arg->getValue());
Sam Cleggc94d3932017-11-17 18:14:09 +0000273
274 if (Config->OutputFile.empty())
275 error("no output file specified");
276
277 if (!Args.hasArg(OPT_INPUT))
278 error("no input files");
279
280 if (Config->Relocatable && !Config->Entry.empty())
281 error("entry point specified for relocatable output file");
Sam Clegg31de2f02017-12-07 03:19:53 +0000282 if (Config->Relocatable && Args.hasArg(OPT_undefined))
283 error("undefined symbols specified for relocatable output file");
Sam Cleggc94d3932017-11-17 18:14:09 +0000284
Sam Clegg0f0a4282018-01-20 01:44:45 +0000285 Symbol *EntrySym = nullptr;
Sam Cleggc94d3932017-11-17 18:14:09 +0000286 if (!Config->Relocatable) {
Sam Clegg50686852018-01-12 18:35:13 +0000287 static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
288 if (!Config->Entry.empty())
Sam Clegg0f0a4282018-01-20 01:44:45 +0000289 EntrySym = Symtab->addUndefinedFunction(Config->Entry, &Signature);
Sam Cleggc94d3932017-11-17 18:14:09 +0000290
Sam Clegg31de2f02017-12-07 03:19:53 +0000291 // Handle the `--undefined <sym>` options.
Sam Clegg2a06afa2018-01-12 22:10:35 +0000292 for (auto* Arg : Args.filtered(OPT_undefined))
Sam Clegg096aa502018-01-20 01:40:17 +0000293 Symtab->addUndefinedFunction(Arg->getValue(), nullptr);
Sam Clegg31de2f02017-12-07 03:19:53 +0000294
Sam Clegg5a11dd92018-01-17 01:10:28 +0000295 // Create linker-synthetic symbols
296 // __wasm_call_ctors:
297 // Function that directly calls all ctors in priority order.
298 // __stack_pointer:
299 // Wasm global that holds the address of the top of the explict
300 // value stack in linear memory.
301 // __dso_handle;
302 // Global in calls to __cxa_atexit to determine current DLL
Sam Clegg50686852018-01-12 18:35:13 +0000303 Config->CtorSymbol = Symtab->addDefinedFunction(
304 "__wasm_call_ctors", &Signature, WASM_SYMBOL_VISIBILITY_HIDDEN);
Sam Cleggc5872e82017-12-08 00:13:14 +0000305 Config->StackPointerSymbol = Symtab->addDefinedGlobal("__stack_pointer");
Sam Clegg51bcdc22018-01-17 01:34:31 +0000306 Config->HeapBaseSymbol = Symtab->addDefinedGlobal("__heap_base");
Sam Clegg5a11dd92018-01-17 01:10:28 +0000307 Symtab->addDefinedGlobal("__dso_handle")->setVirtualAddress(0);
Sam Cleggc94d3932017-11-17 18:14:09 +0000308 }
309
310 createFiles(Args);
311 if (errorCount())
312 return;
313
314 // Add all files to the symbol table. This will add almost all
315 // symbols that we need to the symbol table.
316 for (InputFile *F : Files)
317 Symtab->addFile(F);
318
319 // Make sure we have resolved all symbols.
320 if (!Config->Relocatable && !Config->AllowUndefined) {
321 Symtab->reportRemainingUndefines();
Sam Clegg31de2f02017-12-07 03:19:53 +0000322 } else {
323 // When we allow undefined symbols we cannot include those defined in
324 // -u/--undefined since these undefined symbols have only names and no
325 // function signature, which means they cannot be written to the final
326 // output.
Sam Clegg2a06afa2018-01-12 22:10:35 +0000327 for (auto* Arg : Args.filtered(OPT_undefined)) {
328 Symbol *Sym = Symtab->find(Arg->getValue());
Sam Clegg31de2f02017-12-07 03:19:53 +0000329 if (!Sym->isDefined())
330 error("function forced with --undefined not found: " + Sym->getName());
331 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000332 }
Rui Ueyama9d8ce232017-12-11 23:09:03 +0000333 if (errorCount())
334 return;
Sam Cleggc94d3932017-11-17 18:14:09 +0000335
Sam Clegg2a06afa2018-01-12 22:10:35 +0000336 for (auto *Arg : Args.filtered(OPT_export)) {
337 Symbol *Sym = Symtab->find(Arg->getValue());
338 if (!Sym || !Sym->isDefined())
339 error("symbol exported via --export not found: " +
340 Twine(Arg->getValue()));
341 else
342 Sym->setHidden(false);
343 }
344
Sam Clegg0f0a4282018-01-20 01:44:45 +0000345 if (EntrySym)
346 EntrySym->setHidden(false);
347
Sam Clegg2c096ba2017-12-08 17:58:25 +0000348 if (errorCount())
349 return;
Sam Cleggc94d3932017-11-17 18:14:09 +0000350
351 // Write the result to the file.
352 writeResult();
353}