[Fuchsia] Support multilib for -fsanitize=address and -fno-exceptions

This introduces a support for multilibs to Fuchsia driver. Unlike the
existing multilibs that are used primarily for handling different
architecture variants, we use multilibs to handle different variants
of Clang runtime libraries: -fsanitize=address and -fno-exceptions
are the two we support initially. This replaces the existing support
for sanitized runtimes libraries that was only used by Fuchsia driver
and it also refactors some of the logic to allow sharing between GNU
and Fuchsia drivers.

Differential Revision: https://reviews.llvm.org/D61040

llvm-svn: 359360
This commit is contained in:
Petr Hosek 2019-04-27 00:25:13 +00:00
parent 0f9f021d05
commit b58561baa5
7 changed files with 85 additions and 50 deletions

View File

@ -570,40 +570,6 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
return false; return false;
} }
static void addSanitizerLibPath(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, StringRef Name) {
for (const auto &LibPath : TC.getLibraryPaths()) {
if (!LibPath.empty()) {
SmallString<128> P(LibPath);
llvm::sys::path::append(P, Name);
if (TC.getVFS().exists(P))
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P));
}
}
}
void tools::addSanitizerPathLibArgs(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
if (SanArgs.needsAsanRt()) {
addSanitizerLibPath(TC, Args, CmdArgs, "asan");
}
if (SanArgs.needsHwasanRt()) {
addSanitizerLibPath(TC, Args, CmdArgs, "hwasan");
}
if (SanArgs.needsLsanRt()) {
addSanitizerLibPath(TC, Args, CmdArgs, "lsan");
}
if (SanArgs.needsMsanRt()) {
addSanitizerLibPath(TC, Args, CmdArgs, "msan");
}
if (SanArgs.needsTsanRt()) {
addSanitizerLibPath(TC, Args, CmdArgs, "tsan");
}
}
void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
ArgStringList &CmdArgs) { ArgStringList &CmdArgs) {
// Force linking against the system libraries sanitizers depends on // Force linking against the system libraries sanitizers depends on
@ -1535,3 +1501,8 @@ SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,
llvm::sys::path::replace_extension(StatsFile, "stats"); llvm::sys::path::replace_extension(StatsFile, "stats");
return StatsFile; return StatsFile;
} }
void tools::addMultilibFlag(bool Enabled, const char *const Flag,
Multilib::flags_list &Flags) {
Flags.push_back(std::string(Enabled ? "+" : "-") + Flag);
}

View File

@ -11,6 +11,7 @@
#include "InputInfo.h" #include "InputInfo.h"
#include "clang/Driver/Driver.h" #include "clang/Driver/Driver.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Tool.h" #include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h" #include "clang/Driver/ToolChain.h"
#include "llvm/Support/CodeGen.h" #include "llvm/Support/CodeGen.h"
@ -31,10 +32,6 @@ void claimNoWarnArgs(const llvm::opt::ArgList &Args);
bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args, bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs); llvm::opt::ArgStringList &CmdArgs);
void addSanitizerPathLibArgs(const ToolChain &TC,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
void linkSanitizerRuntimeDeps(const ToolChain &TC, void linkSanitizerRuntimeDeps(const ToolChain &TC,
llvm::opt::ArgStringList &CmdArgs); llvm::opt::ArgStringList &CmdArgs);
@ -121,6 +118,12 @@ void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args,
SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args, SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args,
const InputInfo &Output, const InputInfo &Output,
const InputInfo &Input, const Driver &D); const InputInfo &Input, const Driver &D);
/// \p Flag must be a flag accepted by the driver with its leading '-' removed,
// otherwise '-print-multi-lib' will not emit them correctly.
void addMultilibFlag(bool Enabled, const char *const Flag,
Multilib::flags_list &Flags);
} // end namespace tools } // end namespace tools
} // end namespace driver } // end namespace driver
} // end namespace clang } // end namespace clang

View File

