From 835832d37af3401601264fcd620e9af5720f041f Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Thu, 30 Mar 2017 00:29:36 +0000 Subject: [PATCH] [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 llvm-svn: 299041 --- clang/include/clang/AST/ASTContext.h | 9 ++ clang/include/clang/Basic/LangOptions.def | 2 + clang/include/clang/Basic/LangOptions.h | 10 +++ clang/include/clang/Basic/XRayLists.h | 54 ++++++++++++ clang/include/clang/Driver/Options.td | 9 ++ clang/include/clang/Driver/ToolChain.h | 4 + clang/include/clang/Driver/XRayArgs.h | 38 +++++++++ clang/lib/AST/ASTContext.cpp | 2 + clang/lib/Basic/CMakeLists.txt | 1 + clang/lib/Basic/LangOptions.cpp | 2 + clang/lib/Basic/XRayLists.cpp | 53 ++++++++++++ clang/lib/CodeGen/CodeGenFunction.cpp | 7 +- clang/lib/CodeGen/CodeGenModule.cpp | 24 ++++++ clang/lib/CodeGen/CodeGenModule.h | 7 ++ clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/ToolChain.cpp | 7 ++ clang/lib/Driver/ToolChains/Clang.cpp | 35 +------- clang/lib/Driver/XRayArgs.cpp | 113 ++++++++++++++++++++++++++ clang/lib/Frontend/CompilerInvocation.cpp | 8 ++ clang/test/CodeGen/xray-always-instrument.cpp | 15 ++++ 20 files changed, 367 insertions(+), 34 deletions(-) create mode 100644 clang/include/clang/Basic/XRayLists.h create mode 100644 clang/include/clang/Driver/XRayArgs.h create mode 100644 clang/lib/Basic/XRayLists.cpp create mode 100644 clang/lib/Driver/XRayArgs.cpp create mode 100644 clang/test/CodeGen/xray-always-instrument.cpp diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 5fa515d..d52c0720 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/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 SanitizerBL; + /// \breif Function filtering mehcanism to determine whether a given function + /// should be imbued with the XRay "always" or "never" attributes. + std::unique_ptr 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/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index d00aa41..1a142b8 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/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/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 16abf9b..e684ec1 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -102,6 +102,16 @@ public: /// (files, functions, variables) should not be instrumented. std::vector 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 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 XRayNeverInstrumentFiles; + clang::ObjCRuntime ObjCRuntime; std::string ObjCConstantStringClass; diff --git a/clang/include/clang/Basic/XRayLists.h b/clang/include/clang/Basic/XRayLists.h new file mode 100644 index 0000000..fe53828 --- /dev/null +++ b/clang/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 + +namespace clang { + +class XRayFunctionFilter { + std::unique_ptr AlwaysInstrument; + std::unique_ptr NeverInstrument; + SourceManager &SM; + +public: + XRayFunctionFilter(ArrayRef AlwaysInstrumentPaths, + ArrayRef 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/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 06d4a24..12b7ca2 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -962,6 +962,15 @@ def fxray_instruction_threshold_ : JoinedOrSeparate<["-"], "fxray-instruction-threshold">, Group, Flags<[CC1Option]>; +def fxray_always_instrument : + JoinedOrSeparate<["-"], "fxray-always-instrument=">, + Group, Flags<[CC1Option]>, + HelpText<"Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">; +def fxray_never_instrument : + JoinedOrSeparate<["-"], "fxray-never-instrument=">, + 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; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group; diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index f8e5fde..105d0f3 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/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 SanitizerArguments; + mutable std::unique_ptr 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/clang/include/clang/Driver/XRayArgs.h b/clang/include/clang/Driver/XRayArgs.h new file mode 100644 index 0000000..83210d1 --- /dev/null +++ b/clang/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 AlwaysInstrumentFiles; + std::vector NeverInstrumentFiles; + std::vector 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/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 071537a..b4423b0 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index 23242ba..2feb318 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/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/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp index ff10a77..c8a7743 100644 --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/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/clang/lib/Basic/XRayLists.cpp b/clang/lib/Basic/XRayLists.cpp new file mode 100644 index 0000000..dccf3ba --- /dev/null +++ b/clang/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 AlwaysInstrumentPaths, + ArrayRef 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/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 11660b4..79c0694 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 89ee7fc..035165c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 5c9dd96..ce8c582 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/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/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 0d7a997..43d6aa8 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/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/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index f9dafb5..4f82503 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/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/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 0511004..f8eeeb4 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/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/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp new file mode 100644 index 0000000..59a35f1 --- /dev/null +++ b/clang/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/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 0c1d6d0..bea29e2 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/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/clang/test/CodeGen/xray-always-instrument.cpp b/clang/test/CodeGen/xray-always-instrument.cpp new file mode 100644 index 0000000..60d8595 --- /dev/null +++ b/clang/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" {{.*}} -- 2.7.4