[compiler-rt] [llvm] [ASan][compiler-rt] Implemented Dormant Mode in ASan (PR #99857)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 22 03:15:49 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: None (gbMattN)
<details>
<summary>Changes</summary>
Added the ability to skip runtime checks with ASan, while maintaining shadow memory coherency. You can then dynamically re-enable the checks.
There is a discussion on discourse: https://discourse.llvm.org/t/rfc-adding-a-dormant-mode-to-addresssanitizer/80278
---
Full diff: https://github.com/llvm/llvm-project/pull/99857.diff
5 Files Affected:
- (modified) compiler-rt/include/sanitizer/asan_interface.h (+7)
- (modified) compiler-rt/lib/asan/asan_interface.inc (+1)
- (modified) compiler-rt/lib/asan/asan_interface_internal.h (+6)
- (modified) compiler-rt/lib/asan/asan_rtl.cpp (+3)
- (modified) llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp (+43-5)
``````````diff
diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 37b6d08f4db19..f6ca4acb03e9d 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -269,6 +269,13 @@ void SANITIZER_CDECL __asan_set_death_callback(void (*callback)(void));
void SANITIZER_CDECL
__asan_set_error_report_callback(void (*callback)(const char *));
+/// Sets whether ASan should be dormant or not. If 0 is passed, ASan resumes
+/// checking memory accesses for errors. If a non-0 value is passed, these
+/// checks will be skipped.
+///
+/// \param dormancy A boolean to control if ASan is dormant or not.
+void SANITIZER_CDECL __asan_set_dormant(int dormancy);
+
/// User-provided callback on ASan errors.
///
/// You can provide a function that would be called immediately when ASan
diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc
index bfc44b4619623..499014fcc4a49 100644
--- a/compiler-rt/lib/asan/asan_interface.inc
+++ b/compiler-rt/lib/asan/asan_interface.inc
@@ -107,6 +107,7 @@ INTERFACE_FUNCTION(__asan_report_store16_noabort)
INTERFACE_FUNCTION(__asan_report_store_n_noabort)
INTERFACE_FUNCTION(__asan_set_death_callback)
INTERFACE_FUNCTION(__asan_set_error_report_callback)
+INTERFACE_FUNCTION(__asan_set_dormant)
INTERFACE_FUNCTION(__asan_set_shadow_00)
INTERFACE_FUNCTION(__asan_set_shadow_01)
INTERFACE_FUNCTION(__asan_set_shadow_02)
diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h
index a998263780221..9b2752ce7e05b 100644
--- a/compiler-rt/lib/asan/asan_interface_internal.h
+++ b/compiler-rt/lib/asan/asan_interface_internal.h
@@ -184,6 +184,9 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void __asan_set_error_report_callback(void (*callback)(const char*));
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_dormant(int dormancy);
+
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
void __asan_on_error();
@@ -202,6 +205,9 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
extern uptr *__asan_test_only_reported_buggy_pointer;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern bool __asan_is_dormant;
+
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1(uptr p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2(uptr p);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4(uptr p);
diff --git a/compiler-rt/lib/asan/asan_rtl.cpp b/compiler-rt/lib/asan/asan_rtl.cpp
index c484e086a5ef7..56da1180cfc28 100644
--- a/compiler-rt/lib/asan/asan_rtl.cpp
+++ b/compiler-rt/lib/asan/asan_rtl.cpp
@@ -36,6 +36,9 @@
uptr __asan_shadow_memory_dynamic_address; // Global interface symbol.
int __asan_option_detect_stack_use_after_return; // Global interface symbol.
uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
+bool __asan_is_dormant = true;
+
+void __asan_set_dormant(int dormancy) { __asan_is_dormant = dormancy; }
namespace __asan {
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index adf77f20cb1c7..774820ae68924 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -178,6 +178,8 @@ const char kAMDGPUAddressPrivateName[] = "llvm.amdgcn.is.private";
const char kAMDGPUBallotName[] = "llvm.amdgcn.ballot.i64";
const char kAMDGPUUnreachableName[] = "llvm.amdgcn.unreachable";
+const char kAsanDormancyVarName[] = "__asan_is_dormant";
+
// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
static const size_t kNumberOfAccessSizes = 5;
@@ -452,6 +454,10 @@ static cl::opt<int> ClDebugMin("asan-debug-min", cl::desc("Debug min inst"),
static cl::opt<int> ClDebugMax("asan-debug-max", cl::desc("Debug max inst"),
cl::Hidden, cl::init(-1));
+static cl::opt<bool> CLAsanDormant("asan-dormant",
+ cl::desc("Makes asan dormant"), cl::Hidden,
+ cl::init(false));
+
STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
STATISTIC(NumOptimizedAccessesToGlobalVar,
@@ -852,6 +858,7 @@ struct AddressSanitizer {
FunctionCallee AsanMemmove, AsanMemcpy, AsanMemset;
Value *LocalDynamicShadow = nullptr;
+ Constant *DormantAsanFlag;
const StackSafetyGlobalInfo *SSGI;
DenseMap<const AllocaInst *, bool> ProcessedAllocas;
@@ -1579,6 +1586,12 @@ bool AddressSanitizer::GlobalIsLinkerInitialized(GlobalVariable *G) {
void AddressSanitizer::instrumentPointerComparisonOrSubtraction(
Instruction *I, RuntimeCallInserter &RTCI) {
IRBuilder<> IRB(I);
+
+ if (CLAsanDormant)
+ IRB.SetInsertPoint(SplitBlockAndInsertIfThen(
+ IRB.CreateNot(IRB.CreateLoad(IRB.getInt1Ty(), DormantAsanFlag)), I,
+ false));
+
FunctionCallee F = isa<ICmpInst>(I) ? AsanPtrCmpFunction : AsanPtrSubFunction;
Value *Param[2] = {I->getOperand(0), I->getOperand(1)};
for (Value *&i : Param) {
@@ -1593,9 +1606,19 @@ static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
MaybeAlign Alignment, unsigned Granularity,
TypeSize TypeStoreSize, bool IsWrite,
Value *SizeArgument, bool UseCalls,
- uint32_t Exp, RuntimeCallInserter &RTCI) {
+ uint32_t Exp, RuntimeCallInserter &RTCI,
+ Value *DormantAsanFlag) {
// Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check
// if the data is properly aligned.
+
+ Instruction *InsertPoint = InsertBefore;
+ if (CLAsanDormant) {
+ InstrumentationIRBuilder IRB(InsertPoint);
+ InsertPoint = SplitBlockAndInsertIfThen(
+ IRB.CreateNot(IRB.CreateLoad(IRB.getInt1Ty(), DormantAsanFlag)),
+ InsertBefore, false);
+ }
+
if (!TypeStoreSize.isScalable()) {
const auto FixedSize = TypeStoreSize.getFixedValue();
switch (FixedSize) {
@@ -1606,12 +1629,12 @@ static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
case 128:
if (!Alignment || *Alignment >= Granularity ||
*Alignment >= FixedSize / 8)
- return Pass->instrumentAddress(I, InsertBefore, Addr, Alignment,
+ return Pass->instrumentAddress(I, InsertPoint, Addr, Alignment,
FixedSize, IsWrite, nullptr, UseCalls,
Exp, RTCI);
}
}
- Pass->instrumentUnusualSizeOrAlignment(I, InsertBefore, Addr, TypeStoreSize,
+ Pass->instrumentUnusualSizeOrAlignment(I, InsertPoint, Addr, TypeStoreSize,
IsWrite, nullptr, UseCalls, Exp, RTCI);
}
@@ -1627,6 +1650,14 @@ void AddressSanitizer::instrumentMaskedLoadOrStore(
IRBuilder IB(I);
Instruction *LoopInsertBefore = I;
+
+ if (CLAsanDormant) {
+ LoopInsertBefore = SplitBlockAndInsertIfThen(
+ IB.CreateNot(IB.CreateLoad(IB.getInt1Ty(), DormantAsanFlag)),
+ LoopInsertBefore, false);
+ IB.SetInsertPoint(LoopInsertBefore);
+ }
+
if (EVL) {
// The end argument of SplitBlockAndInsertForLane is assumed bigger
// than zero, so we should check whether EVL is zero here.
@@ -1677,7 +1708,7 @@ void AddressSanitizer::instrumentMaskedLoadOrStore(
}
doInstrumentAddress(Pass, I, &*IRB.GetInsertPoint(), InstrumentedAddress,
Alignment, Granularity, ElemTypeSize, IsWrite,
- SizeArgument, UseCalls, Exp, RTCI);
+ SizeArgument, UseCalls, Exp, RTCI, DormantAsanFlag);
});
}
@@ -1734,7 +1765,7 @@ void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
} else {
doInstrumentAddress(this, O.getInsn(), O.getInsn(), Addr, O.Alignment,
Granularity, O.TypeStoreSize, O.IsWrite, nullptr,
- UseCalls, Exp, RTCI);
+ UseCalls, Exp, RTCI, DormantAsanFlag);
}
}
@@ -1846,6 +1877,11 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
}
InstrumentationIRBuilder IRB(InsertBefore);
+ if (CLAsanDormant)
+ IRB.SetInsertPoint(SplitBlockAndInsertIfThen(
+ IRB.CreateNot(IRB.CreateLoad(IRB.getInt1Ty(), DormantAsanFlag)),
+ InsertBefore, false));
+
size_t AccessSizeIndex = TypeStoreSizeToSizeIndex(TypeStoreSize);
const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex);
@@ -2856,6 +2892,8 @@ void AddressSanitizer::initializeCallbacks(Module &M, const TargetLibraryInfo *T
M.getOrInsertFunction(kAMDGPUAddressSharedName, IRB.getInt1Ty(), PtrTy);
AMDGPUAddressPrivate =
M.getOrInsertFunction(kAMDGPUAddressPrivateName, IRB.getInt1Ty(), PtrTy);
+
+ DormantAsanFlag = M.getOrInsertGlobal(kAsanDormancyVarName, IRB.getInt1Ty());
}
bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/99857
More information about the llvm-commits
mailing list