mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
[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
This commit is contained in:
parent
be3f051c49
commit
52eb699220
@ -27,11 +27,14 @@
|
|||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/Intrinsics.h"
|
#include "llvm/Intrinsics.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
|
#include "llvm/LLVMContext.h"
|
||||||
|
#include "llvm/Metadata.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/IRBuilder.h"
|
#include "llvm/Support/IRBuilder.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Transforms/Instrumentation.h"
|
#include "llvm/Transforms/Instrumentation.h"
|
||||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||||
@ -61,6 +64,7 @@ struct ThreadSanitizer : public FunctionPass {
|
|||||||
static const size_t kNumberOfAccessSizes = 5;
|
static const size_t kNumberOfAccessSizes = 5;
|
||||||
Value *TsanRead[kNumberOfAccessSizes];
|
Value *TsanRead[kNumberOfAccessSizes];
|
||||||
Value *TsanWrite[kNumberOfAccessSizes];
|
Value *TsanWrite[kNumberOfAccessSizes];
|
||||||
|
Value *TsanVptrUpdate;
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -105,6 +109,9 @@ bool ThreadSanitizer::doInitialization(Module &M) {
|
|||||||
TsanWrite[i] = M.getOrInsertFunction(WriteName, IRB.getVoidTy(),
|
TsanWrite[i] = M.getOrInsertFunction(WriteName, IRB.getVoidTy(),
|
||||||
IRB.getInt8PtrTy(), NULL);
|
IRB.getInt8PtrTy(), NULL);
|
||||||
}
|
}
|
||||||
|
TsanVptrUpdate = M.getOrInsertFunction("__tsan_vptr_update", IRB.getVoidTy(),
|
||||||
|
IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
|
||||||
|
NULL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,10 +158,21 @@ bool ThreadSanitizer::runOnFunction(Function &F) {
|
|||||||
IRBuilder<> IRBRet(RetVec[i]);
|
IRBuilder<> IRBRet(RetVec[i]);
|
||||||
IRBRet.CreateCall(TsanFuncExit);
|
IRBRet.CreateCall(TsanFuncExit);
|
||||||
}
|
}
|
||||||
|
Res = true;
|
||||||
}
|
}
|
||||||
return Res;
|
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) {
|
bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
|
||||||
IRBuilder<> IRB(I);
|
IRBuilder<> IRB(I);
|
||||||
bool IsWrite = isa<StoreInst>(*I);
|
bool IsWrite = isa<StoreInst>(*I);
|
||||||
@ -170,6 +188,13 @@ bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
|
|||||||
// Ignore all unusual sizes.
|
// Ignore all unusual sizes.
|
||||||
return false;
|
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);
|
size_t Idx = CountTrailingZeros_32(TypeSize / 8);
|
||||||
assert(Idx < kNumberOfAccessSizes);
|
assert(Idx < kNumberOfAccessSizes);
|
||||||
Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
|
Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
|
||||||
|
1
test/Instrumentation/ThreadSanitizer/lit.local.cfg
Normal file
1
test/Instrumentation/ThreadSanitizer/lit.local.cfg
Normal file
@ -0,0 +1 @@
|
|||||||
|
config.suffixes = ['.ll', '.c', '.cpp']
|
13
test/Instrumentation/ThreadSanitizer/vptr_update.ll
Normal file
13
test/Instrumentation/ThreadSanitizer/vptr_update.ll
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
; RUN: opt < %s -tsan -S | FileCheck %s
|
||||||
|
; Check that vtable pointer updates are treated in a special way.
|
||||||
|
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"
|
||||||
|
|
||||||
|
define void @Foo(i8** nocapture %a, i8* %b) nounwind uwtable {
|
||||||
|
entry:
|
||||||
|
; CHECK: call void @__tsan_vptr_update
|
||||||
|
store i8* %b, i8** %a, align 8, !tbaa !0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
!0 = metadata !{metadata !"vtable pointer", metadata !1}
|
||||||
|
!1 = metadata !{metadata !"Simple C/C++ TBAA", null}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user