Skip to content

Commit

Permalink
[XRay] Add -fxray-{always,never}-instrument= flags to clang
Browse files Browse the repository at this point in the history
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
  • Loading branch information
deanberris committed Mar 30, 2017
1 parent 2ccbac3 commit 835832d
Show file tree
Hide file tree
Showing 20 changed files with 367 additions and 34 deletions.
9 changes: 9 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -475,6 +476,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// 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
Expand Down Expand Up @@ -657,6 +662,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
return *SanitizerBL;
}

const XRayFunctionFilter &getXRayFilter() const {
return *XRayFilter;
}

DiagnosticsEngine &getDiagnostics() const;

FullSourceLoc getFullLoc(SourceLocation Loc) const {
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ class LangOptions : public LangOptionsBase {
/// (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;
Expand Down
54 changes: 54 additions & 0 deletions clang/include/clang/Basic/XRayLists.h
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/ToolChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace driver {
class RegisterEffectiveTriple;
class SanitizerArgs;
class Tool;
class XRayArgs;

/// ToolChain - Access to tools for a single platform.
class ToolChain {
Expand Down Expand Up @@ -94,6 +95,7 @@ class ToolChain {
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;
Expand Down Expand Up @@ -177,6 +179,8 @@ class ToolChain {

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; }

Expand Down
38 changes: 38 additions & 0 deletions clang/include/clang/Driver/XRayArgs.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ add_clang_library(clangBasic
VersionTuple.cpp
VirtualFileSystem.cpp
Warnings.cpp
XRayLists.cpp
${version_inc}
)

2 changes: 2 additions & 0 deletions clang/lib/Basic/LangOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
53 changes: 53 additions & 0 deletions clang/lib/Basic/XRayLists.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
7 changes: 4 additions & 3 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}

Expand Down
24 changes: 24 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1125,6 +1126,12 @@ class CodeGenModule : public CodeGenTypeCache {
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();
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ add_clang_library(clangDriver
ToolChains/WebAssembly.cpp
ToolChains/XCore.cpp
Types.cpp
XRayArgs.cpp

DEPENDS
ClangDriverOptions
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 835832d

Please sign in to comment.