1 //===- 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" 12 #include "SymbolTable.h" 13 #include "Writer.h" 14 #include "lld/Common/Args.h" 15 #include "lld/Common/ErrorHandler.h" 16 #include "lld/Common/Memory.h" 17 #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 26 using namespace llvm; 27 using namespace llvm::sys; 28 using namespace llvm::wasm; 29 30 using namespace lld; 31 using namespace lld::wasm; 32 33 namespace { 34 35 // Parses command line options. 36 class WasmOptTable : public llvm::opt::OptTable { 37 public: 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 43 enum { 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 50 class LinkerDriver { 51 public: 52 void link(ArrayRef<const char *> ArgsArr); 53 54 private: 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 63 Configuration *lld::wasm::Config; 64 65 bool 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 97 static 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 105 // Set color diagnostics according to -color-diagnostics={auto,always,never} 106 // or -no-color-diagnostics flags. 107 static 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. 129 static 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 137 static void printHelp(const char *Argv0) { 138 WasmOptTable().PrintHelp(outs(), Argv0, "LLVM Linker", false); 139 } 140 141 WasmOptTable::WasmOptTable() : OptTable(OptInfo) {} 142 143 opt::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 156 // 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 163 static 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 169 void LinkerDriver::addFile(StringRef Path) { 170 Optional<MemoryBufferRef> Buffer = readFile(Path); 171 if (!Buffer.hasValue()) 172 return; 173 MemoryBufferRef MBRef = *Buffer; 174 175 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 181 Files.push_back(make<ArchiveFile>(MBRef)); 182 return; 183 } 184 185 Files.push_back(make<ObjFile>(MBRef)); 186 } 187 188 // Add a given library by searching it from input search paths. 189 void 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 200 void 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 216 static StringRef getEntry(opt::InputArgList &Args, StringRef Default) { 217 auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry); 218 if (!Arg) 219 return Default; 220 if (Arg->getOption().getID() == OPT_no_entry) 221 return ""; 222 return Arg->getValue(); 223 } 224 225 void 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; 237 V.push_back("wasm-ld (LLVM option parsing)"); 238 for (auto *Arg : Args.filtered(OPT_mllvm)) 239 V.push_back(Arg->getValue()); 240 cl::ParseCommandLineOptions(V.size(), V.data()); 241 242 errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); 243 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); 250 Config->CheckSignatures = 251 Args.hasFlag(OPT_check_signatures, OPT_no_check_signatures, false); 252 Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start"); 253 Config->ImportMemory = Args.hasArg(OPT_import_memory); 254 Config->OutputFile = Args.getLastArgValue(OPT_o); 255 Config->Relocatable = Args.hasArg(OPT_relocatable); 256 Config->SearchPaths = args::getStrings(Args, OPT_L); 257 Config->StripAll = Args.hasArg(OPT_strip_all); 258 Config->StripDebug = Args.hasArg(OPT_strip_debug); 259 errorHandler().Verbose = Args.hasArg(OPT_verbose); 260 ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); 261 262 Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0); 263 Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024); 264 Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0); 265 Config->ZStackSize = 266 args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize); 267 268 if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) 269 readImportFile(Arg->getValue()); 270 271 if (Config->OutputFile.empty()) 272 error("no output file specified"); 273 274 if (!Args.hasArg(OPT_INPUT)) 275 error("no input files"); 276 277 if (Config->Relocatable && !Config->Entry.empty()) 278 error("entry point specified for relocatable output file"); 279 if (Config->Relocatable && Args.hasArg(OPT_undefined)) 280 error("undefined symbols specified for relocatable output file"); 281 282 Symbol *EntrySym = nullptr; 283 if (!Config->Relocatable) { 284 static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; 285 if (!Config->Entry.empty()) 286 EntrySym = Symtab->addUndefinedFunction(Config->Entry, &Signature); 287 288 // Handle the `--undefined <sym>` options. 289 for (auto* Arg : Args.filtered(OPT_undefined)) 290 Symtab->addUndefinedFunction(Arg->getValue(), nullptr); 291 292 // Create linker-synthetic symbols 293 // __wasm_call_ctors: 294 // Function that directly calls all ctors in priority order. 295 // __stack_pointer: 296 // Wasm global that holds the address of the top of the explict 297 // value stack in linear memory. 298 // __dso_handle; 299 // Global in calls to __cxa_atexit to determine current DLL 300 Config->CtorSymbol = Symtab->addDefinedFunction( 301 "__wasm_call_ctors", &Signature, WASM_SYMBOL_VISIBILITY_HIDDEN); 302 Config->StackPointerSymbol = Symtab->addDefinedGlobal("__stack_pointer"); 303 Config->HeapBaseSymbol = Symtab->addDefinedGlobal("__heap_base"); 304 Symtab->addDefinedGlobal("__dso_handle")->setVirtualAddress(0); 305 } 306 307 createFiles(Args); 308 if (errorCount()) 309 return; 310 311 // Add all files to the symbol table. This will add almost all 312 // symbols that we need to the symbol table. 313 for (InputFile *F : Files) 314 Symtab->addFile(F); 315 316 // Make sure we have resolved all symbols. 317 if (!Config->Relocatable && !Config->AllowUndefined) { 318 Symtab->reportRemainingUndefines(); 319 } else { 320 // When we allow undefined symbols we cannot include those defined in 321 // -u/--undefined since these undefined symbols have only names and no 322 // function signature, which means they cannot be written to the final 323 // output. 324 for (auto* Arg : Args.filtered(OPT_undefined)) { 325 Symbol *Sym = Symtab->find(Arg->getValue()); 326 if (!Sym->isDefined()) 327 error("function forced with --undefined not found: " + Sym->getName()); 328 } 329 } 330 if (errorCount()) 331 return; 332 333 for (auto *Arg : Args.filtered(OPT_export)) { 334 Symbol *Sym = Symtab->find(Arg->getValue()); 335 if (!Sym || !Sym->isDefined()) 336 error("symbol exported via --export not found: " + 337 Twine(Arg->getValue())); 338 else 339 Sym->setHidden(false); 340 } 341 342 if (EntrySym) 343 EntrySym->setHidden(false); 344 345 if (errorCount()) 346 return; 347 348 // Write the result to the file. 349 writeResult(); 350 } 351