diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Basic/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Basic/LangOptions.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Basic/XRayLists.cpp | 53 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 24 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 7 | ||||
-rw-r--r-- | clang/lib/Driver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChain.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Driver/XRayArgs.cpp | 113 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 8 |
12 files changed, 226 insertions, 34 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 071537a051c..b4423b00469 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 23242ba3f60..2feb31851cf 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 ff10a773a97..c8a774311ef 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 00000000000..dccf3baa75e --- /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<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/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 11660b4f419..79c0694f902 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 89ee7fc74c3..035165cdb9e 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 5c9dd965e85..ce8c58224c5 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 0d7a99766b8..43d6aa8f99b 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 f9dafb54753..4f82503276f 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 0511004b41b..f8eeeb4eef6 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 00000000000..59a35f11151 --- /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 0c1d6d0d854..bea29e2de7c 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, |