Skip to content

Commit 365bddf

Browse files
authored
[hwasan] Add intrinsics for fixed shadow on Aarch64 (#89319)
This patch introduces HWASan memaccess intrinsics that assume a fixed shadow (with the offset provided by --hwasan-mapping-offset=...), with and without short granule support. The behavior of HWASan is not meaningfully changed by this patch; future work ("Optimize outlined memaccess for fixed shadow on Aarch64": #88544) will make HWASan use these intrinsics. We currently only support lowering the LLVM IR intrinsic to AArch64. The test case is adapted from hwasan-check-memaccess.ll.
1 parent a28557a commit 365bddf

File tree

4 files changed

+118
-49
lines changed

4 files changed

+118
-49
lines changed

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2363,13 +2363,34 @@ def int_load_relative: DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_a
23632363
def int_asan_check_memaccess :
23642364
Intrinsic<[],[llvm_ptr_ty, llvm_i32_ty], [ImmArg<ArgIndex<1>>]>;
23652365

2366+
// HWASan intrinsics to test whether a pointer is addressable.
2367+
//===----------------------------------------------------------------------===//
2368+
//
2369+
// Variant 1) is the OG memaccess intrinsic
2370+
// Parameters: Shadow base (passed in a register), pointer to be checked for
2371+
// validity, AccessInfo (AccessInfo is defined in HWAddressSanitizer.h)
23662372
def int_hwasan_check_memaccess :
23672373
Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty],
23682374
[ImmArg<ArgIndex<2>>]>;
2375+
2376+
// Variant 2) supports short granule checks
2377+
// Parameters: same as Variant 1
23692378
def int_hwasan_check_memaccess_shortgranules :
23702379
Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty],
23712380
[ImmArg<ArgIndex<2>>]>;
23722381

