From b58561baa509f26709caaa06d2666834f51431ea Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Sat, 27 Apr 2019 00:25:13 +0000 Subject: [PATCH] [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 --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 39 +++------------- clang/lib/Driver/ToolChains/CommonArgs.h | 11 +++-- clang/lib/Driver/ToolChains/Fuchsia.cpp | 52 +++++++++++++++++++++- clang/lib/Driver/ToolChains/Gnu.cpp | 12 +---- .../aarch64-fuchsia/lib/noexcept/.keep | 0 .../x86_64-fuchsia/lib/noexcept/.keep | 0 clang/test/Driver/fuchsia.cpp | 21 +++++++++ 7 files changed, 85 insertions(+), 50 deletions(-) create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/noexcept/.keep create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/noexcept/.keep diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 16548c2..d0c9d7d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -570,40 +570,6 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, 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, ArgStringList &CmdArgs) { // 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"); return StatsFile; } + +void tools::addMultilibFlag(bool Enabled, const char *const Flag, + Multilib::flags_list &Flags) { + Flags.push_back(std::string(Enabled ? "+" : "-") + Flag); +} diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 9c64a50..9a31170 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -11,6 +11,7 @@ #include "InputInfo.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Multilib.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.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, llvm::opt::ArgStringList &CmdArgs); -void addSanitizerPathLibArgs(const ToolChain &TC, - const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs); - void linkSanitizerRuntimeDeps(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs); @@ -121,6 +118,12 @@ void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args, SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args, const InputInfo &Output, 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 driver } // end namespace clang diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index 2db2d88..c906379 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -15,7 +15,9 @@ #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" using namespace clang::driver; using namespace clang::driver::toolchains; @@ -23,6 +25,8 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +using tools::addMultilibFlag; + void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, 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_u); - addSanitizerPathLibArgs(ToolChain, Args, CmdArgs); - ToolChain.AddFilePathLibArgs(Args, CmdArgs); if (D.isUsingLTO()) { @@ -169,6 +171,52 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, llvm::sys::path::append(P, "lib"); getFilePaths().push_back(P.str()); } + + auto RuntimeDirs = [&](const Multilib &M) -> std::vector { + SmallString<128> P; + std::vector 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 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, diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 8915e3f..41c9abe 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -33,6 +33,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) { @@ -871,16 +873,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 &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; } diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/noexcept/.keep b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/aarch64-fuchsia/lib/noexcept/.keep new file mode 100644 index 0000000..e69de29 diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/noexcept/.keep b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/x86_64-fuchsia/lib/noexcept/.keep new file mode 100644 index 0000000..e69de29 diff --git a/clang/test/Driver/fuchsia.cpp b/clang/test/Driver/fuchsia.cpp index d18d496..a6d9b8e 100644 --- a/clang/test/Driver/fuchsia.cpp +++ b/clang/test/Driver/fuchsia.cpp @@ -49,3 +49,24 @@ // CHECK-NOSTDLIBXX-NOT: "-lc++" // CHECK-NOSTDLIBXX-NOT: "-lm" // 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" -- 2.7.4