forked from OSchip/llvm-project
[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
This commit is contained in:
parent
8fdd821aef
commit
09391e7e50
|
@ -287,7 +287,7 @@ public:
|
|||
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 different 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));
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Reference in New Issue