[llvm] 09391e7 - [hwasan] Do not instrument accesses to uninteresting allocas.

Florian Mayer via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 10 11:28:46 PDT 2021


Author: Florian Mayer
Date: 2021-09-10T19:28:28+01:00
New Revision: 09391e7e507f88b0873c34af621fc937c5f341fd

URL: https://github.com/llvm/llvm-project/commit/09391e7e507f88b0873c34af621fc937c5f341fd
DIFF: https://github.com/llvm/llvm-project/commit/09391e7e507f88b0873c34af621fc937c5f341fd.diff

LOG: [hwasan] Do not instrument accesses to uninteresting allocas.

This leads to a statistically significant improvement when using -hwasan-instrument-stack=0: https://bit.ly/3AZUIKI.
When enabling stack instrumentation, the data appears gets better but not statistically significantly so. This is consistent
with the very moderate improvements I have seen for stack safety otherwise, so I expect it to improve when the underlying
issue of that is resolved.

Reviewed By: eugenis

Differential Revision: https://reviews.llvm.org/D108457

Added: 
    

Modified: 
    llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
    llvm/test/Instrumentation/HWAddressSanitizer/memaccess-clobber.ll
    llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index e51bc2a7f015e..f1a7049784d01 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -287,7 +287,7 @@ class HWAddressSanitizer {
                                  Instruction *InsertBefore);
   void instrumentMemIntrinsic(MemIntrinsic *MI);
   bool instrumentMemAccess(InterestingMemoryOperand &O);
-  bool ignoreAccess(Value *Ptr);
+  bool ignoreAccess(Instruction *Inst, Value *Ptr);
   void getInterestingMemoryOperands(
       Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting);
 
@@ -768,7 +768,7 @@ Value *HWAddressSanitizer::getShadowNonTls(IRBuilder<> &IRB) {
   }
 }
 
-bool HWAddressSanitizer::ignoreAccess(Value *Ptr) {
+bool HWAddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) {
   // Do not instrument acesses from 
diff erent address spaces; we cannot deal
   // with them.
   Type *PtrTy = cast<PointerType>(Ptr->getType()->getScalarType());
@@ -782,6 +782,12 @@ bool HWAddressSanitizer::ignoreAccess(Value *Ptr) {
   if (Ptr->isSwiftError())
     return true;
 
+  if (!InstrumentStack) {
+    if (findAllocaForValue(Ptr))
+      return true;
+  } else if (SSI && SSI->accessIsSafe(*Inst)) {
+    return true;
+  }
   return false;
 }
 
@@ -796,29 +802,29 @@ void HWAddressSanitizer::getInterestingMemoryOperands(
     return;
 
   if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
-    if (!ClInstrumentReads || ignoreAccess(LI->getPointerOperand()))
+    if (!ClInstrumentReads || ignoreAccess(I, LI->getPointerOperand()))
       return;
     Interesting.emplace_back(I, LI->getPointerOperandIndex(), false,
                              LI->getType(), LI->getAlign());
   } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
-    if (!ClInstrumentWrites || ignoreAccess(SI->getPointerOperand()))
+    if (!ClInstrumentWrites || ignoreAccess(I, SI->getPointerOperand()))
       return;
     Interesting.emplace_back(I, SI->getPointerOperandIndex(), true,
                              SI->getValueOperand()->getType(), SI->getAlign());
   } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
-    if (!ClInstrumentAtomics || ignoreAccess(RMW->getPointerOperand()))
+    if (!ClInstrumentAtomics || ignoreAccess(I, RMW->getPointerOperand()))
       return;
     Interesting.emplace_back(I, RMW->getPointerOperandIndex(), true,
                              RMW->getValOperand()->getType(), None);
   } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
-    if (!ClInstrumentAtomics || ignoreAccess(XCHG->getPointerOperand()))
+    if (!ClInstrumentAtomics || ignoreAccess(I, XCHG->getPointerOperand()))
       return;
     Interesting.emplace_back(I, XCHG->getPointerOperandIndex(), true,
                              XCHG->getCompareOperand()->getType(), None);
   } else if (auto CI = dyn_cast<CallInst>(I)) {
     for (unsigned ArgNo = 0; ArgNo < CI->getNumArgOperands(); ArgNo++) {
       if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) ||
-          ignoreAccess(CI->getArgOperand(ArgNo)))
+          ignoreAccess(I, CI->getArgOperand(ArgNo)))
         continue;
       Type *Ty = CI->getParamByValType(ArgNo);
       Interesting.emplace_back(I, ArgNo, false, Ty, Align(1));

diff  --git a/llvm/test/Instrumentation/HWAddressSanitizer/memaccess-clobber.ll b/llvm/test/Instrumentation/HWAddressSanitizer/memaccess-clobber.ll
index 2a23079e532ce..dc3f964d6ef2e 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/memaccess-clobber.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/memaccess-clobber.ll
@@ -1,6 +1,6 @@
 ; Make sure memaccess checks preceed the following reads.
 ;
-; RUN: opt < %s -S -enable-new-pm=0 -hwasan -basic-aa -memdep -print-memdeps -analyze -mtriple aarch64-linux-android30 | FileCheck %s
+; RUN: opt < %s -S -enable-new-pm=0 -hwasan -hwasan-use-stack-safety=0 -basic-aa -memdep -print-memdeps -analyze -mtriple aarch64-linux-android30 | FileCheck %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64--linux-android10000"

