diff options
Diffstat (limited to 'lib/Driver/ToolChains/Gnu.cpp')
| -rw-r--r-- | lib/Driver/ToolChains/Gnu.cpp | 206 |
1 files changed, 141 insertions, 65 deletions
diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 2ad45097dce8c..33cdd3585c297 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -1,9 +1,8 @@ //===--- Gnu.cpp - Gnu Tool and ToolChain Implementations -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -22,6 +21,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Path.h" @@ -34,6 +34,8 @@ using namespace clang::driver::toolchains; using namespace clang; using namespace llvm::opt; +using tools::addMultilibFlag; + void tools::GnuTool::anchor() {} static bool forwardToGCC(const Option &O) { @@ -309,7 +311,7 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) { static bool getPIE(const ArgList &Args, const toolchains::Linux &ToolChain) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_r)) + Args.hasArg(options::OPT_r) || Args.hasArg(options::OPT_static_pie)) return false; Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie, @@ -319,6 +321,26 @@ static bool getPIE(const ArgList &Args, const toolchains::Linux &ToolChain) { return A->getOption().matches(options::OPT_pie); } +static bool getStaticPIE(const ArgList &Args, + const toolchains::Linux &ToolChain) { + bool HasStaticPIE = Args.hasArg(options::OPT_static_pie); + // -no-pie is an alias for -nopie. So, handling -nopie takes care of + // -no-pie as well. + if (HasStaticPIE && Args.hasArg(options::OPT_nopie)) { + const Driver &D = ToolChain.getDriver(); + const llvm::opt::OptTable &Opts = D.getOpts(); + const char *StaticPIEName = Opts.getOptionName(options::OPT_static_pie); + const char *NoPIEName = Opts.getOptionName(options::OPT_nopie); + D.Diag(diag::err_drv_cannot_mix_options) << StaticPIEName << NoPIEName; + } + return HasStaticPIE; +} + +static bool getStatic(const ArgList &Args) { + return Args.hasArg(options::OPT_static) && + !Args.hasArg(options::OPT_static_pie); +} + void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -334,6 +356,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, const bool isAndroid = ToolChain.getTriple().isAndroid(); const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU(); const bool IsPIE = getPIE(Args, ToolChain); + const bool IsStaticPIE = getStaticPIE(Args, ToolChain); + const bool IsStatic = getStatic(Args); const bool HasCRTBeginEndFiles = ToolChain.getTriple().hasEnvironment() || (ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies); @@ -354,6 +378,19 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (IsPIE) CmdArgs.push_back("-pie"); + if (IsStaticPIE) { + CmdArgs.push_back("-static"); + CmdArgs.push_back("-pie"); + CmdArgs.push_back("--no-dynamic-linker"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("text"); + } + + if (ToolChain.isNoExecStackDefault()) { + CmdArgs.push_back("-z"); + CmdArgs.push_back("noexecstack"); + } + if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); @@ -376,6 +413,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--fix-cortex-a53-843419"); } + // Android does not allow shared text relocations. Emit a warning if the + // user's code contains any. + if (isAndroid) + CmdArgs.push_back("--warn-shared-textrel"); + for (const auto &Opt : ToolChain.ExtraOpts) CmdArgs.push_back(Opt.c_str()); @@ -389,7 +431,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, return; } - if (Args.hasArg(options::OPT_static)) { + if (IsStatic) { if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb) CmdArgs.push_back("-Bstatic"); @@ -399,11 +441,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-shared"); } - if (!Args.hasArg(options::OPT_static)) { + if (!IsStatic) { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); - if (!Args.hasArg(options::OPT_shared)) { + if (!Args.hasArg(options::OPT_shared) && !IsStaticPIE) { const std::string Loader = D.DyldPrefix + ToolChain.getDynamicLinker(Args); CmdArgs.push_back("-dynamic-linker"); @@ -422,6 +464,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, crt1 = "gcrt1.o"; else if (IsPIE) crt1 = "Scrt1.o"; + else if (IsStaticPIE) + crt1 = "rcrt1.o"; else crt1 = "crt1.o"; } @@ -433,20 +477,29 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (IsIAMCU) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); - else { - const char *crtbegin; - if (Args.hasArg(options::OPT_static)) - crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; - else if (Args.hasArg(options::OPT_shared)) - crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; - else if (IsPIE) - crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; - else - crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; - - if (HasCRTBeginEndFiles) - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); - } + else if (HasCRTBeginEndFiles) { + std::string P; + if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT && + !isAndroid) { + std::string crtbegin = ToolChain.getCompilerRT(Args, "crtbegin", + ToolChain::FT_Object); + if (ToolChain.getVFS().exists(crtbegin)) + P = crtbegin; + } + if (P.empty()) { + const char *crtbegin; + if (IsStatic) + crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; + else if (Args.hasArg(options::OPT_shared)) + crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; + else if (IsPIE || IsStaticPIE) + crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; + else + crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; + P = ToolChain.GetFilePath(crtbegin); + } + CmdArgs.push_back(Args.MakeArgString(P)); + } // Add crtfastmath.o if available and fast math is enabled. ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); @@ -490,7 +543,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { - if (Args.hasArg(options::OPT_static)) + if (IsStatic || IsStaticPIE) CmdArgs.push_back("--start-group"); if (NeedsSanitizerDeps) @@ -519,13 +572,14 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("--wrap=pthread_create"); - CmdArgs.push_back("-lc"); + if (!Args.hasArg(options::OPT_nolibc)) + CmdArgs.push_back("-lc"); // Add IAMCU specific libs, if needed. if (IsIAMCU) CmdArgs.push_back("-lgloss"); - if (Args.hasArg(options::OPT_static)) + if (IsStatic || IsStaticPIE) CmdArgs.push_back("--end-group"); else AddRunTimeLibs(ToolChain, D, CmdArgs, Args); @@ -539,16 +593,27 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostartfiles) && !IsIAMCU) { - const char *crtend; - if (Args.hasArg(options::OPT_shared)) - crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; - else if (IsPIE) - crtend = isAndroid ? "crtend_android.o" : "crtendS.o"; - else - crtend = isAndroid ? "crtend_android.o" : "crtend.o"; - - if (HasCRTBeginEndFiles) - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); + if (HasCRTBeginEndFiles) { + std::string P; + if (ToolChain.GetRuntimeLibType(Args) == ToolChain::RLT_CompilerRT && + !isAndroid) { + std::string crtend = ToolChain.getCompilerRT(Args, "crtend", + ToolChain::FT_Object); + if (ToolChain.getVFS().exists(crtend)) + P = crtend; + } + if (P.empty()) { + const char *crtend; + if (Args.hasArg(options::OPT_shared)) + crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; + else if (IsPIE || IsStaticPIE) + crtend = isAndroid ? "crtend_android.o" : "crtendS.o"; + else + crtend = isAndroid ? "crtend_android.o" : "crtend.o"; + P = ToolChain.GetFilePath(crtend); + } + CmdArgs.push_back(Args.MakeArgString(P)); + } if (!isAndroid) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } @@ -585,14 +650,12 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, if (const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ)) { if (A->getOption().getID() == options::OPT_gz) { - CmdArgs.push_back("-compress-debug-sections"); + CmdArgs.push_back("--compress-debug-sections"); } else { StringRef Value = A->getValue(); - if (Value == "none") { - CmdArgs.push_back("-compress-debug-sections=none"); - } else if (Value == "zlib" || Value == "zlib-gnu") { + if (Value == "none" || Value == "zlib" || Value == "zlib-gnu") { CmdArgs.push_back( - Args.MakeArgString("-compress-debug-sections=" + Twine(Value))); + Args.MakeArgString("--compress-debug-sections=" + Twine(Value))); } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; @@ -600,6 +663,10 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, } } + if (getToolChain().isNoExecStackDefault()) { + CmdArgs.push_back("--noexecstack"); + } + switch (getToolChain().getArch()) { default: break; @@ -652,14 +719,16 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, case llvm::Triple::sparcel: { CmdArgs.push_back("-32"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back( + sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } case llvm::Triple::sparcv9: { CmdArgs.push_back("-64"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back( + sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } @@ -817,7 +886,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, if (Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux()) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, - SplitDebugName(Args, Output)); + SplitDebugName(Args, Inputs[0], Output)); } namespace { @@ -846,16 +915,6 @@ static bool isSoftFloatABI(const ArgList &Args) { A->getValue() == StringRef("soft")); } -/// \p Flag must be a flag accepted by the driver with its leading '-' removed, -// otherwise '-print-multi-lib' will not emit them correctly. -static void addMultilibFlag(bool Enabled, const char *const Flag, - std::vector<std::string> &Flags) { - if (Enabled) - Flags.push_back(std::string("+") + Flag); - else - Flags.push_back(std::string("-") + Flag); -} - static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) { return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb; } @@ -874,10 +933,6 @@ static bool isMicroMips(const ArgList &Args) { return A && A->getOption().matches(options::OPT_mmicromips); } -static bool isRISCV(llvm::Triple::ArchType Arch) { - return Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64; -} - static bool isMSP430(llvm::Triple::ArchType Arch) { return Arch == llvm::Triple::msp430; } @@ -1850,6 +1905,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( // Non-Solaris is much simpler - most systems just go with "/usr". if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux) { // Yet, still look for RHEL devtoolsets. + Prefixes.push_back("/opt/rh/devtoolset-8/root/usr"); Prefixes.push_back("/opt/rh/devtoolset-7/root/usr"); Prefixes.push_back("/opt/rh/devtoolset-6/root/usr"); Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); @@ -1889,6 +1945,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( static const char *const ARMebHFTriples[] = { "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"}; + static const char *const AVRLibDirs[] = {"/lib"}; + static const char *const AVRTriples[] = {"avr"}; + static const char *const X86_64LibDirs[] = {"/lib64", "/lib"}; static const char *const X86_64Triples[] = { "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", @@ -1951,10 +2010,14 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( "powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu", "powerpc64le-suse-linux", "ppc64le-redhat-linux"}; - static const char *const RISCV32LibDirs[] = {"/lib", "/lib32"}; - static const char *const RISCVTriples[] = {"riscv32-unknown-linux-gnu", - "riscv64-unknown-linux-gnu", - "riscv32-unknown-elf"}; + static const char *const RISCV32LibDirs[] = {"/lib32", "/lib"}; + static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu", + "riscv32-linux-gnu", + "riscv32-unknown-elf"}; + static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"}; + static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu", + "riscv64-linux-gnu", + "riscv64-unknown-elf"}; static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"}; static const char *const SPARCv8Triples[] = {"sparc-linux-gnu", @@ -2105,6 +2168,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( TripleAliases.append(begin(ARMebTriples), end(ARMebTriples)); } break; + case llvm::Triple::avr: + LibDirs.append(begin(AVRLibDirs), end(AVRLibDirs)); + TripleAliases.append(begin(AVRTriples), end(AVRTriples)); + break; case llvm::Triple::x86_64: LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs)); TripleAliases.append(begin(X86_64Triples), end(X86_64Triples)); @@ -2184,9 +2251,15 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( break; case llvm::Triple::riscv32: LibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs)); + TripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples)); + BiarchLibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs)); + BiarchTripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples)); + break; + case llvm::Triple::riscv64: + LibDirs.append(begin(RISCV64LibDirs), end(RISCV64LibDirs)); + TripleAliases.append(begin(RISCV64Triples), end(RISCV64Triples)); BiarchLibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs)); - TripleAliases.append(begin(RISCVTriples), end(RISCVTriples)); - BiarchTripleAliases.append(begin(RISCVTriples), end(RISCVTriples)); + BiarchTripleAliases.append(begin(RISCV32Triples), end(RISCV32Triples)); break; case llvm::Triple::sparc: case llvm::Triple::sparcel: @@ -2235,10 +2308,12 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs( } else if (TargetTriple.isMIPS()) { if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected)) return false; - } else if (isRISCV(TargetArch)) { + } else if (TargetTriple.isRISCV()) { findRISCVMultilibs(D, TargetTriple, Path, Args, Detected); } else if (isMSP430(TargetArch)) { findMSP430Multilibs(D, TargetTriple, Path, Args, Detected); + } else if (TargetArch == llvm::Triple::avr) { + // AVR has no multilibs. } else if (!findBiarchMultilibs(D, TargetTriple, Path, Args, NeedsBiarchSuffix, Detected)) { return false; @@ -2512,7 +2587,8 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const { case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::sparcv9: - if (getTriple().isOSSolaris() || getTriple().isOSOpenBSD()) + if (getTriple().isOSFreeBSD() || getTriple().isOSOpenBSD() || + getTriple().isOSSolaris()) return true; return false; default: |
