tsan: handle vptr loads specially

This is required to determine ctor/dtor vs virtual call races.
http://llvm-reviews.chandlerc.com/D566



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177717 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dmitry Vyukov 2013-03-22 08:51:22 +00:00
parent 7541cd36fd
commit ab78ac1a2d
2 changed files with 23 additions and 0 deletions

View File

@ -63,6 +63,7 @@ STATISTIC(NumOmittedReadsBeforeWrite,
"Number of reads ignored due to following writes"); "Number of reads ignored due to following writes");
STATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size"); STATISTIC(NumAccessesWithBadSize, "Number of accesses with bad size");
STATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes"); STATISTIC(NumInstrumentedVtableWrites, "Number of vtable ptr writes");
STATISTIC(NumInstrumentedVtableReads, "Number of vtable ptr reads");
STATISTIC(NumOmittedReadsFromConstantGlobals, STATISTIC(NumOmittedReadsFromConstantGlobals,
"Number of reads from constant globals"); "Number of reads from constant globals");
STATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads"); STATISTIC(NumOmittedReadsFromVtable, "Number of vtable reads");
@ -108,6 +109,7 @@ struct ThreadSanitizer : public FunctionPass {
Function *TsanAtomicThreadFence; Function *TsanAtomicThreadFence;
Function *TsanAtomicSignalFence; Function *TsanAtomicSignalFence;
Function *TsanVptrUpdate; Function *TsanVptrUpdate;
Function *TsanVptrLoad;
}; };
} // namespace } // namespace
@ -196,6 +198,8 @@ void ThreadSanitizer::initializeCallbacks(Module &M) {
TsanVptrUpdate = checkInterfaceFunction(M.getOrInsertFunction( TsanVptrUpdate = checkInterfaceFunction(M.getOrInsertFunction(
"__tsan_vptr_update", IRB.getVoidTy(), IRB.getInt8PtrTy(), "__tsan_vptr_update", IRB.getVoidTy(), IRB.getInt8PtrTy(),
IRB.getInt8PtrTy(), NULL)); IRB.getInt8PtrTy(), NULL));
TsanVptrLoad = checkInterfaceFunction(M.getOrInsertFunction(
"__tsan_vptr_read", IRB.getVoidTy(), IRB.getInt8PtrTy(), NULL));
TsanAtomicThreadFence = checkInterfaceFunction(M.getOrInsertFunction( TsanAtomicThreadFence = checkInterfaceFunction(M.getOrInsertFunction(
"__tsan_atomic_thread_fence", IRB.getVoidTy(), OrdTy, NULL)); "__tsan_atomic_thread_fence", IRB.getVoidTy(), OrdTy, NULL));
TsanAtomicSignalFence = checkInterfaceFunction(M.getOrInsertFunction( TsanAtomicSignalFence = checkInterfaceFunction(M.getOrInsertFunction(
@ -386,6 +390,12 @@ bool ThreadSanitizer::instrumentLoadOrStore(Instruction *I) {
NumInstrumentedVtableWrites++; NumInstrumentedVtableWrites++;
return true; return true;
} }
if (!IsWrite && isVtableAccess(I)) {
IRB.CreateCall(TsanVptrLoad,
IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
NumInstrumentedVtableReads++;
return true;
}
Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx]; Value *OnAccessFunc = IsWrite ? TsanWrite[Idx] : TsanRead[Idx];
IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy())); IRB.CreateCall(OnAccessFunc, IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()));
if (IsWrite) NumInstrumentedWrites++; if (IsWrite) NumInstrumentedWrites++;

View File

@ -0,0 +1,13 @@
; RUN: opt < %s -tsan -S | FileCheck %s
; Check that vptr reads 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 i8 @Foo(i8* %a) nounwind uwtable {
entry:
; CHECK: call void @__tsan_vptr_read
%0 = load i8* %a, align 8, !tbaa !0
ret i8 %0
}
!0 = metadata !{metadata !"vtable pointer", metadata !1}
!1 = metadata !{metadata !"Simple C/C++ TBAA", null}