diff  --git a/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll b/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll
index cb671f8eae88b..a71f950105877 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll
@@ -1,15 +1,21 @@
-; RUN: opt -passes=hwasan -hwasan-use-stack-safety=1 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY
-; RUN: opt -passes=hwasan -hwasan-use-stack-safety=0 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSAFETY
-; RUN: opt -passes=hwasan -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY
+; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=1 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY,CHECK
+; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=0 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSAFETY,CHECK
+; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY,CHECK
+; RUN: opt -passes=hwasan -hwasan-instrument-stack=0 -hwasan-instrument-with-calls -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSTACK,CHECK
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "aarch64-unknown-linux-gnu"
 
 ; Check a safe alloca to ensure it does not get a tag.
-define i32 @test_load(i32* %a) sanitize_hwaddress {
+define i32 @test_simple(i32* %a) sanitize_hwaddress {
 entry:
+  ; CHECK-LABEL: @test_simple
   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
+  ; SAFETY-NOT: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK-NOT: call {{.*}}__hwasan_store
   %buf.sroa.0 = alloca i8, align 4
   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
   store volatile i8 0, i8* %buf.sroa.0, align 4, !tbaa !8
@@ -20,8 +26,13 @@ entry:
 ; Check a non-safe alloca to ensure it gets a tag.
 define i32 @test_use(i32* %a) sanitize_hwaddress {
 entry:
+  ; CHECK-LABEL: @test_use
   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
   ; SAFETY: call {{.*}}__hwasan_generate_tag
+  ; SAFETY-NOT: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK-NOT: call {{.*}}__hwasan_store
   %buf.sroa.0 = alloca i8, align 4
   call void @use(i8* nonnull %buf.sroa.0)
   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
@@ -30,13 +41,130 @@ entry:
   ret i32 0
 }
 
+; Check an alloca with in range GEP to ensure it does not get a tag or check.
+define i32 @test_in_range(i32* %a) sanitize_hwaddress {
+entry:
+  ; CHECK-LABEL: @test_in_range
+  ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
+  ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
+  ; SAFETY-NOT: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK-NOT: call {{.*}}__hwasan_store
+  %buf.sroa.0 = alloca [10 x i8], align 4
+  %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 0
+  call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
+  store volatile i8 0, i8* %ptr, align 4, !tbaa !8
+  call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
+  ret i32 0
+}
+
+; Check an alloca with in range GEP to ensure it does not get a tag or check.
+define i32 @test_in_range2(i32* %a) sanitize_hwaddress {
+entry:
+  ; CHECK-LABEL: @test_in_range2
+  ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
+  ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
+  ; SAFETY-NOT: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK-NOT: call {{.*}}__hwasan_store
+  %buf.sroa.0 = alloca [10 x i8], align 4
+  %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
+  %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
+  store volatile i8 0, i8* %ptr, align 4, !tbaa !8
+  call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
+  ret i32 0
+}
+
+; Check an alloca with out of range GEP to ensure it gets a tag and check.
+define i32 @test_out_of_range(i32* %a) sanitize_hwaddress {
+entry:
+  ; CHECK-LABEL: @test_out_of_range
+  ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
+  ; SAFETY: call {{.*}}__hwasan_generate_tag
+  ; SAFETY: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK-NOT: call {{.*}}__hwasan_store
+  %buf.sroa.0 = alloca [10 x i8], align 4
+  %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 10
+  %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
+  store volatile i8 0, i8* %ptr, align 4, !tbaa !8
+  call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
+  ret i32 0
+}
+
+; Check an alloca with potentially out of range GEP to ensure it gets a tag and
+; check.
+define i32 @test_potentially_out_of_range(i32* %a) sanitize_hwaddress {
+entry:
+  ; CHECK-LABEL: @test_potentially_out_of_range
+  ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
+  ; SAFETY: call {{.*}}__hwasan_generate_tag
+  ; SAFETY: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK-NOT: call {{.*}}__hwasan_store
+  %buf.sroa.0 = alloca [10 x i8], align 4
+  %off = call i32 @getoffset()
+  %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 %off
+  call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
+  store volatile i8 0, i8* %ptr, align 4, !tbaa !8
+  call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
+  ret i32 0
+}
+
+; Check an alloca with potentially out of range GEP to ensure it gets a tag and
+; check.
+define i32 @test_unclear(i32* %a) sanitize_hwaddress {
+entry:
+  ; CHECK-LABEL: @test_unclear
+  ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
+  ; SAFETY: call {{.*}}__hwasan_generate_tag
+  ; SAFETY: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK: call {{.*}}__hwasan_store
+  %buf.sroa.0 = alloca i8, align 4
+  %ptr = call i8* @getptr(i8* %buf.sroa.0)
+  call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
+  store volatile i8 0, i8* %ptr, align 4, !tbaa !8
+  call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
+  ret i32 0
+}
+
+define i32 @test_select(i8* %a) sanitize_hwaddress {
+entry:
+  ; CHECK-LABEL: @test_select
+  ; NOSAFETY: call {{.*}}__hwasan_generate_tag
+  ; NOSAFETY: call {{.*}}__hwasan_store
+  ; SAFETY: call {{.*}}__hwasan_generate_tag
+  ; SAFETY: call {{.*}}__hwasan_store
+  ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
+  ; NOSTACK: call {{.*}}__hwasan_store
+  %x = call i8* @getptr(i8* %a)
+  %buf.sroa.0 = alloca i8, align 4
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
+  %c = call i1 @cond()
+  %ptr = select i1 %c, i8* %x, i8* %buf.sroa.0
+  store volatile i8 0, i8* %ptr, align 4, !tbaa !8
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
+  ret i32 0
+}
+
 ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
 
 ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
 
+declare i1 @cond()
 declare void @use(i8* nocapture)
+declare i32 @getoffset()
+declare i8* @getptr(i8* nocapture)
 
 !8 = !{!9, !9, i64 0}
 !9 = !{!"omnipotent char", !10, i64 0}


        


More information about the llvm-commits mailing list