summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorMarcin Koscielnicki <koriakin@0x04.net>2016-06-18 10:10:37 +0000
committerMarcin Koscielnicki <koriakin@0x04.net>2016-06-18 10:10:37 +0000
commit3feda222c6fb290718ee23f585b6e07afb6559cb (patch)
tree6988a77a67614fd03986c589c000b5aeea41357e /llvm/lib
parent7cb30664fcc510c484224677c641187b8996cd00 (diff)
downloadbcm5719-llvm-3feda222c6fb290718ee23f585b6e07afb6559cb.tar.gz
bcm5719-llvm-3feda222c6fb290718ee23f585b6e07afb6559cb.zip
[sanitizers] Disable target-specific lowering of string functions.
CodeGen has hooks that allow targets to emit specialized code instead of calls to memcmp, memchr, strcpy, stpcpy, strcmp, strlen, strnlen. When ASan/MSan/TSan/ESan is in use, this sidesteps its interceptors, resulting in uninstrumented memory accesses. To avoid that, make these sanitizers mark the calls as nobuiltin. Differential Revision: http://reviews.llvm.org/D19781 llvm-svn: 273083
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp6
-rw-r--r--llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp20
-rw-r--r--llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp17
-rw-r--r--llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp19
-rw-r--r--llvm/lib/Transforms/Utils/Local.cpp26
5 files changed, 80 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 16a55527c20..599b2cc5b36 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1765,6 +1765,8 @@ bool AddressSanitizer::runOnFunction(Function &F) {
bool IsWrite;
unsigned Alignment;
uint64_t TypeSize;
+ const TargetLibraryInfo *TLI =
+ &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
// Fill the set of memory operations to instrument.
for (auto &BB : F) {
@@ -1793,6 +1795,8 @@ bool AddressSanitizer::runOnFunction(Function &F) {
TempsToInstrument.clear();
if (CS.doesNotReturn()) NoReturnCalls.push_back(CS.getInstruction());
}
+ if (CallInst *CI = dyn_cast<CallInst>(&Inst))
+ maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI);
continue;
}
ToInstrument.push_back(&Inst);
@@ -1805,8 +1809,6 @@ bool AddressSanitizer::runOnFunction(Function &F) {
CompileKernel ||
(ClInstrumentationWithCallsThreshold >= 0 &&
ToInstrument.size() > (unsigned)ClInstrumentationWithCallsThreshold);
- const TargetLibraryInfo *TLI =
- &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
const DataLayout &DL = F.getParent()->getDataLayout();
ObjectSizeOffsetVisitor ObjSizeVis(DL, TLI, F.getContext(),
/*RoundToAlign=*/true);
diff --git a/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
index c5dac62a3b1..eeb314d74ad 100644
--- a/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
@@ -23,6 +23,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -32,6 +33,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
using namespace llvm;
@@ -149,6 +151,7 @@ public:
const EfficiencySanitizerOptions &Opts = EfficiencySanitizerOptions())
: ModulePass(ID), Options(OverrideOptionsFromCL(Opts)) {}
const char *getPassName() const override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnModule(Module &M) override;
static char ID;
@@ -199,13 +202,22 @@ private:
} // namespace
char EfficiencySanitizer::ID = 0;
-INITIALIZE_PASS(EfficiencySanitizer, "esan",
- "EfficiencySanitizer: finds performance issues.", false, false)
+INITIALIZE_PASS_BEGIN(
+ EfficiencySanitizer, "esan",
+ "EfficiencySanitizer: finds performance issues.", false, false)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(
+ EfficiencySanitizer, "esan",
+ "EfficiencySanitizer: finds performance issues.", false, false)
const char *EfficiencySanitizer::getPassName() const {
return "EfficiencySanitizer";
}
+void EfficiencySanitizer::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
+}
+
ModulePass *
llvm::createEfficiencySanitizerPass(const EfficiencySanitizerOptions &Options) {
return new EfficiencySanitizer(Options);
@@ -544,6 +556,8 @@ bool EfficiencySanitizer::runOnFunction(Function &F, Module &M) {
SmallVector<Instruction *, 8> GetElementPtrs;
bool Res = false;
const DataLayout &DL = M.getDataLayout();
+ const TargetLibraryInfo *TLI =
+ &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
for (auto &BB : F) {
for (auto &Inst : BB) {
@@ -555,6 +569,8 @@ bool EfficiencySanitizer::runOnFunction(Function &F, Module &M) {
MemIntrinCalls.push_back(&Inst);
else if (isa<GetElementPtrInst>(Inst))
GetElementPtrs.push_back(&Inst);
+ else if (CallInst *CI = dyn_cast<CallInst>(&Inst))
+ maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI);
}
}
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 618bfb15718..0a71bec279d 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -317,6 +317,9 @@ class MemorySanitizer : public FunctionPass {
TrackOrigins(std::max(TrackOrigins, (int)ClTrackOrigins)),
WarningFn(nullptr) {}
const char *getPassName() const override { return "MemorySanitizer"; }
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
+ }
bool runOnFunction(Function &F) override;
bool doInitialization(Module &M) override;
static char ID; // Pass identification, replacement for typeid.
@@ -384,9 +387,13 @@ class MemorySanitizer : public FunctionPass {
} // anonymous namespace
char MemorySanitizer::ID = 0;
-INITIALIZE_PASS(MemorySanitizer, "msan",
- "MemorySanitizer: detects uninitialized reads.",
- false, false)
+INITIALIZE_PASS_BEGIN(
+ MemorySanitizer, "msan",
+ "MemorySanitizer: detects uninitialized reads.", false, false)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(
+ MemorySanitizer, "msan",
+ "MemorySanitizer: detects uninitialized reads.", false, false)
FunctionPass *llvm::createMemorySanitizerPass(int TrackOrigins) {
return new MemorySanitizer(TrackOrigins);
@@ -618,6 +625,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
SmallVector<PHINode *, 16> ShadowPHINodes, OriginPHINodes;
ValueMap<Value*, Value*> ShadowMap, OriginMap;
std::unique_ptr<VarArgHelper> VAHelper;
+ const TargetLibraryInfo *TLI;
// The following flags disable parts of MSan instrumentation based on
// blacklist contents and command-line options.
@@ -647,6 +655,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// FIXME: Consider using SpecialCaseList to specify a list of functions that
// must always return fully initialized values. For now, we hardcode "main".
CheckReturnValue = SanitizeFunction && (F.getName() == "main");
+ TLI = &MS.getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
DEBUG(if (!InsertChecks)
dbgs() << "MemorySanitizer is not inserting checks into '"
@@ -2529,6 +2538,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
AttributeSet::FunctionIndex,
B));
}
+
+ maybeMarkSanitizerLibraryCallNoBuiltin(Call, TLI);
}
IRBuilder<> IRB(&I);
diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index 48bf1c3eeb8..eed77b701e3 100644
--- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -26,6 +26,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
@@ -42,6 +43,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
using namespace llvm;
@@ -82,6 +84,7 @@ namespace {
struct ThreadSanitizer : public FunctionPass {
ThreadSanitizer() : FunctionPass(ID) {}
const char *getPassName() const override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
bool doInitialization(Module &M) override;
static char ID; // Pass identification, replacement for typeid.
@@ -122,7 +125,13 @@ struct ThreadSanitizer : public FunctionPass {
} // namespace
char ThreadSanitizer::ID = 0;
-INITIALIZE_PASS(ThreadSanitizer, "tsan",
+INITIALIZE_PASS_BEGIN(
+ ThreadSanitizer, "tsan",
+ "ThreadSanitizer: detects data races.",
+ false, false)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(
+ ThreadSanitizer, "tsan",
"ThreadSanitizer: detects data races.",
false, false)
@@ -130,6 +139,10 @@ const char *ThreadSanitizer::getPassName() const {
return "ThreadSanitizer";
}
+void ThreadSanitizer::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
+}
+
FunctionPass *llvm::createThreadSanitizerPass() {
return new ThreadSanitizer();
}
@@ -368,6 +381,8 @@ bool ThreadSanitizer::runOnFunction(Function &F) {
bool HasCalls = false;
bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread);
const DataLayout &DL = F.getParent()->getDataLayout();
+ const TargetLibraryInfo *TLI =
+ &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
// Traverse all instructions, collect loads/stores/returns, check for calls.
for (auto &BB : F) {
@@ -379,6 +394,8 @@ bool ThreadSanitizer::runOnFunction(Function &F) {
else if (isa<ReturnInst>(Inst))
RetVec.push_back(&Inst);
else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
+ if (CallInst *CI = dyn_cast<CallInst>(&Inst))
+ maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI);
if (isa<MemIntrinsic>(Inst))
MemIntrinCalls.push_back(&Inst);
HasCalls = true;
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index a0dd5d1a434..4f8935dd971 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1942,3 +1942,29 @@ bool llvm::recognizeBSwapOrBitReverseIdiom(
InsertedInsts.push_back(CallInst::Create(F, Res->Provider, "rev", I));
return true;
}
+
+// CodeGen has special handling for some string functions that may replace
+// them with target-specific intrinsics. Since that'd skip our interceptors
+// in ASan/MSan/TSan/DFSan, and thus make us miss some memory accesses,
+// we mark affected calls as NoBuiltin, which will disable optimization
+// in CodeGen.
+void llvm::maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI,
+ const TargetLibraryInfo *TLI) {
+ Function *F = CI->getCalledFunction();
+ LibFunc::Func Func;
+ if (!F || F->hasLocalLinkage() || !F->hasName() ||
+ !TLI->getLibFunc(F->getName(), Func))
+ return;
+ switch (Func) {
+ default: break;
+ case LibFunc::memcmp:
+ case LibFunc::memchr:
+ case LibFunc::strcpy:
+ case LibFunc::stpcpy:
+ case LibFunc::strcmp:
+ case LibFunc::strlen:
+ case LibFunc::strnlen:
+ CI->addAttribute(AttributeSet::FunctionIndex, Attribute::NoBuiltin);
+ break;
+ }
+}
OpenPOWER on IntegriCloud