@ -15,7 +15,9 @@
#include "clang/Driver/Options.h" #include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h" #include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver; using namespace clang::driver;
using namespace clang::driver::toolchains; using namespace clang::driver::toolchains;
@ -23,6 +25,8 @@ using namespace clang::driver::tools;
using namespace clang; using namespace clang;
using namespace llvm::opt; using namespace llvm::opt;
using tools::addMultilibFlag;
void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfo &Output,
const InputInfoList &Inputs, const InputInfoList &Inputs,
@ -98,8 +102,6 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_u); Args.AddAllArgs(CmdArgs, options::OPT_u);
addSanitizerPathLibArgs(ToolChain, Args, CmdArgs);
ToolChain.AddFilePathLibArgs(Args, CmdArgs); ToolChain.AddFilePathLibArgs(Args, CmdArgs);
if (D.isUsingLTO()) { if (D.isUsingLTO()) {
@ -169,6 +171,52 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
llvm::sys::path::append(P, "lib"); llvm::sys::path::append(P, "lib");
getFilePaths().push_back(P.str()); getFilePaths().push_back(P.str());
} }
auto RuntimeDirs = [&](const Multilib &M) -> std::vector<std::string> {
SmallString<128> P;
std::vector<std::string> RD;
P.assign(D.ResourceDir);
llvm::sys::path::append(P, D.getTargetTriple(), "lib", M.gccSuffix());
if (getVFS().exists(P))
RD.push_back(P.str());
P.assign(D.ResourceDir);
llvm::sys::path::append(P, Triple.str(), "lib", M.gccSuffix());
if (getVFS().exists(P))
RD.push_back(P.str());
return RD;
};
Multilibs.push_back(Multilib());
// Use the noexcept variant with -fno-exceptions to avoid the extra overhead.
Multilibs.push_back(Multilib("noexcept", {}, {}, 1)
.flag("-fexceptions")
.flag("+fno-exceptions"));
// ASan has higher priority because we always want the instrumentated version.
Multilibs.push_back(Multilib("asan", {}, {}, 2)
.flag("+fsanitize=address"));
Multilibs.FilterOut([&](const Multilib &M) {
std::vector<std::string> RD = RuntimeDirs(M);
return std::all_of(RD.begin(), RD.end(), [&](std::string P) {
return !getVFS().exists(P);
});
});
Multilib::flags_list Flags;
addMultilibFlag(
Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true),
"fexceptions", Flags);
addMultilibFlag(getSanitizerArgs().needsAsanRt(), "fsanitize=address", Flags);
Multilibs.setFilePathsCallback(RuntimeDirs);
if (Multilibs.select(Flags, SelectedMultilib))
if (!SelectedMultilib.isDefault())
if (const auto &PathsCallback = Multilibs.filePathsCallback())
for (const auto &Path : PathsCallback(SelectedMultilib))
// We need to prepend the multilib path to ensure it takes precedence.
getLibraryPaths().insert(getLibraryPaths().begin(), Path);
} }
std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args, std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args,

View File

@ -33,6 +33,8 @@ using namespace clang::driver::toolchains;
using namespace clang; using namespace clang;
using namespace llvm::opt; using namespace llvm::opt;
using tools::addMultilibFlag;
void tools::GnuTool::anchor() {} void tools::GnuTool::anchor() {}
static bool forwardToGCC(const Option &O) { static bool forwardToGCC(const Option &O) {
@ -871,16 +873,6 @@ static bool isSoftFloatABI(const ArgList &Args) {
A->getValue() == StringRef("soft")); 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) { static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb; return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb;
} }

View File

@ -49,3 +49,24 @@
// CHECK-NOSTDLIBXX-NOT: "-lc++" // CHECK-NOSTDLIBXX-NOT: "-lc++"
// CHECK-NOSTDLIBXX-NOT: "-lm" // CHECK-NOSTDLIBXX-NOT: "-lm"
// CHECK-NOSTDLIBXX: "-lc" // CHECK-NOSTDLIBXX: "-lc"
// RUN: %clang %s -### --target=x86_64-fuchsia \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: -fuse-ld=lld 2>&1\
// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86
// RUN: %clang %s -### --target=x86_64-fuchsia -fsanitize=address \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: -fuse-ld=lld 2>&1\
// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-X86
// RUN: %clang %s -### --target=x86_64-fuchsia -fno-exceptions \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: -fuse-ld=lld 2>&1\
// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-NOEXCEPT-X86
// RUN: %clang %s -### --target=x86_64-fuchsia -fsanitize=address -fno-exceptions \
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
// RUN: -fuse-ld=lld 2>&1\
// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-X86
// CHECK-MULTILIB-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
// CHECK-MULTILIB-ASAN-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}asan"
// CHECK-MULTILIB-NOEXCEPT-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}noexcept"
// CHECK-MULTILIB-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib"