1 //===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===// 2 // 3 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the main function of the lld executable. The main 10 // function is a thin wrapper which dispatches to the platform specific 11 // driver. 12 // 13 // lld is a single executable that contains four different linkers for ELF, 14 // COFF, WebAssembly and Mach-O. The main function dispatches according to 15 // argv[0] (i.e. command name). The most common name for each target is shown 16 // below: 17 // 18 // - ld.lld: ELF (Unix) 19 // - ld64: Mach-O (macOS) 20 // - lld-link: COFF (Windows) 21 // - ld-wasm: WebAssembly 22 // 23 // lld can be invoked as "lld" along with "-flavor" option. This is for 24 // backward compatibility and not recommended. 25 // 26 //===----------------------------------------------------------------------===// 27 28 #include "lld/Common/Driver.h" 29 #include "lld/Common/ErrorHandler.h" 30 #include "lld/Common/Memory.h" 31 #include "llvm/ADT/STLExtras.h" 32 #include "llvm/ADT/SmallVector.h" 33 #include "llvm/ADT/StringSwitch.h" 34 #include "llvm/ADT/Twine.h" 35 #include "llvm/Support/CommandLine.h" 36 #include "llvm/Support/CrashRecoveryContext.h" 37 #include "llvm/Support/InitLLVM.h" 38 #include "llvm/Support/LLVMDriver.h" 39 #include "llvm/Support/Path.h" 40 #include "llvm/Support/PluginLoader.h" 41 #include "llvm/Support/Process.h" 42 #include "llvm/TargetParser/Host.h" 43 #include "llvm/TargetParser/Triple.h" 44 #include <cstdlib> 45 #include <optional> 46 47 using namespace lld; 48 using namespace llvm; 49 using namespace llvm::sys; 50 51 namespace lld { 52 extern bool inTestOutputDisabled; 53 54 // Bypass the crash recovery handler, which is only meant to be used in 55 // LLD-as-lib scenarios. 56 int unsafeLldMain(llvm::ArrayRef<const char *> args, 57 llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS, 58 llvm::ArrayRef<DriverDef> drivers, bool exitEarly); 59 } // namespace lld 60 61 // When in lit tests, tells how many times the LLD tool should re-execute the 62 // main loop with the same inputs. When not in test, returns a value of 0 which 63 // signifies that LLD shall not release any memory after execution, to speed up 64 // process destruction. 65 static unsigned inTestVerbosity() { 66 unsigned v = 0; 67 StringRef(getenv("LLD_IN_TEST")).getAsInteger(10, v); 68 return v; 69 } 70 71 #if 1 72 // On FreeBSD we only build the ELF linker. 73 LLD_HAS_DRIVER(elf) 74 #undef LLD_ALL_DRIVERS 75 #define LLD_ALL_DRIVERS { {lld::Gnu, &lld::elf::link} } 76 #else 77 LLD_HAS_DRIVER(coff) 78 LLD_HAS_DRIVER(elf) 79 LLD_HAS_DRIVER(mingw) 80 LLD_HAS_DRIVER(macho) 81 LLD_HAS_DRIVER(wasm) 82 #endif 83 84 int lld_main(int argc, char **argv, const llvm::ToolContext &) { 85 InitLLVM x(argc, argv); 86 sys::Process::UseANSIEscapeCodes(true); 87 88 if (::getenv("FORCE_LLD_DIAGNOSTICS_CRASH")) { 89 llvm::errs() 90 << "crashing due to environment variable FORCE_LLD_DIAGNOSTICS_CRASH\n"; 91 LLVM_BUILTIN_TRAP; 92 } 93 94 ArrayRef<const char *> args(argv, argv + argc); 95 96 // Not running in lit tests, just take the shortest codepath with global 97 // exception handling and no memory cleanup on exit. 98 if (!inTestVerbosity()) { 99 int r = 100 lld::unsafeLldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS, 101 /*exitEarly=*/true); 102 return r; 103 } 104 105 std::optional<int> mainRet; 106 CrashRecoveryContext::Enable(); 107 108 for (unsigned i = inTestVerbosity(); i > 0; --i) { 109 // Disable stdout/stderr for all iterations but the last one. 110 inTestOutputDisabled = (i != 1); 111 112 // Execute one iteration. 113 auto r = lldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS); 114 if (!r.canRunAgain) 115 exitLld(r.retCode); // Exit now, can't re-execute again. 116 117 if (!mainRet) { 118 mainRet = r.retCode; 119 } else if (r.retCode != *mainRet) { 120 // Exit now, to fail the tests if the result is different between runs. 121 return r.retCode; 122 } 123 } 124 return *mainRet; 125 } 126