Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,14 @@ void AArch64AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {

void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
Register Reg = MI.getOperand(0).getReg();

// The HWASan pass won't emit a CHECK_MEMACCESS intrinsic with a pointer
// statically known to be zero. However, conceivably the HWASan pass has a
// "maybe non-zero" pointer but later optimization passes convert it into
// a null pointer. As a last line of defense, we perform elision here too.
if (Reg == AArch64::XZR)
return;

bool IsShort =
((MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
(MI.getOpcode() ==
Expand Down
20 changes: 16 additions & 4 deletions llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ class HWAddressSanitizer {
bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *MI);
void instrumentMemIntrinsic(MemIntrinsic *MI);
bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,
LoopInfo *LI);
LoopInfo *LI, const DataLayout &DL);
bool ignoreAccessWithoutRemark(Instruction *Inst, Value *Ptr);
bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,
Value *Ptr);
Expand Down Expand Up @@ -1163,12 +1163,23 @@ void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
}

bool HWAddressSanitizer::instrumentMemAccess(InterestingMemoryOperand &O,
DomTreeUpdater &DTU,
LoopInfo *LI) {
DomTreeUpdater &DTU, LoopInfo *LI,
const DataLayout &DL) {
Value *Addr = O.getPtr();

LLVM_DEBUG(dbgs() << "Instrumenting: " << O.getInsn() << "\n");

// If the pointer is statically known to be zero, the tag check will pass
// since:
// 1) it has a zero tag
// 2) the shadow memory corresponding to address 0 is initialized to zero and
// never updated.
// We can therefore elide the tag check.
llvm::KnownBits Known(DL.getPointerTypeSizeInBits(Addr->getType()));
llvm::computeKnownBits(Addr, Known, DL);
if (Known.getMinValue() == 0 && Known.getMaxValue() == 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be just

if (Known.isZero())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a nice simplification! Done.

return false;

if (O.MaybeMask)
return false; // FIXME

Expand Down Expand Up @@ -1701,8 +1712,9 @@ void HWAddressSanitizer::sanitizeFunction(Function &F,
PostDominatorTree *PDT = FAM.getCachedResult<PostDominatorTreeAnalysis>(F);
LoopInfo *LI = FAM.getCachedResult<LoopAnalysis>(F);
DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
const DataLayout &DL = F.getDataLayout();
for (auto &Operand : OperandsToInstrument)
instrumentMemAccess(Operand, DTU, LI);
instrumentMemAccess(Operand, DTU, LI, DL);
DTU.flush();

if (ClInstrumentMemIntrinsics && !IntrinToInstrument.empty()) {
Expand Down
11 changes: 6 additions & 5 deletions llvm/test/CodeGen/AArch64/hwasan-zero-ptr.ll
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -filetype asm -o - %s | FileCheck %s

; This shows that when dereferencing a null pointer, HWASan will call
; __hwasan_check_x4294967071_19_fixed_0_short_v2
; (N.B. 4294967071 == 2**32 - 239 + 14 == 2**32 - X0 + XZR
; This shows that HWASan will elide the tag check when lowering the memaccess
; intrinsic for null pointers.
; N.B. The HWASan pass will normally omit the memaccess intrinsic if the
; pointer is already statically known to be null.
;
; The source was generated from llvm/test/Instrumentation/HWAddressSanitizer/zero-ptr.ll.
; The source was generated from llvm/test/Instrumentation/HWAddressSanitizer/zero-ptr.ll
; with the memaccess deliberately retained.

; ModuleID = '<stdin>'
source_filename = "<stdin>"
Expand All @@ -25,7 +27,6 @@ define void @test_store_to_zeroptr() #0 {
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: bl __hwasan_check_x4294967071_19_fixed_0_short_v2
; CHECK-NEXT: mov x8, xzr
; CHECK-NEXT: mov w9, #42 // =0x2a
; CHECK-NEXT: str x9, [x8]
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/Instrumentation/HWAddressSanitizer/zero-ptr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; RUN: opt < %s -passes=hwasan -S | FileCheck %s
; RUN: opt < %s -passes=hwasan -hwasan-recover=0 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=ABORT-ZERO-BASED-SHADOW

; This shows that HWASan will emit a memaccess check when dereferencing a null
; This shows that HWASan omits the memaccess check when dereferencing a null
; pointer.
; The output is used as the source for llvm/test/CodeGen/AArch64/hwasan-zero-ptr.ll.

Expand All @@ -15,7 +15,6 @@ define void @test_store_to_zeroptr() sanitize_hwaddress {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[DOTHWASAN_SHADOW:%.*]] = call ptr asm "", "=r,0"(ptr @__hwasan_shadow)
; CHECK-NEXT: [[B:%.*]] = inttoptr i64 0 to ptr
; CHECK-NEXT: call void @llvm.hwasan.check.memaccess.shortgranules(ptr [[DOTHWASAN_SHADOW]], ptr [[B]], i32 19)
; CHECK-NEXT: store i64 42, ptr [[B]], align 8
; CHECK-NEXT: ret void
;
Expand All @@ -24,7 +23,6 @@ define void @test_store_to_zeroptr() sanitize_hwaddress {
; ABORT-ZERO-BASED-SHADOW-NEXT: entry:
; ABORT-ZERO-BASED-SHADOW-NEXT: [[DOTHWASAN_SHADOW:%.*]] = call ptr asm "", "=r,0"(ptr null)
; ABORT-ZERO-BASED-SHADOW-NEXT: [[B:%.*]] = inttoptr i64 0 to ptr
; ABORT-ZERO-BASED-SHADOW-NEXT: call void @llvm.hwasan.check.memaccess.shortgranules.fixedshadow(ptr [[B]], i32 19, i64 0)
; ABORT-ZERO-BASED-SHADOW-NEXT: store i64 42, ptr [[B]], align 8
; ABORT-ZERO-BASED-SHADOW-NEXT: ret void
;
Expand Down
Loading