diff options
author | Marcin Koscielnicki <koriakin@0x04.net> | 2016-06-18 10:10:37 +0000 |
---|---|---|
committer | Marcin Koscielnicki <koriakin@0x04.net> | 2016-06-18 10:10:37 +0000 |
commit | 3feda222c6fb290718ee23f585b6e07afb6559cb (patch) | |
tree | 6988a77a67614fd03986c589c000b5aeea41357e /llvm/lib | |
parent | 7cb30664fcc510c484224677c641187b8996cd00 (diff) | |
download | bcm5719-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')
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; + } +} |