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 wasm global into the output binary with the given value. 138 // Wasm global are used in relocatable object files to model symbol imports 139 // and exports. In the final exectuable the only use of wasm globals is the 140 // for the exlicit stack pointer (__stack_pointer). 141 static void addSyntheticGlobal(StringRef Name, int32_t Value) { 142 log("injecting global: " + Name); 143 Symbol *S = Symtab->addDefinedGlobal(Name); 144 S->setOutputIndex(Config->SyntheticGlobals.size()); 145 146 WasmGlobal Global; 147 Global.Mutable = true; 148 Global.Type = WASM_TYPE_I32; 149 Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; 150 Global.InitExpr.Value.Int32 = Value; 151 Config->SyntheticGlobals.emplace_back(S, Global); 152 } 153 154 // Inject a new undefined symbol into the link. This will cause the link to 155 // fail unless this symbol can be found. 156 static void addSyntheticUndefinedFunction(StringRef Name, 157 const WasmSignature *Type) { 158 log("injecting undefined func: " + Name); 159 Symtab->addUndefinedFunction(Name, Type); 160 } 161 162 static void printHelp(const char *Argv0) { 163 WasmOptTable Table; 164 Table.PrintHelp(outs(), Argv0, "LLVM Linker", false); 165 } 166 167 WasmOptTable::WasmOptTable() : OptTable(OptInfo) {} 168 169 opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) { 170 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); 171 172 unsigned MissingIndex; 173 unsigned MissingCount; 174 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); 175 176 handleColorDiagnostics(Args); 177 for (auto *Arg : Args.filtered(OPT_UNKNOWN)) 178 error("unknown argument: " + Arg->getSpelling()); 179 return Args; 180 } 181 182 void LinkerDriver::addFile(StringRef Path) { 183 Optional<MemoryBufferRef> Buffer = readFile(Path); 184 if (!Buffer.hasValue()) 185 return; 186 MemoryBufferRef MBRef = *Buffer; 187 188 if (identify_magic(MBRef.getBuffer()) == file_magic::archive) 189 Files.push_back(make<ArchiveFile>(MBRef)); 190 else 191 Files.push_back(make<ObjFile>(MBRef)); 192 } 193 194 // Add a given library by searching it from input search paths. 195 void LinkerDriver::addLibrary(StringRef Name) { 196 for (StringRef Dir : Config->SearchPaths) { 197 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) { 198 addFile(*S); 199 return; 200 } 201 } 202 203 error("unable to find library -l" + Name); 204 } 205 206 void LinkerDriver::createFiles(opt::InputArgList &Args) { 207 for (auto *Arg : Args) { 208 switch (Arg->getOption().getUnaliasedOption().getID()) { 209 case OPT_l: 210 addLibrary(Arg->getValue()); 211 break; 212 case OPT_INPUT: 213 addFile(Arg->getValue()); 214 break; 215 } 216 } 217 218 if (Files.empty()) 219 error("no input files"); 220 } 221 222 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { 223 WasmOptTable Parser; 224 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); 225 226 // Handle --help 227 if (Args.hasArg(OPT_help)) { 228 printHelp(ArgsArr[0]); 229 return; 230 } 231 232 // Parse and evaluate -mllvm options. 233 std::vector<const char *> V; 234 V.push_back("wasm-ld (LLVM option parsing)"); 235 for (auto *Arg : Args.filtered(OPT_mllvm)) 236 V.push_back(Arg->getValue()); 237 cl::ParseCommandLineOptions(V.size(), V.data()); 238 239 errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); 240 241 if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { 242 outs() << getLLDVersion() << "\n"; 243 return; 244 } 245 246 Config->AllowUndefined = Args.hasArg(OPT_allow_undefined); 247 Config->CheckSignatures = 248 Args.hasFlag(OPT_check_signatures, OPT_no_check_signatures, false); 249 Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); 250 Config->Entry = Args.getLastArgValue(OPT_entry); 251 Config->ImportMemory = Args.hasArg(OPT_import_memory); 252 Config->OutputFile = Args.getLastArgValue(OPT_o); 253 Config->Relocatable = Args.hasArg(OPT_relocatable); 254 Config->SearchPaths = args::getStrings(Args, OPT_L); 255 Config->StripAll = Args.hasArg(OPT_strip_all); 256 Config->StripDebug = Args.hasArg(OPT_strip_debug); 257 Config->Sysroot = Args.getLastArgValue(OPT_sysroot); 258 errorHandler().Verbose = Args.hasArg(OPT_verbose); 259 ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); 260 261 Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0); 262 Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024); 263 Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0); 264 Config->ZStackSize = 265 args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize); 266 267 if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) 268 if (Optional<MemoryBufferRef> Buf = readFile(Arg->getValue())) 269 for (StringRef Sym : args::getLines(*Buf)) 270 Config->AllowUndefinedSymbols.insert(Sym); 271 272 if (Config->OutputFile.empty()) 273 error("no output file specified"); 274 275 if (!Args.hasArg(OPT_INPUT)) 276 error("no input files"); 277 278 if (Config->Relocatable && !Config->Entry.empty()) 279 error("entry point specified for relocatable output file"); 280 281 if (!Config->Relocatable) { 282 if (Config->Entry.empty()) 283 Config->Entry = "_start"; 284 static WasmSignature Signature = { {}, WASM_TYPE_NORESULT }; 285 addSyntheticUndefinedFunction(Config->Entry, &Signature); 286 287 addSyntheticGlobal("__stack_pointer", 0); 288 } 289 290 createFiles(Args); 291 if (errorCount()) 292 return; 293 294 // Add all files to the symbol table. This will add almost all 295 // symbols that we need to the symbol table. 296 for (InputFile *F : Files) 297 Symtab->addFile(F); 298 299 // Make sure we have resolved all symbols. 300 if (!Config->Relocatable && !Config->AllowUndefined) { 301 Symtab->reportRemainingUndefines(); 302 if (errorCount()) 303 return; 304 } 305 306 if (!Config->Entry.empty()) { 307 Symbol *Sym = Symtab->find(Config->Entry); 308 if (!Sym->isFunction()) 309 fatal("entry point is not a function: " + Sym->getName()); 310 } 311 312 // Write the result to the file. 313 writeResult(); 314 } 315