From 610469f4c27b8813e82a13db147b99de27a66312 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 18 Mar 2014 13:30:56 +0000 Subject: [PATCH] [msan] Origin tracking with history. LLVM part of MSan implementation of advanced origin tracking, when we record not only creation point, but all locations where an uninitialized value was stored to memory, too. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204151 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Transforms/Instrumentation.h | 2 +- .../Instrumentation/MemorySanitizer.cpp | 30 ++++++++++------ .../MemorySanitizer/store-origin.ll | 34 +++++++++++++++++++ 3 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 test/Instrumentation/MemorySanitizer/store-origin.ll diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 47bdb4246fa..b527546e058 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -71,7 +71,7 @@ ModulePass *createAddressSanitizerModulePass( bool CheckInitOrder = true, StringRef BlacklistFile = StringRef()); // Insert MemorySanitizer instrumentation (detection of uninitialized reads) -FunctionPass *createMemorySanitizerPass(bool TrackOrigins = false, +FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0, StringRef BlacklistFile = StringRef()); // Insert ThreadSanitizer (race detection) instrumentation diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 99114d1414f..c07892229df 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -133,9 +133,9 @@ static const unsigned kShadowTLSAlignment = 8; /// /// Adds a section to MemorySanitizer report that points to the allocation /// (stack or heap) the uninitialized bits came from originally. -static cl::opt ClTrackOrigins("msan-track-origins", +static cl::opt ClTrackOrigins("msan-track-origins", cl::desc("Track origins (allocation sites) of poisoned memory"), - cl::Hidden, cl::init(false)); + cl::Hidden, cl::init(0)); static cl::opt ClKeepGoing("msan-keep-going", cl::desc("keep going after reporting a UMR"), cl::Hidden, cl::init(false)); @@ -199,10 +199,10 @@ namespace { /// uninitialized reads. class MemorySanitizer : public FunctionPass { public: - MemorySanitizer(bool TrackOrigins = false, + MemorySanitizer(int TrackOrigins = 0, StringRef BlacklistFile = StringRef()) : FunctionPass(ID), - TrackOrigins(TrackOrigins || ClTrackOrigins), + TrackOrigins(std::max(TrackOrigins, (int)ClTrackOrigins)), DL(0), WarningFn(0), BlacklistFile(BlacklistFile.empty() ? ClBlacklistFile : BlacklistFile), @@ -216,7 +216,7 @@ class MemorySanitizer : public FunctionPass { void initializeCallbacks(Module &M); /// \brief Track origins (allocation points) of uninitialized values. - bool TrackOrigins; + int TrackOrigins; const DataLayout *DL; LLVMContext *C; @@ -250,6 +250,9 @@ class MemorySanitizer : public FunctionPass { Value *MsanSetAllocaOrigin4Fn; /// \brief Run-time helper that poisons stack on function entry. Value *MsanPoisonStackFn; + /// \brief Run-time helper that records a store (or any event) of an + /// uninitialized value and returns an updated origin id encoding this info. + Value *MsanChainOriginFn; /// \brief MSan runtime replacements for memmove, memcpy and memset. Value *MemmoveFn, *MemcpyFn, *MemsetFn; @@ -286,7 +289,7 @@ INITIALIZE_PASS(MemorySanitizer, "msan", "MemorySanitizer: detects uninitialized reads.", false, false) -FunctionPass *llvm::createMemorySanitizerPass(bool TrackOrigins, +FunctionPass *llvm::createMemorySanitizerPass(int TrackOrigins, StringRef BlacklistFile) { return new MemorySanitizer(TrackOrigins, BlacklistFile); } @@ -323,6 +326,8 @@ void MemorySanitizer::initializeCallbacks(Module &M) { IRB.getInt8PtrTy(), IntptrTy, NULL); MsanPoisonStackFn = M.getOrInsertFunction( "__msan_poison_stack", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, NULL); + MsanChainOriginFn = M.getOrInsertFunction( + "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty(), NULL); MemmoveFn = M.getOrInsertFunction( "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy, NULL); @@ -520,6 +525,11 @@ struct MemorySanitizerVisitor : public InstVisitor { << F.getName() << "'\n"); } + Value *updateOrigin(Value *V, IRBuilder<> &IRB) { + if (MS.TrackOrigins <= 1) return V; + return IRB.CreateCall(MS.MsanChainOriginFn, V); + } + void materializeStores() { for (size_t i = 0, n = StoreList.size(); i < n; i++) { StoreInst& I = *dyn_cast(StoreList[i]); @@ -544,8 +554,8 @@ struct MemorySanitizerVisitor : public InstVisitor { if (MS.TrackOrigins) { unsigned Alignment = std::max(kMinOriginAlignment, I.getAlignment()); if (isa(Shadow->getType())) { - IRB.CreateAlignedStore(getOrigin(Val), getOriginPtr(Addr, IRB), - Alignment); + IRB.CreateAlignedStore(updateOrigin(getOrigin(Val), IRB), + getOriginPtr(Addr, IRB), Alignment); } else { Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB); @@ -560,8 +570,8 @@ struct MemorySanitizerVisitor : public InstVisitor { Instruction *CheckTerm = SplitBlockAndInsertIfThen(Cmp, &I, false, MS.OriginStoreWeights); IRBuilder<> IRBNew(CheckTerm); - IRBNew.CreateAlignedStore(getOrigin(Val), getOriginPtr(Addr, IRBNew), - Alignment); + IRBNew.CreateAlignedStore(updateOrigin(getOrigin(Val), IRBNew), + getOriginPtr(Addr, IRBNew), Alignment); } } } diff --git a/test/Instrumentation/MemorySanitizer/store-origin.ll b/test/Instrumentation/MemorySanitizer/store-origin.ll new file mode 100644 index 00000000000..75e531969da --- /dev/null +++ b/test/Instrumentation/MemorySanitizer/store-origin.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck -check-prefix=CHECK -check-prefix=CHECK-ORIGINS1 %s +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck -check-prefix=CHECK -check-prefix=CHECK-ORIGINS2 %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + + +; Check origin instrumentation of stores + +define void @Store(i32* nocapture %p, i32 %x) nounwind uwtable sanitize_memory { +entry: + store i32 %x, i32* %p, align 4 + ret void +} + +; CHECK: @Store +; CHECK: load {{.*}} @__msan_param_tls +; CHECK: [[ORIGIN:%[01-9a-z]+]] = load {{.*}} @__msan_param_origin_tls +; CHECK: store +; CHECK: icmp +; CHECK: br i1 +; CHECK: