Skip to content

Commit ef66b29

Browse files
committed
Add __tsan_enable/__tsan_disalbe intrinsics
1 parent d76f5b0 commit ef66b29

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed

compiler-rt/include/sanitizer/tsan_interface.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,12 @@ int SANITIZER_CDECL __tsan_get_report_unique_tid(void *report,
309309
/// \returns An opaque pointer to the current report. Otherwise returns NULL.
310310
void *SANITIZER_CDECL __tsan_get_current_report();
311311

312+
/////////////////////////////////////////////////////////////////////////////
313+
// This code is for disabling/enabling instrumentation
314+
// for specific code section
315+
void SANITIZER_CDECL __tsan_enable();
316+
void SANITIZER_CDECL __tsan_disable();
317+
312318
#ifdef __cplusplus
313319
} // extern "C"
314320
#endif

compiler-rt/lib/tsan/rtl/tsan_interface.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,10 @@ SANITIZER_INTERFACE_ATTRIBUTE
437437
void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
438438
u8 *a);
439439

440+
// Functions for disabling/enabling instrumentation
441+
// for specific code section
442+
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_disable();
443+
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_enable();
440444
} // extern "C"
441445

442446
} // namespace __tsan

compiler-rt/lib/tsan/rtl/tsan_interface.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,9 @@ void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
188188
void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
189189
MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true);
190190
}
191+
192+
///////////////////////////////////////////////////////////////////////////////
193+
// This is for disabling/enabling TSan instrumentation
194+
int GV;
195+
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_disable() { GV++; };
196+
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_enable() { GV++; };

llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ struct ThreadSanitizer {
211211
FunctionCallee TsanVptrUpdate;
212212
FunctionCallee TsanVptrLoad;
213213
FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
214+
215+
// Instrinsics for disabling/enabling instrumentation
216+
// for specific code section
217+
FunctionCallee TsanDisableFn, TsanEnableFn;
214218
};
215219

216220
void insertModuleCtor(Module &M) {
@@ -414,6 +418,12 @@ void ThreadSanitizer::initialize(Module &M, const TargetLibraryInfo &TLI) {
414418
"__tsan_memset",
415419
TLI.getAttrList(&Ctx, {1}, /*Signed=*/true, /*Ret=*/false, Attr),
416420
IRB.getPtrTy(), IRB.getPtrTy(), IRB.getInt32Ty(), IntptrTy);
421+
422+
/////////////////////////////////////////////////////////////////////////////
423+
// This code is for disabling/enabling instrumentation
424+
// for specific code section
425+
TsanEnableFn = M.getOrInsertFunction("__tsan_enable", Attr, IRB.getVoidTy());
426+
TsanDisableFn = M.getOrInsertFunction("__tsan_disable", Attr, IRB.getVoidTy());
417427
}
418428

419429
static bool isVtableAccess(Instruction *I) {
@@ -649,11 +659,42 @@ bool ThreadSanitizer::sanitizeFunction(
649659
bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread);
650660
const DataLayout &DL = F.getParent()->getDataLayout();
651661

662+
///////////////////////////////////////////////////////////////////////////////
663+
// List of instructions (function calls) to delete
664+
SmallVector<CallInst*, 8> EnableDisableFuncToDelete;
665+
666+
// Counter for considering nesting __tsan_disable/__tsan_enable
667+
int disableEnableNesting = 0;
668+
652669
// Traverse all instructions, collect loads/stores/returns, check for calls.
653670
for (auto &BB : F) {
654671
LLVM_DEBUG(dbgs() << "\nInstrumenting BB: " << BB.getName() << "\n");
655672
for (auto &Inst : BB) {
656673
LLVM_DEBUG(dbgs() << "Instrumenting I: " << Inst << "\n");
674+
///////////////////////////////////////////////////////////////////////////////
675+
// This code is for disabling/enabling instrumentation
676+
// for specific code section
677+
//
678+
// Check whether we encountered TSan disable/enable intrinsics
679+
if (auto *CI = dyn_cast<CallInst>(&Inst)) {
680+
Function *CalledFunc = CI->getCalledFunction();
681+
if (CalledFunc) {
682+
// errs() << "CalledFunc: " << CalledFunc->getName() << "\n";
683+
if (CalledFunc->getName() == "__tsan_disable") {
684+
disableEnableNesting++;
685+
EnableDisableFuncToDelete.push_back(CI);
686+
continue;
687+
} else if (CalledFunc->getName() == "__tsan_enable") {
688+
disableEnableNesting--;
689+
EnableDisableFuncToDelete.push_back(CI);
690+
continue;
691+
}
692+
}
693+
}
694+
695+
if (disableEnableNesting > 0)
696+
continue;
697+
///////////////////////////////////////////////////////////////////////////////
657698

658699
// Skip instructions inserted by another instrumentation.
659700
if (Inst.hasMetadata(LLVMContext::MD_nosanitize))
@@ -688,6 +729,22 @@ bool ThreadSanitizer::sanitizeFunction(
688729
EAI, EAIGlobal);
689730
}
690731

732+
//////////////////////////////////////////////////////////////////////////////
733+
// This is for disabling/enabling TSan instrumentation
734+
// Disable for now check of matching
735+
/*
736+
if (disableEnableNesting != 0) {
737+
// Error: __tsan_enable without __tsan_disable
738+
report_fatal_error("Unmatched __tsan_enable__ call in function " +
739+
F.getName());
740+
}
741+
*/
742+
743+
// Erase all __tsan_disable/enable functions
744+
for (auto *CI: EnableDisableFuncToDelete)
745+
CI->eraseFromParent();
746+
//////////////////////////////////////////////////////////////////////////////
747+
691748
// We have collected all loads and stores.
692749
// FIXME: many of these accesses do not need to be checked for races
693750
// (e.g. variables that do not escape, etc).

0 commit comments

Comments
 (0)