2382+
// Variant 3) assumes a fixed shadow offset
2383+
// Parameters: Pointer to be checked for validity, AccessInfo, Shadow base
2384+
def int_hwasan_check_memaccess_fixedshadow :
2385+
Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i64_ty],
2386+
[ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;
2387+
2388+
// Variant 4) supports short granule checks and assumes a fixed shadow offset
2389+
// Parameters: same as Variant 3
2390+
def int_hwasan_check_memaccess_shortgranules_fixedshadow :
2391+
Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i64_ty],
2392+
[ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;
2393+
23732394
// Xray intrinsics
23742395
//===----------------------------------------------------------------------===//
23752396
// Custom event logging for x-ray.

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ class AArch64AsmPrinter : public AsmPrinter {
116116
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
117117
void LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, bool Typed);
118118

119-
typedef std::tuple<unsigned, bool, uint32_t> HwasanMemaccessTuple;
119+
typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
120+
HwasanMemaccessTuple;
120121
std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
121122
void LowerKCFI_CHECK(const MachineInstr &MI);
122123
void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
@@ -551,17 +552,27 @@ void AArch64AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
551552
void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
552553
Register Reg = MI.getOperand(0).getReg();
553554
bool IsShort =
554-
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES;
555+
((MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
556+
(MI.getOpcode() ==
557+
AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
555558
uint32_t AccessInfo = MI.getOperand(1).getImm();
556-
MCSymbol *&Sym =
557-
HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, IsShort, AccessInfo)];
559+
bool IsFixedShadow =
560+
((MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
561+
(MI.getOpcode() ==
562+
AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
563+
uint64_t FixedShadowOffset = IsFixedShadow ? MI.getOperand(2).getImm() : 0;
564+
565+
MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
566+
Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
558567
if (!Sym) {
559568
// FIXME: Make this work on non-ELF.
560569
if (!TM.getTargetTriple().isOSBinFormatELF())
561570
report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
562571

563572
std::string SymName = "__hwasan_check_x" + utostr(Reg - AArch64::X0) + "_" +
564573
utostr(AccessInfo);
574+
if (IsFixedShadow)
575+
SymName += "_fixed_" + utostr(FixedShadowOffset);
565576
if (IsShort)
566577
SymName += "_short_v2";
567578
Sym = OutContext.getOrCreateSymbol(SymName);
@@ -596,6 +607,8 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
596607
unsigned Reg = std::get<0>(P.first);
597608
bool IsShort = std::get<1>(P.first);
598609
uint32_t AccessInfo = std::get<2>(P.first);
610+
bool IsFixedShadow = std::get<3>(P.first);
611+
uint64_t FixedShadowOffset = std::get<4>(P.first);
599612
const MCSymbolRefExpr *HwasanTagMismatchRef =
600613
IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
601614
MCSymbol *Sym = P.second;
@@ -625,14 +638,35 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
625638
.addImm(4)
626639
.addImm(55),
627640
*STI);
628-
OutStreamer->emitInstruction(
629-
MCInstBuilder(AArch64::LDRBBroX)
630-
.addReg(AArch64::W16)
631-
.addReg(IsShort ? AArch64::X20 : AArch64::X9)
632-
.addReg(AArch64::X16)
633-
.addImm(0)
634-
.addImm(0),
635-
*STI);
641+
642+
if (IsFixedShadow) {
643+
// Aarch64 makes it difficult to embed large constants in the code.
644+
// Fortuitously, kShadowBaseAlignment == 32, so we use the 32-bit
645+
// left-shift option in the MOV instruction. Combined with the 16-bit
646+
// immediate, this is enough to represent any offset up to 2**48.
647+
OutStreamer->emitInstruction(MCInstBuilder(AArch64::MOVZXi)
648+
.addReg(AArch64::X17)
649+
.addImm(FixedShadowOffset >> 32)
650+
.addImm(32),
651+
*STI);
652+
OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDRBBroX)
653+
.addReg(AArch64::W16)
654+
.addReg(AArch64::X17)
655+
.addReg(AArch64::X16)
656+
.addImm(0)
657+
.addImm(0),
658+
*STI);
659+
} else {
660+
OutStreamer->emitInstruction(
661+
MCInstBuilder(AArch64::LDRBBroX)
662+
.addReg(AArch64::W16)
663+
.addReg(IsShort ? AArch64::X20 : AArch64::X9)
664+
.addReg(AArch64::X16)
665+
.addImm(0)
666+
.addImm(0),
667+
*STI);
668+
}
669+
636670
OutStreamer->emitInstruction(
637671
MCInstBuilder(AArch64::SUBSXrs)
638672
.addReg(AArch64::XZR)
@@ -1765,6 +1799,8 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
17651799

17661800
case AArch64::HWASAN_CHECK_MEMACCESS:
17671801
case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
1802+
case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
1803+
case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
17681804
LowerHWASAN_CHECK_MEMACCESS(*MI);
17691805
return;
17701806

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,20 @@ def HWASAN_CHECK_MEMACCESS_SHORTGRANULES : Pseudo<
18181818
Sched<[]>;
18191819
}
18201820

1821+
let Defs = [ X16, X17, LR, NZCV ] in {
1822+
def HWASAN_CHECK_MEMACCESS_FIXEDSHADOW : Pseudo<
1823+
(outs), (ins GPR64noip:$ptr, i32imm:$accessinfo, i64imm:$fixed_shadow),
1824+
[(int_hwasan_check_memaccess_fixedshadow GPR64noip:$ptr, (i32 timm:$accessinfo), (i64 timm:$fixed_shadow))]>,
1825+
Sched<[]>;
1826+
}
1827+
1828+
let Defs = [ X16, X17, LR, NZCV ] in {
1829+
def HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW : Pseudo<
1830+
(outs), (ins GPR64noip:$ptr, i32imm:$accessinfo, i64imm:$fixed_shadow),
1831+
[(int_hwasan_check_memaccess_shortgranules_fixedshadow GPR64noip:$ptr, (i32 timm:$accessinfo), (i64 timm:$fixed_shadow))]>,
1832+
Sched<[]>;
1833+
}
1834+
18211835
// The virtual cycle counter register is CNTVCT_EL0.
18221836
def : Pat<(readcyclecounter), (MRS 0xdf02)>;
18231837

llvm/test/CodeGen/AArch64/hwasan-check-memaccess-fixedshadow.ll

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
2-
; RUN: llc --hwasan-mapping-offset=4398046511104 < %s | FileCheck %s
2+
; RUN: llc < %s | FileCheck %s
33

44
target triple = "aarch64--linux-android"
55

@@ -9,27 +9,24 @@ define ptr @f1(ptr %x0, ptr %x1) {
99
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
1010
; CHECK-NEXT: .cfi_def_cfa_offset 16
1111
; CHECK-NEXT: .cfi_offset w30, -16
12-
; CHECK-NEXT: mov x9, x0
12+
; CHECK-NEXT: bl __hwasan_check_x1_1_fixed_4398046511104
1313
; CHECK-NEXT: mov x0, x1
14-
; CHECK-NEXT: bl __hwasan_check_x1_1
1514
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
1615
; CHECK-NEXT: ret
17-
call void @llvm.hwasan.check.memaccess(ptr %x0, ptr %x1, i32 1)
16+
call void @llvm.hwasan.check.memaccess.fixedshadow(ptr %x1, i32 1, i64 4398046511104)
1817
ret ptr %x1
1918
}
2019

2120
define ptr @f2(ptr %x0, ptr %x1) {
2221
; CHECK-LABEL: f2:
2322
; CHECK: // %bb.0:
24-
; CHECK-NEXT: stp x30, x20, [sp, #-16]! // 16-byte Folded Spill
23+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
2524
; CHECK-NEXT: .cfi_def_cfa_offset 16
26-
; CHECK-NEXT: .cfi_offset w20, -8
2725
; CHECK-NEXT: .cfi_offset w30, -16
28-
; CHECK-NEXT: mov x20, x1
29-
; CHECK-NEXT: bl __hwasan_check_x0_2_short_v2
30-
; CHECK-NEXT: ldp x30, x20, [sp], #16 // 16-byte Folded Reload
26+
; CHECK-NEXT: bl __hwasan_check_x0_2_fixed_4398046511104_short_v2
27+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
3128
; CHECK-NEXT: ret
32-
call void @llvm.hwasan.check.memaccess.shortgranules(ptr %x1, ptr %x0, i32 2)
29+
call void @llvm.hwasan.check.memaccess.shortgranules.fixedshadow(ptr %x0, i32 2, i64 4398046511104)
3330
ret ptr %x0
3431
}
3532

@@ -40,40 +37,38 @@ define void @f3(ptr %x0, ptr %x1) {
4037
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
4138
; CHECK-NEXT: .cfi_def_cfa_offset 16
4239
; CHECK-NEXT: .cfi_offset w30, -16
43-
; CHECK-NEXT: mov x9, x0
44-
; CHECK-NEXT: bl __hwasan_check_x1_67043328
40+
; CHECK-NEXT: bl __hwasan_check_x1_67043328_fixed_4398046511104
4541
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
4642
; CHECK-NEXT: ret
47-
call void @llvm.hwasan.check.memaccess(ptr %x0, ptr %x1, i32 67043328)
43+
call void @llvm.hwasan.check.memaccess.fixedshadow(ptr %x1, i32 67043328, i64 4398046511104)
4844
ret void
4945
}
5046

5147
define void @f4(ptr %x0, ptr %x1) {
5248
; 0x1000010 (access-size-index = 0, is-write = 1, match-all = 0x0)
5349
; CHECK-LABEL: f4:
5450
; CHECK: // %bb.0:
55-
; CHECK-NEXT: stp x30, x20, [sp, #-16]! // 16-byte Folded Spill
51+
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
5652
; CHECK-NEXT: .cfi_def_cfa_offset 16
57-
; CHECK-NEXT: .cfi_offset w20, -8
5853
; CHECK-NEXT: .cfi_offset w30, -16
59-
; CHECK-NEXT: mov x20, x0
60-
; CHECK-NEXT: bl __hwasan_check_x1_16777232_short_v2
61-
; CHECK-NEXT: ldp x30, x20, [sp], #16 // 16-byte Folded Reload
54+
; CHECK-NEXT: bl __hwasan_check_x1_16777232_fixed_4398046511104_short_v2
55+
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
6256
; CHECK-NEXT: ret
63-
call void @llvm.hwasan.check.memaccess.shortgranules(ptr %x0, ptr %x1, i32 16777232)
57+
call void @llvm.hwasan.check.memaccess.shortgranules.fixedshadow(ptr %x1, i32 16777232, i64 4398046511104)
6458
ret void
6559
}
6660

67-
declare void @llvm.hwasan.check.memaccess(ptr, ptr, i32)
68-
declare void @llvm.hwasan.check.memaccess.shortgranules(ptr, ptr, i32)
61+
declare void @llvm.hwasan.check.memaccess.fixedshadow(ptr, i32, i64)
62+
declare void @llvm.hwasan.check.memaccess.shortgranules.fixedshadow(ptr, i32, i64)
6963

70-
; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x0_2_short_v2,comdat
71-
; CHECK-NEXT: .type __hwasan_check_x0_2_short_v2,@function
72-
; CHECK-NEXT: .weak __hwasan_check_x0_2_short_v2
73-
; CHECK-NEXT: .hidden __hwasan_check_x0_2_short_v2
74-
; CHECK-NEXT: __hwasan_check_x0_2_short_v2:
64+
; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x0_2_fixed_4398046511104_short_v2,comdat
65+
; CHECK-NEXT: .type __hwasan_check_x0_2_fixed_4398046511104_short_v2,@function
66+
; CHECK-NEXT: .weak __hwasan_check_x0_2_fixed_4398046511104_short_v2
67+
; CHECK-NEXT: .hidden __hwasan_check_x0_2_fixed_4398046511104_short_v2
68+
; CHECK-NEXT: __hwasan_check_x0_2_fixed_4398046511104_short_v2:
7569
; CHECK-NEXT: sbfx x16, x0, #4, #52
76-
; CHECK-NEXT: ldrb w16, [x20, x16]
70+
; CHECK-NEXT: mov x17, #4398046511104
71+
; CHECK-NEXT: ldrb w16, [x17, x16]
7772
; CHECK-NEXT: cmp x16, x0, lsr #56
7873
; CHECK-NEXT: b.ne .Ltmp0
7974
; CHECK-NEXT: .Ltmp1:
@@ -98,13 +93,14 @@ declare void @llvm.hwasan.check.memaccess.shortgranules(ptr, ptr, i32)
9893
; CHECK-NEXT: br x16
9994

10095

101-
; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x1_1,comdat
102-
; CHECK-NEXT: .type __hwasan_check_x1_1,@function
103-
; CHECK-NEXT: .weak __hwasan_check_x1_1
104-
; CHECK-NEXT: .hidden __hwasan_check_x1_1
105-
; CHECK-NEXT: __hwasan_check_x1_1:
96+
; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x1_1_fixed_4398046511104,comdat
97+
; CHECK-NEXT: .type __hwasan_check_x1_1_fixed_4398046511104,@function
98+
; CHECK-NEXT: .weak __hwasan_check_x1_1_fixed_4398046511104
99+
; CHECK-NEXT: .hidden __hwasan_check_x1_1_fixed_4398046511104
100+
; CHECK-NEXT: __hwasan_check_x1_1_fixed_4398046511104:
106101
; CHECK-NEXT: sbfx x16, x1, #4, #52
107-
; CHECK-NEXT: ldrb w16, [x9, x16]
102+
; CHECK-NEXT: mov x17, #4398046511104
103+
; CHECK-NEXT: ldrb w16, [x17, x16]
108104
; CHECK-NEXT: cmp x16, x1, lsr #56
109105
; CHECK-NEXT: b.ne .Ltmp3
110106
; CHECK-NEXT: .Ltmp4:
@@ -118,9 +114,10 @@ declare void @llvm.hwasan.check.memaccess.shortgranules(ptr, ptr, i32)
118114
; CHECK-NEXT: ldr x16, [x16, :got_lo12:__hwasan_tag_mismatch]
119115
; CHECK-NEXT: br x16
120116

121-
; CHECK: __hwasan_check_x1_67043328:
117+
; CHECK: __hwasan_check_x1_67043328_fixed_4398046511104:
122118
; CHECK-NEXT: sbfx x16, x1, #4, #52
123-
; CHECK-NEXT: ldrb w16, [x9, x16]
119+
; CHECK-NEXT: mov x17, #4398046511104
120+
; CHECK-NEXT: ldrb w16, [x17, x16]
124121
; CHECK-NEXT: cmp x16, x1, lsr #56
125122
; CHECK-NEXT: b.ne .Ltmp5
126123
; CHECK-NEXT: .Ltmp6:
@@ -135,9 +132,10 @@ declare void @llvm.hwasan.check.memaccess.shortgranules(ptr, ptr, i32)
135132
; CHECK-NEXT: mov x1, #0
136133
; CHECK-NEXT: b __hwasan_tag_mismatch
137134

138-
; CHECK: __hwasan_check_x1_16777232_short_v2:
135+
; CHECK: __hwasan_check_x1_16777232_fixed_4398046511104_short_v2:
139136
; CHECK-NEXT: sbfx x16, x1, #4, #52
140-
; CHECK-NEXT: ldrb w16, [x20, x16]
137+
; CHECK-NEXT: mov x17, #4398046511104
138+
; CHECK-NEXT: ldrb w16, [x17, x16]
141139
; CHECK-NEXT: cmp x16, x1, lsr #56
142140
; CHECK-NEXT: b.ne .Ltmp7
143141
; CHECK-NEXT: .Ltmp8:

0 commit comments

Comments
 (0)