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 // Inject a new undefined symbol into the link. This will cause the link to 138 // fail unless this symbol can be found. 139 static void addSyntheticUndefinedFunction(StringRef Name, 140 const WasmSignature *Type) { 141 log("injecting undefined func: " + Name); 142 Symtab->addUndefinedFunction(Name, Type); 143 } 144 145 static void printHelp(const char *Argv0) { 146 WasmOptTable().PrintHelp(outs(), Argv0, "LLVM Linker", false); 147 } 148 149 WasmOptTable::WasmOptTable() : OptTable(OptInfo) {} 150 151 opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) { 152 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); 153 154 unsigned MissingIndex; 155 unsigned MissingCount; 156 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); 157 158 handleColorDiagnostics(Args); 159 for (auto *Arg : Args.filtered(OPT_UNKNOWN)) 160 error("unknown argument: " + Arg->getSpelling()); 161 return Args; 162 } 163 164 // Currently we allow a ".imports" to live alongside a library. This can 165 // be used to specify a list of symbols which can be undefined at link 166 // time (imported from the environment. For example libc.a include an 167 // import file that lists the syscall functions it relies on at runtime. 168 // In the long run this information would be better stored as a symbol 169 // attribute/flag in the object file itself. 170 // See: https://github.com/WebAssembly/tool-conventions/issues/35 171 static void readImportFile(StringRef Filename) { 172 if (Optional<MemoryBufferRef> Buf = readFile(Filename)) 173 for (StringRef Sym : args::getLines(*Buf)) 174 Config->AllowUndefinedSymbols.insert(Sym); 175 } 176 177 void LinkerDriver::addFile(StringRef Path) { 178 Optional<MemoryBufferRef> Buffer = readFile(Path); 179 if (!Buffer.hasValue()) 180 return; 181 MemoryBufferRef MBRef = *Buffer; 182 183 if (identify_magic(MBRef.getBuffer()) == file_magic::archive) { 184 SmallString<128> ImportFile = Path; 185 path::replace_extension(ImportFile, ".imports"); 186 if (fs::exists(ImportFile)) 187 readImportFile(ImportFile.str()); 188 189 Files.push_back(make<ArchiveFile>(MBRef)); 190 return; 191 } 192 193 Files.push_back(make<ObjFile>(MBRef)); 194 } 195 196 // Add a given library by searching it from input search paths. 197 void LinkerDriver::addLibrary(StringRef Name) { 198 for (StringRef Dir : Config->SearchPaths) { 199 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) { 200 addFile(*S); 201 return; 202 } 203 } 204 205 error("unable to find library -l" + Name); 206 } 207 208 void LinkerDriver::createFiles(opt::InputArgList &Args) { 209 for (auto *Arg : Args) { 210 switch (Arg->getOption().getUnaliasedOption().getID()) { 211 case OPT_l: 212 addLibrary(Arg->getValue()); 213 break; 214 case OPT_INPUT: 215 addFile(Arg->getValue()); 216 break; 217 } 218 } 219 220 if (Files.empty()) 221 error("no input files"); 222 } 223 224 static StringRef getEntry(opt::InputArgList &Args, StringRef Default) { 225 auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry); 226 if (!Arg) 227 return Default; 228 if (Arg->getOption().getID() == OPT_no_entry) 229 return ""; 230 return Arg->getValue(); 231 } 232 233 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { 234 WasmOptTable Parser; 235 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); 236 237 // Handle --help 238 if (Args.hasArg(OPT_help)) { 239 printHelp(ArgsArr[0]); 240 return; 241 } 242 243 // Parse and evaluate -mllvm options. 244 std::vector<const char *> V; 245 V.push_back("wasm-ld (LLVM option parsing)"); 246 for (auto *Arg : Args.filtered(OPT_mllvm)) 247 V.push_back(Arg->getValue()); 248 cl::ParseCommandLineOptions(V.size(), V.data()); 249 250 errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); 251 252 if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { 253 outs() << getLLDVersion() << "\n"; 254 return; 255 } 256 257 Config->AllowUndefined = Args.hasArg(OPT_allow_undefined); 258 Config->CheckSignatures = 259 Args.hasFlag(OPT_check_signatures, OPT_no_check_signatures, false); 260 Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); 261 Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start"); 262 Config->ImportMemory = Args.hasArg(OPT_import_memory); 263 Config->OutputFile = Args.getLastArgValue(OPT_o); 264 Config->Relocatable = Args.hasArg(OPT_relocatable); 265 Config->SearchPaths = args::getStrings(Args, OPT_L); 266 Config->StripAll = Args.hasArg(OPT_strip_all); 267 Config->StripDebug = Args.hasArg(OPT_strip_debug); 268 errorHandler().Verbose = Args.hasArg(OPT_verbose); 269 ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); 270 if (Config->Relocatable) 271 Config->EmitRelocs = true; 272 273 Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0); 274 Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024); 275 Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0); 276 Config->ZStackSize = 277 args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize); 278 279 if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) 280 readImportFile(Arg->getValue()); 281 282 if (Config->OutputFile.empty()) 283 error("no output file specified"); 284 285 if (!Args.hasArg(OPT_INPUT)) 286 error("no input files"); 287 288 if (Config->Relocatable && !Config->Entry.empty()) 289 error("entry point specified for relocatable output file"); 290 if (Config->Relocatable && Args.hasArg(OPT_undefined)) 291 error("undefined symbols specified for relocatable output file"); 292 293 if (!Config->Relocatable) { 294 static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; 295 if (!Config->Entry.empty()) 296 addSyntheticUndefinedFunction(Config->Entry, &Signature); 297 298 // Handle the `--undefined <sym>` options. 299 for (auto* Arg : Args.filtered(OPT_undefined)) 300 addSyntheticUndefinedFunction(Arg->getValue(), nullptr); 301 302 // Create linker-synthetic symbols 303 // __wasm_call_ctors: 304 // Function that directly calls all ctors in priority order. 305 // __stack_pointer: 306 // Wasm global that holds the address of the top of the explict 307 // value stack in linear memory. 308 // __dso_handle; 309 // Global in calls to __cxa_atexit to determine current DLL 310 Config->CtorSymbol = Symtab->addDefinedFunction( 311 "__wasm_call_ctors", &Signature, WASM_SYMBOL_VISIBILITY_HIDDEN); 312 Config->StackPointerSymbol = Symtab->addDefinedGlobal("__stack_pointer"); 313 Config->HeapBaseSymbol = Symtab->addDefinedGlobal("__heap_base"); 314 Symtab->addDefinedGlobal("__dso_handle")->setVirtualAddress(0); 315 } 316 317 createFiles(Args); 318 if (errorCount()) 319 return; 320 321 // Add all files to the symbol table. This will add almost all 322 // symbols that we need to the symbol table. 323 for (InputFile *F : Files) 324 Symtab->addFile(F); 325 326 // Make sure we have resolved all symbols. 327 if (!Config->Relocatable && !Config->AllowUndefined) { 328 Symtab->reportRemainingUndefines(); 329 } else { 330 // When we allow undefined symbols we cannot include those defined in 331 // -u/--undefined since these undefined symbols have only names and no 332 // function signature, which means they cannot be written to the final 333 // output. 334 for (auto* Arg : Args.filtered(OPT_undefined)) { 335 Symbol *Sym = Symtab->find(Arg->getValue()); 336 if (!Sym->isDefined()) 337 error("function forced with --undefined not found: " + Sym->getName()); 338 } 339 } 340 if (errorCount()) 341 return; 342 343 for (auto *Arg : Args.filtered(OPT_export)) { 344 Symbol *Sym = Symtab->find(Arg->getValue()); 345 if (!Sym || !Sym->isDefined()) 346 error("symbol exported via --export not found: " + 347 Twine(Arg->getValue())); 348 else 349 Sym->setHidden(false); 350 } 351 352 if (!Config->Entry.empty() && !Symtab->find(Config->Entry)->isDefined()) 353 error("entry point not found: " + Config->Entry); 354 if (errorCount()) 355 return; 356 357 // Write the result to the file. 358 writeResult(); 359 } 360