| //===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains the main function of the lld executable. The main |
| // function is a thin wrapper which dispatches to the platform specific |
| // driver. |
| // |
| // lld is a single executable that contains four different linkers for ELF, |
| // COFF, WebAssembly and Mach-O. The main function dispatches according to |
| // argv[0] (i.e. command name). The most common name for each target is shown |
| // below: |
| // |
| // - ld.lld: ELF (Unix) |
| // - ld64: Mach-O (macOS) |
| // - lld-link: COFF (Windows) |
| // - ld-wasm: WebAssembly |
| // |
| // lld can be invoked as "lld" along with "-flavor" option. This is for |
| // backward compatibility and not recommended. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "lld/Common/Driver.h" |
| #include "lld/Common/ErrorHandler.h" |
| #include "lld/Common/Memory.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/Twine.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/CrashRecoveryContext.h" |
| #include "llvm/Support/LLVMDriver.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/PluginLoader.h" |
| #include "llvm/Support/Process.h" |
| #include "llvm/TargetParser/Host.h" |
| #include "llvm/TargetParser/Triple.h" |
| #include <cstdlib> |
| #include <optional> |
| |
| using namespace lld; |
| using namespace llvm; |
| using namespace llvm::sys; |
| |
| namespace lld { |
| extern bool inTestOutputDisabled; |
| |
| // Bypass the crash recovery handler, which is only meant to be used in |
| // LLD-as-lib scenarios. |
| int unsafeLldMain(llvm::ArrayRef<const char *> args, |
| llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS, |
| llvm::ArrayRef<DriverDef> drivers, bool exitEarly); |
| } // namespace lld |
| |
| // When in lit tests, tells how many times the LLD tool should re-execute the |
| // main loop with the same inputs. When not in test, returns a value of 0 which |
| // signifies that LLD shall not release any memory after execution, to speed up |
| // process destruction. |
| static unsigned inTestVerbosity() { |
| unsigned v = 0; |
| StringRef(getenv("LLD_IN_TEST")).getAsInteger(10, v); |
| return v; |
| } |
| |
| LLD_HAS_DRIVER(coff) |
| LLD_HAS_DRIVER(elf) |
| LLD_HAS_DRIVER(mingw) |
| LLD_HAS_DRIVER(macho) |
| LLD_HAS_DRIVER(wasm) |
| |
| int lld_main(int argc, char **argv, const llvm::ToolContext &) { |
| sys::Process::UseANSIEscapeCodes(true); |
| |
| if (::getenv("FORCE_LLD_DIAGNOSTICS_CRASH")) { |
| llvm::errs() |
| << "crashing due to environment variable FORCE_LLD_DIAGNOSTICS_CRASH\n"; |
| LLVM_BUILTIN_TRAP; |
| } |
| |
| ArrayRef<const char *> args(argv, argv + argc); |
| |
| // Not running in lit tests, just take the shortest codepath with global |
| // exception handling and no memory cleanup on exit. |
| if (!inTestVerbosity()) { |
| int r = |
| lld::unsafeLldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS, |
| /*exitEarly=*/true); |
| return r; |
| } |
| |
| std::optional<int> mainRet; |
| CrashRecoveryContext::Enable(); |
| |
| for (unsigned i = inTestVerbosity(); i > 0; --i) { |
| // Disable stdout/stderr for all iterations but the last one. |
| inTestOutputDisabled = (i != 1); |
| |
| // Execute one iteration. |
| auto r = lldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS); |
| if (!r.canRunAgain) |
| exitLld(r.retCode); // Exit now, can't re-execute again. |
| |
| if (!mainRet) { |
| mainRet = r.retCode; |
| } else if (r.retCode != *mainRet) { |
| // Exit now, to fail the tests if the result is different between runs. |
| return r.retCode; |
| } |
| } |
| return *mainRet; |
| } |