aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2012-03-26 17:35:03 +0000
committerKostya Serebryany <kcc@google.com>2012-03-26 17:35:03 +0000
commit52eb699220aa00696b5c4a1a67141a8bcc8a4e68 (patch)
tree2d09229fd220e94e71c7f4a07e752fff19c474ef /lib
parentbe3f051c49699a86d526833d7dbe95645680a340 (diff)
downloadexternal_llvm-52eb699220aa00696b5c4a1a67141a8bcc8a4e68.zip
external_llvm-52eb699220aa00696b5c4a1a67141a8bcc8a4e68.tar.gz
external_llvm-52eb699220aa00696b5c4a1a67141a8bcc8a4e68.tar.bz2
[tsan] treat vtable pointer updates in a special way (requires tbaa); fix a bug (forgot to return true after instrumenting); make sure the tsan tests are run
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153448 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/Instrumentation/ThreadSanitizer.cpp25
1 files changed, 25 insertions, 0 deletions
diff --git a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index 85fda30..b774211 100644
--- a/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -27,11 +27,14 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Intrinsics.h"
#include "llvm/Function.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Metadata.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
@@ -61,6 +64,7 @@ struct ThreadSanitizer : public FunctionPass {
static const size_t kNumberOfAccessSizes = 5;
Value *TsanRead[kNumberOfAccessSizes];
Value *TsanWrite[kNumberOfAccessSizes];
+ Value *TsanVptrUpdate;
};
} // namespace
@@ -105,6 +109,9 @@ bool ThreadSanitizer::doInitialization(Module &M) {
TsanWrite[i] = M.getOrInsertFunction(WriteName, IRB.getVoidTy(),
IRB.getInt8PtrTy(), NULL);
}
+ TsanVptrUpdate = M.getOrInsertFunction("__tsan_vptr_update", IRB.getVoidTy(),
+ IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
+ NULL);
return true;
}
@@ -151,10 +158,21 @@ bool ThreadSanitizer::runOnFunction(Function &F) {
IRBuilder<> IRBRet(RetVec[i]);
IRBRet.CreateCall(TsanFuncExit);
}
+ Res = true;
}
return Res;
}
+static bool isVtableAccess(Instruction *I) {
+ if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa)) {
+ if (Tag->getNumOperands() < 1) return false;
+ if (MDString *Tag1 = dyn_cast<MDString>(Tag->getOperand(0))) {
+ if (Tag1->getString() == "vtable pointer") return true;
+ }
+ }
+ return false;
+}
+
bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
IRBuilder<> IRB(I);
bool IsWrite = isa<StoreInst>(*I);
@@ -170,6 +188,13 @@ bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
// Ignore all unusual sizes.
return false;
}
+ if (IsWrite && isVtableAccess(I)) {
+ Value *StoredValue = cast<StoreInst>(I)->getValueOperand();
+ IRB.CreateCall2(TsanVptrUpdate,
+ IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
+ IRB.CreatePointerCast(StoredValue, IRB.getInt8PtrTy()));
+ return true;
+ }
size_t Idx = CountTrailingZeros_32(TypeSize / 8);
assert(Idx < kNumberOfAccessSizes);
Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];