diff options
author | Dean Michael Berris <dberris@google.com> | 2017-03-30 00:29:36 +0000 |
---|---|---|
committer | Dean Michael Berris <dberris@google.com> | 2017-03-30 00:29:36 +0000 |
commit | ca9fad67afe0d4c4757747486a116b3fca09e565 (patch) | |
tree | d1585384d6ac980a0e4946f28d27568ed7908bfb | |
parent | 6cecba61e47d6be93136d0caaeba3d7e54962e8f (diff) | |
download | clang-ca9fad67afe0d4c4757747486a116b3fca09e565.tar.gz |
[XRay] Add -fxray-{always,never}-instrument= flags to clang
Summary:
The -fxray-always-instrument= and -fxray-never-instrument= flags take
filenames that are used to imbue the XRay instrumentation attributes
using a whitelist mechanism (similar to the sanitizer special cases
list). We use the same syntax and semantics as the sanitizer blacklists
files in the implementation.
As implemented, we respect the attributes that are already defined in
the source file (i.e. those that have the
[[clang::xray_{always,never}_instrument]] attributes) before applying
the always/never instrument lists.
Reviewers: rsmith, chandlerc
Subscribers: jfb, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D30388
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@299041 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 9 | ||||
-rw-r--r-- | include/clang/Basic/LangOptions.def | 2 | ||||
-rw-r--r-- | include/clang/Basic/LangOptions.h | 10 | ||||
-rw-r--r-- | include/clang/Basic/XRayLists.h | 54 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 9 | ||||
-rw-r--r-- | include/clang/Driver/ToolChain.h | 4 | ||||
-rw-r--r-- | include/clang/Driver/XRayArgs.h | 38 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | lib/Basic/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Basic/LangOptions.cpp | 2 | ||||
-rw-r--r-- | lib/Basic/XRayLists.cpp | 53 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 24 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 7 | ||||
-rw-r--r-- | lib/Driver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Driver/ToolChain.cpp | 7 | ||||
-rw-r--r-- | lib/Driver/ToolChains/Clang.cpp | 35 | ||||
-rw-r--r-- | lib/Driver/XRayArgs.cpp | 113 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 8 | ||||
-rw-r--r-- | test/CodeGen/xray-always-instrument.cpp | 15 |
20 files changed, 367 insertions, 34 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 5fa515d02d..d52c07200c 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -39,6 +39,7 @@ #include "clang/Basic/SanitizerBlacklist.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/XRayLists.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -475,6 +476,10 @@ private: /// entities should not be instrumented. std::unique_ptr<SanitizerBlacklist> SanitizerBL; + /// \breif Function filtering mehcanism to determine whether a given function + /// should be imbued with the XRay "always" or "never" attributes. + std::unique_ptr<XRayFunctionFilter> XRayFilter; + /// \brief The allocator used to create AST objects. /// /// AST objects are never destructed; rather, all memory associated with the @@ -657,6 +662,10 @@ public: return *SanitizerBL; } + const XRayFunctionFilter &getXRayFilter() const { + return *XRayFilter; + } + DiagnosticsEngine &getDiagnostics() const; FullSourceLoc getFullLoc(SourceLocation Loc) const { diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index d00aa411de..1a142b8b74 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -263,6 +263,8 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan " "field padding (0: none, 1:least " "aggressive, 2: more aggressive)") +LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 16abf9b7bb..e684ec1ba9 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -102,6 +102,16 @@ public: /// (files, functions, variables) should not be instrumented. std::vector<std::string> SanitizerBlacklistFiles; + /// \brief Paths to the XRay "always instrument" files specifying which + /// objects (files, functions, variables) should be imbued with the XRay + /// "always instrument" attribute. + std::vector<std::string> XRayAlwaysInstrumentFiles; + + /// \brief Paths to the XRay "never instrument" files specifying which + /// objects (files, functions, variables) should be imbued with the XRay + /// "never instrument" attribute. + std::vector<std::string> XRayNeverInstrumentFiles; + clang::ObjCRuntime ObjCRuntime; std::string ObjCConstantStringClass; diff --git a/include/clang/Basic/XRayLists.h b/include/clang/Basic/XRayLists.h new file mode 100644 index 0000000000..fe538289c3 --- /dev/null +++ b/include/clang/Basic/XRayLists.h @@ -0,0 +1,54 @@ +//===--- XRayLists.h - XRay automatic attribution ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// User-provided filters for always/never XRay instrumenting certain functions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_XRAYLISTS_H +#define LLVM_CLANG_BASIC_XRAYLISTS_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SpecialCaseList.h" +#include <memory> + +namespace clang { + +class XRayFunctionFilter { + std::unique_ptr<llvm::SpecialCaseList> AlwaysInstrument; + std::unique_ptr<llvm::SpecialCaseList> NeverInstrument; + SourceManager &SM; + +public: + XRayFunctionFilter(ArrayRef<std::string> AlwaysInstrumentPaths, + ArrayRef<std::string> NeverInstrumentPaths, + SourceManager &SM); + + enum class ImbueAttribute { + NONE, + ALWAYS, + NEVER, + }; + + ImbueAttribute shouldImbueFunction(StringRef FunctionName) const; + + ImbueAttribute + shouldImbueFunctionsInFile(StringRef Filename, + StringRef Category = StringRef()) const; + + ImbueAttribute shouldImbueLocation(SourceLocation Loc, + StringRef Category = StringRef()) const; +}; + +} // namespace clang + +#endif diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 06d4a244c1..12b7ca21fc 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -962,6 +962,15 @@ def fxray_instruction_threshold_ : JoinedOrSeparate<["-"], "fxray-instruction-threshold">, Group<f_Group>, Flags<[CC1Option]>; +def fxray_always_instrument : + JoinedOrSeparate<["-"], "fxray-always-instrument=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">; +def fxray_never_instrument : + JoinedOrSeparate<["-"], "fxray-never-instrument=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; + def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index f8e5fde2cd..105d0f338a 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -44,6 +44,7 @@ namespace driver { class RegisterEffectiveTriple; class SanitizerArgs; class Tool; + class XRayArgs; /// ToolChain - Access to tools for a single platform. class ToolChain { @@ -94,6 +95,7 @@ private: Tool *getOffloadBundler() const; mutable std::unique_ptr<SanitizerArgs> SanitizerArguments; + mutable std::unique_ptr<XRayArgs> XRayArguments; /// The effective clang triple for the current Job. mutable llvm::Triple EffectiveTriple; @@ -177,6 +179,8 @@ public: const SanitizerArgs& getSanitizerArgs() const; + const XRayArgs& getXRayArgs() const; + // Returns the Arg * that explicitly turned on/off rtti, or nullptr. const llvm::opt::Arg *getRTTIArg() const { return CachedRTTIArg; } diff --git a/include/clang/Driver/XRayArgs.h b/include/clang/Driver/XRayArgs.h new file mode 100644 index 0000000000..83210d100a --- /dev/null +++ b/include/clang/Driver/XRayArgs.h @@ -0,0 +1,38 @@ +//===--- XRayArgs.h - Arguments for XRay ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_DRIVER_XRAYARGS_H +#define LLVM_CLANG_DRIVER_XRAYARGS_H + +#include "clang/Driver/Types.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" + +namespace clang { +namespace driver { + +class ToolChain; + +class XRayArgs { + std::vector<std::string> AlwaysInstrumentFiles; + std::vector<std::string> NeverInstrumentFiles; + std::vector<std::string> ExtraDeps; + bool XRayInstrument = false; + int InstructionThreshold = 200; + +public: + /// Parses the XRay arguments from an argument list. + XRayArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); + void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const; +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_XRAYARGS_H diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 071537a051..b4423b0046 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -748,6 +748,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, ExternCContext(nullptr), MakeIntegerSeqDecl(nullptr), TypePackElementDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), + XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, + LangOpts.XRayNeverInstrumentFiles, SM)), AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr), diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt index 23242ba3f6..2feb31851c 100644 --- a/lib/Basic/CMakeLists.txt +++ b/lib/Basic/CMakeLists.txt @@ -90,6 +90,7 @@ add_clang_library(clangBasic VersionTuple.cpp VirtualFileSystem.cpp Warnings.cpp + XRayLists.cpp ${version_inc} ) diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index ff10a773a9..c8a774311e 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -33,6 +33,8 @@ void LangOptions::resetNonModularOptions() { // sanitizer options (this affects __has_feature(address_sanitizer) etc). Sanitize.clear(); SanitizerBlacklistFiles.clear(); + XRayAlwaysInstrumentFiles.clear(); + XRayNeverInstrumentFiles.clear(); CurrentModule.clear(); IsHeaderFile = false; diff --git a/lib/Basic/XRayLists.cpp b/lib/Basic/XRayLists.cpp new file mode 100644 index 0000000000..dccf3baa75 --- /dev/null +++ b/lib/Basic/XRayLists.cpp @@ -0,0 +1,53 @@ +//===--- XRayFunctionFilter.cpp - XRay automatic-attribution --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// User-provided filters for always/never XRay instrumenting certain functions. +// +//===----------------------------------------------------------------------===// +#include "clang/Basic/XRayLists.h" + +using namespace clang; + +XRayFunctionFilter::XRayFunctionFilter( + ArrayRef<std::string> AlwaysInstrumentPaths, + ArrayRef<std::string> NeverInstrumentPaths, SourceManager &SM) + : AlwaysInstrument( + llvm::SpecialCaseList::createOrDie(AlwaysInstrumentPaths)), + NeverInstrument(llvm::SpecialCaseList::createOrDie(NeverInstrumentPaths)), + SM(SM) {} + +XRayFunctionFilter::ImbueAttribute +XRayFunctionFilter::shouldImbueFunction(StringRef FunctionName) const { + // First apply the always instrument list, than if it isn't an "always" see + // whether it's treated as a "never" instrument function. + if (AlwaysInstrument->inSection("fun", FunctionName)) + return ImbueAttribute::ALWAYS; + if (NeverInstrument->inSection("fun", FunctionName)) + return ImbueAttribute::NEVER; + return ImbueAttribute::NONE; +} + +XRayFunctionFilter::ImbueAttribute +XRayFunctionFilter::shouldImbueFunctionsInFile(StringRef Filename, + StringRef Category) const { + if (AlwaysInstrument->inSection("src", Filename, Category)) + return ImbueAttribute::ALWAYS; + if (NeverInstrument->inSection("src", Filename, Category)) + return ImbueAttribute::NEVER; + return ImbueAttribute::NONE; +} + +XRayFunctionFilter::ImbueAttribute +XRayFunctionFilter::shouldImbueLocation(SourceLocation Loc, + StringRef Category) const { + if (!Loc.isValid()) + return ImbueAttribute::NONE; + return this->shouldImbueFunctionsInFile(SM.getFilename(SM.getFileLoc(Loc)), + Category); +} diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 11660b4f41..79c0694f90 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -786,9 +786,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, llvm::utostr(LogArgs->getArgumentCount())); } } else { - Fn->addFnAttr( - "xray-instruction-threshold", - llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold)); + if (!CGM.imbueXRayAttrs(Fn, Loc)) + Fn->addFnAttr( + "xray-instruction-threshold", + llvm::itostr(CGM.getCodeGenOpts().XRayInstructionThreshold)); } } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 89ee7fc74c..035165cdb9 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1489,6 +1489,30 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV, return false; } +bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, + StringRef Category) const { + if (!LangOpts.XRayInstrument) + return false; + const auto &XRayFilter = getContext().getXRayFilter(); + using ImbueAttr = XRayFunctionFilter::ImbueAttribute; + auto Attr = XRayFunctionFilter::ImbueAttribute::NONE; + if (Loc.isValid()) + Attr = XRayFilter.shouldImbueLocation(Loc, Category); + if (Attr == ImbueAttr::NONE) + Attr = XRayFilter.shouldImbueFunction(Fn->getName()); + switch (Attr) { + case ImbueAttr::NONE: + return false; + case ImbueAttr::ALWAYS: + Fn->addFnAttr("function-instrument", "xray-always"); + break; + case ImbueAttr::NEVER: + Fn->addFnAttr("function-instrument", "xray-never"); + break; + } + return true; +} + bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) { // Never defer when EmitAllDecls is specified. if (LangOpts.EmitAllDecls) diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 5c9dd965e8..ce8c58224c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -28,6 +28,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/SanitizerBlacklist.h" +#include "clang/Basic/XRayLists.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -1125,6 +1126,12 @@ public: QualType Ty, StringRef Category = StringRef()) const; + /// Imbue XRay attributes to a function, applying the always/never attribute + /// lists in the process. Returns true if we did imbue attributes this way, + /// false otherwise. + bool imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, + StringRef Category = StringRef()) const; + SanitizerMetadata *getSanitizerMetadata() { return SanitizerMD.get(); } diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt index 0d7a99766b..43d6aa8f99 100644 --- a/lib/Driver/CMakeLists.txt +++ b/lib/Driver/CMakeLists.txt @@ -58,6 +58,7 @@ add_clang_library(clangDriver ToolChains/WebAssembly.cpp ToolChains/XCore.cpp Types.cpp + XRayArgs.cpp DEPENDS ClangDriverOptions diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index f9dafb5475..4f82503276 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -19,6 +19,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/XRayArgs.h" #include "llvm/ADT/SmallString.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" @@ -100,6 +101,12 @@ const SanitizerArgs& ToolChain::getSanitizerArgs() const { return *SanitizerArguments.get(); } +const XRayArgs& ToolChain::getXRayArgs() const { + if (!XRayArguments.get()) + XRayArguments.reset(new XRayArgs(*this, Args)); + return *XRayArguments.get(); +} + namespace { struct DriverSuffix { const char *Suffix; diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 0511004b41..f8eeeb4eef 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -27,6 +27,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/XRayArgs.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" @@ -2818,37 +2819,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); - if (Args.hasFlag(options::OPT_fxray_instrument, - options::OPT_fnoxray_instrument, false)) { - const char *const XRayInstrumentOption = "-fxray-instrument"; - if (Triple.getOS() == llvm::Triple::Linux) - switch (Triple.getArch()) { - case llvm::Triple::x86_64: - case llvm::Triple::arm: - case llvm::Triple::aarch64: - case llvm::Triple::ppc64le: - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - // Supported. - break; - default: - D.Diag(diag::err_drv_clang_unsupported) - << (std::string(XRayInstrumentOption) + " on " + Triple.str()); - } - else - D.Diag(diag::err_drv_clang_unsupported) - << (std::string(XRayInstrumentOption) + " on non-Linux target OS"); - CmdArgs.push_back(XRayInstrumentOption); - if (const Arg *A = - Args.getLastArg(options::OPT_fxray_instruction_threshold_, - options::OPT_fxray_instruction_threshold_EQ)) { - CmdArgs.push_back("-fxray-instruction-threshold"); - CmdArgs.push_back(A->getValue()); - } - } - addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs); // Add runtime flag for PS4 when PGO or Coverage are enabled. @@ -3238,6 +3208,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType); + const XRayArgs &XRay = getToolChain().getXRayArgs(); + XRay.addArgs(getToolChain(), Args, CmdArgs, InputType); + if (getToolChain().SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); diff --git a/lib/Driver/XRayArgs.cpp b/lib/Driver/XRayArgs.cpp new file mode 100644 index 0000000000..59a35f1115 --- /dev/null +++ b/lib/Driver/XRayArgs.cpp @@ -0,0 +1,113 @@ +//===--- XRayArgs.cpp - Arguments for XRay --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "clang/Driver/XRayArgs.h" +#include "ToolChains/CommonArgs.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/ToolChain.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/SpecialCaseList.h" + +using namespace clang; +using namespace clang::driver; +using namespace llvm::opt; + +namespace { +constexpr char XRayInstrumentOption[] = "-fxray-instrument"; +constexpr char XRayInstructionThresholdOption[] = + "-fxray-instruction-threshold="; +constexpr char XRayAlwaysInstrumentOption[] = "-fxray-always-instrument="; +constexpr char XRayNeverInstrumentOption[] = "-fxray-never-instrument="; +} // namespace + +XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) { + const Driver &D = TC.getDriver(); + const llvm::Triple &Triple = TC.getTriple(); + if (Args.hasFlag(options::OPT_fxray_instrument, + options::OPT_fnoxray_instrument, false)) { + if (Triple.getOS() == llvm::Triple::Linux) + switch (Triple.getArch()) { + case llvm::Triple::x86_64: + case llvm::Triple::arm: + case llvm::Triple::aarch64: + case llvm::Triple::ppc64le: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + break; + default: + D.Diag(diag::err_drv_clang_unsupported) + << (std::string(XRayInstrumentOption) + " on " + Triple.str()); + } + else + D.Diag(diag::err_drv_clang_unsupported) + << (std::string(XRayInstrumentOption) + " on non-Linux target OS"); + XRayInstrument = true; + if (const Arg *A = + Args.getLastArg(options::OPT_fxray_instruction_threshold_, + options::OPT_fxray_instruction_threshold_EQ)) { + StringRef S = A->getValue(); + if (S.getAsInteger(0, InstructionThreshold) || InstructionThreshold < 0) + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + } + + // Validate the always/never attribute files. We also make sure that they + // are treated as actual dependencies. + for (const auto &Filename : + Args.getAllArgValues(options::OPT_fxray_always_instrument)) { + if (llvm::sys::fs::exists(Filename)) { + AlwaysInstrumentFiles.push_back(Filename); + ExtraDeps.push_back(Filename); + } else + D.Diag(clang::diag::err_drv_no_such_file) << Filename; + } + + for (const auto &Filename : + Args.getAllArgValues(options::OPT_fxray_never_instrument)) { + if (llvm::sys::fs::exists(Filename)) { + NeverInstrumentFiles.push_back(Filename); + ExtraDeps.push_back(Filename); + } else + D.Diag(clang::diag::err_drv_no_such_file) << Filename; + } + } +} + +void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, types::ID InputType) const { + if (!XRayInstrument) + return; + + CmdArgs.push_back(XRayInstrumentOption); + CmdArgs.push_back(Args.MakeArgString(XRayInstructionThresholdOption + + std::to_string(InstructionThreshold))); + + for (const auto &Always : AlwaysInstrumentFiles) { + SmallString<64> AlwaysInstrumentOpt(XRayAlwaysInstrumentOption); + AlwaysInstrumentOpt += Always; + CmdArgs.push_back(Args.MakeArgString(AlwaysInstrumentOpt)); + } + + for (const auto &Never : NeverInstrumentFiles) { + SmallString<64> NeverInstrumentOpt(XRayNeverInstrumentOption); + NeverInstrumentOpt += Never; + CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt)); + } + + for (const auto &Dep : ExtraDeps) { + SmallString<64> ExtraDepOpt("-fdepfile-entry="); + ExtraDepOpt += Dep; + CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt)); + } +} diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 0c1d6d0d85..bea29e2de7 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2307,6 +2307,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeAddressFieldPadding = getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags); Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist); + + // -fxray-{always,never}-instrument= filenames. + Opts.XRayInstrument = + Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false); + Opts.XRayAlwaysInstrumentFiles = + Args.getAllArgValues(OPT_fxray_always_instrument); + Opts.XRayNeverInstrumentFiles = + Args.getAllArgValues(OPT_fxray_never_instrument); } static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, diff --git a/test/CodeGen/xray-always-instrument.cpp b/test/CodeGen/xray-always-instrument.cpp new file mode 100644 index 0000000000..60d8595699 --- /dev/null +++ b/test/CodeGen/xray-always-instrument.cpp @@ -0,0 +1,15 @@ +// RUN: echo "fun:*foo*" > %t.always-instrument +// RUN: echo "src:*xray-always-instrument.cpp" >> %t.always-instrument +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s -triple x86_64-unknown-linux-gnu | FileCheck %s + +void foo() {} + +[[clang::xray_never_instrument]] void bar() {} + +void baz() {} + +// CHECK: define void @_Z3foov() #[[ALWAYSATTR:[0-9]+]] { +// CHECK: define void @_Z3barv() #[[NEVERATTR:[0-9]+]] { +// CHECK: define void @_Z3bazv() #[[ALWAYSATTR:[0-9]+]] { +// CHECK: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}} +// CHECK: attributes #[[NEVERATTR]] = {{.*}} "function-instrument"="xray-never" {{.*}} |