Skip to content

Commit 7502e5f

Browse files
[KMSAN] Enable -msan-handle-asm-conservative by default
This change enables conservative assembly instrumentation in KMSAN builds by default. It's still possible to disable it with -msan-handle-asm-conservative=0 if something breaks. It's now impossible to enable conservative instrumentation for userspace builds, but it's not used anyway. llvm-svn: 348112
1 parent d336c4e commit 7502e5f

File tree

3 files changed

+77
-34
lines changed

3 files changed

+77
-34
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,13 @@ static cl::opt<bool> ClHandleICmpExact("msan-handle-icmp-exact",
255255
// passed into an assembly call. Note that this may cause false positives.
256256
// Because it's impossible to figure out the array sizes, we can only unpoison
257257
// the first sizeof(type) bytes for each type* pointer.
258+
// The instrumentation is only enabled in KMSAN builds, and only if
259+
// -msan-handle-asm-conservative is on. This is done because we may want to
260+
// quickly disable assembly instrumentation when it breaks.
258261
static cl::opt<bool> ClHandleAsmConservative(
259262
"msan-handle-asm-conservative",
260263
cl::desc("conservative handling of inline assembly"), cl::Hidden,
261-
cl::init(false));
264+
cl::init(true));
262265

263266
// This flag controls whether we check the shadow of the address
264267
// operand of load or store. Such bugs are very rare, since load from
@@ -3118,7 +3121,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
31183121
// outputs as clean. Note that any side effects of the inline asm that are
31193122
// not immediately visible in its constraints are not handled.
31203123
if (Call->isInlineAsm()) {
3121-
if (ClHandleAsmConservative)
3124+
if (ClHandleAsmConservative && MS.CompileKernel)
31223125
visitAsmInstruction(I);
31233126
else
31243127
visitInstruction(I);

llvm/test/Instrumentation/MemorySanitizer/msan_asm_conservative.ll

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Test for handling of asm constraints in MSan instrumentation.
2-
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S | FileCheck -check-prefixes=CHECK,CHECK-NONCONS %s
3-
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=1 -S | FileCheck -check-prefixes=CHECK,CHECK-CONS %s
2+
; RUN: opt < %s -msan -msan-kernel=1 -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S | FileCheck -check-prefixes=CHECK,CHECK-NONCONS %s
3+
; RUN: opt < %s -msan -msan-kernel=1 -msan-check-access-address=0 -msan-handle-asm-conservative=1 -S | FileCheck -check-prefixes=CHECK,CHECK-CONS %s
44

55
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
66
target triple = "x86_64-unknown-linux-gnu"
@@ -40,9 +40,12 @@ entry:
4040

4141
; CHECK-LABEL: @f_1i_1o_reg
4242
; CHECK: [[IS1_F1:%.*]] = load i32, i32* @is1, align 4
43-
; CHECK: call void @__msan_warning_noreturn()
43+
; CHECK: call void @__msan_warning
4444
; CHECK: call i32 asm "",{{.*}}(i32 [[IS1_F1]])
45-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
45+
; CHECK: [[PACK1_F1:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
46+
; CHECK: [[EXT1_F1:%.*]] = extractvalue { i8*, i32* } [[PACK1_F1]], 0
47+
; CHECK: [[CAST1_F1:%.*]] = bitcast i8* [[EXT1_F1]] to i32*
48+
; CHECK: store i32 0, i32* [[CAST1_F1]]
4649

4750

4851
; Two input registers, two output registers:
@@ -62,11 +65,17 @@ entry:
6265
; CHECK-LABEL: @f_2i_2o_reg
6366
; CHECK: [[IS1_F2:%.*]] = load i32, i32* @is1, align 4
6467
; CHECK: [[IS2_F2:%.*]] = load i32, i32* @is2, align 4
65-
; CHECK: call void @__msan_warning_noreturn()
66-
; CHECK: call void @__msan_warning_noreturn()
68+
; CHECK: call void @__msan_warning
69+
; CHECK: call void @__msan_warning
6770
; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[IS1_F2]], i32 [[IS2_F2]])
68-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
69-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
71+
; CHECK: [[PACK1_F2:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
72+
; CHECK: [[EXT1_F2:%.*]] = extractvalue { i8*, i32* } [[PACK1_F2]], 0
73+
; CHECK: [[CAST1_F2:%.*]] = bitcast i8* [[EXT1_F2]] to i32*
74+
; CHECK: store i32 0, i32* [[CAST1_F2]]
75+
; CHECK: [[PACK2_F2:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
76+
; CHECK: [[EXT2_F2:%.*]] = extractvalue { i8*, i32* } [[PACK2_F2]], 0
77+
; CHECK: [[CAST2_F2:%.*]] = bitcast i8* [[EXT2_F2]] to i32*
78+
; CHECK: store i32 0, i32* [[CAST2_F2]]
7079

7180
; Input same as output, used twice:
7281
; asm("" : "=r" (id1), "=r" (id2) : "r" (id1), "r" (id2));
@@ -85,11 +94,17 @@ entry:
8594
; CHECK-LABEL: @f_2i_2o_reuse2_reg
8695
; CHECK: [[ID1_F3:%.*]] = load i32, i32* @id1, align 4
8796
; CHECK: [[ID2_F3:%.*]] = load i32, i32* @id2, align 4
88-
; CHECK: call void @__msan_warning_noreturn()
89-
; CHECK: call void @__msan_warning_noreturn()
97+
; CHECK: call void @__msan_warning
98+
; CHECK: call void @__msan_warning
9099
; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[ID1_F3]], i32 [[ID2_F3]])
91-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
92-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
100+
; CHECK: [[PACK1_F3:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
101+
; CHECK: [[EXT1_F3:%.*]] = extractvalue { i8*, i32* } [[PACK1_F3]], 0
102+
; CHECK: [[CAST1_F3:%.*]] = bitcast i8* [[EXT1_F3]] to i32*
103+
; CHECK: store i32 0, i32* [[CAST1_F3]]
104+
; CHECK: [[PACK2_F3:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
105+
; CHECK: [[EXT2_F3:%.*]] = extractvalue { i8*, i32* } [[PACK2_F3]], 0
106+
; CHECK: [[CAST2_F3:%.*]] = bitcast i8* [[EXT2_F3]] to i32*
107+
; CHECK: store i32 0, i32* [[CAST2_F3]]
93108

94109

95110
; One of the input registers is also an output:
@@ -109,11 +124,17 @@ entry:
109124
; CHECK-LABEL: @f_2i_2o_reuse1_reg
110125
; CHECK: [[ID1_F4:%.*]] = load i32, i32* @id1, align 4
111126
; CHECK: [[IS1_F4:%.*]] = load i32, i32* @is1, align 4
112-
; CHECK: call void @__msan_warning_noreturn()
113-
; CHECK: call void @__msan_warning_noreturn()
127+
; CHECK: call void @__msan_warning
128+
; CHECK: call void @__msan_warning
114129
; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[ID1_F4]], i32 [[IS1_F4]])
115-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
116-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
130+
; CHECK: [[PACK1_F4:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
131+
; CHECK: [[EXT1_F4:%.*]] = extractvalue { i8*, i32* } [[PACK1_F4]], 0
132+
; CHECK: [[CAST1_F4:%.*]] = bitcast i8* [[EXT1_F4]] to i32*
133+
; CHECK: store i32 0, i32* [[CAST1_F4]]
134+
; CHECK: [[PACK2_F4:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
135+
; CHECK: [[EXT2_F4:%.*]] = extractvalue { i8*, i32* } [[PACK2_F4]], 0
136+
; CHECK: [[CAST2_F4:%.*]] = bitcast i8* [[EXT2_F4]] to i32*
137+
; CHECK: store i32 0, i32* [[CAST2_F4]]
117138

118139

119140
; One input register, three output registers:
@@ -133,11 +154,20 @@ entry:
133154

134155
; CHECK-LABEL: @f_1i_3o_reg
135156
; CHECK: [[IS1_F5:%.*]] = load i32, i32* @is1, align 4
136-
; CHECK: call void @__msan_warning_noreturn()
157+
; CHECK: call void @__msan_warning
137158
; CHECK: call { i32, i32, i32 } asm "",{{.*}}(i32 [[IS1_F5]])
138-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
139-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
140-
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id3 to i64)
159+
; CHECK: [[PACK1_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
160+
; CHECK: [[EXT1_F5:%.*]] = extractvalue { i8*, i32* } [[PACK1_F5]], 0
161+
; CHECK: [[CAST1_F5:%.*]] = bitcast i8* [[EXT1_F5]] to i32*
162+
; CHECK: store i32 0, i32* [[CAST1_F5]]
163+
; CHECK: [[PACK2_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
164+
; CHECK: [[EXT2_F5:%.*]] = extractvalue { i8*, i32* } [[PACK2_F5]], 0
165+
; CHECK: [[CAST2_F5:%.*]] = bitcast i8* [[EXT2_F5]] to i32*
166+
; CHECK: store i32 0, i32* [[CAST2_F5]]
167+
; CHECK: [[PACK3_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id3{{.*}})
168+
; CHECK: [[EXT3_F5:%.*]] = extractvalue { i8*, i32* } [[PACK3_F5]], 0
169+
; CHECK: [[CAST3_F5:%.*]] = bitcast i8* [[EXT3_F5]] to i32*
170+
; CHECK: store i32 0, i32* [[CAST3_F5]]
141171

142172

143173
; 2 input memory args, 2 output memory args:
@@ -170,7 +200,7 @@ entry:
170200
; CHECK: [[IS1_F7:%.*]] = load i32, i32* @is1, align 4
171201
; CHECK-CONS: call void @__msan_instrument_asm_load({{.*}}@is1{{.*}}, i64 4)
172202
; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@id1{{.*}}, i64 4)
173-
; CHECK: call void @__msan_warning_noreturn()
203+
; CHECK: call void @__msan_warning
174204
; CHECK: call i32 asm "", "=r,=*m,r,*m,~{dirflag},~{fpsr},~{flags}"(i32* @id1, i32 [[IS1_F7]], i32* @is1)
175205

176206

@@ -212,9 +242,9 @@ entry:
212242
; CHECK: [[C1_F9:%.*]] = load {{.*}} @c1
213243
; CHECK: [[MEMCPY_S1_F9:%.*]] = load {{.*}} @memcpy_s1
214244
; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@pair2{{.*}}, i64 8)
215-
; CHECK: call void @__msan_warning_noreturn()
216-
; CHECK: call void @__msan_warning_noreturn()
217-
; CHECK: call void @__msan_warning_noreturn()
245+
; CHECK: call void @__msan_warning
246+
; CHECK: call void @__msan_warning
247+
; CHECK: call void @__msan_warning
218248
; CHECK: call { i8, i8* (i8*, i8*, i32)* } asm "", "=*r,=r,=r,r,r,r,~{dirflag},~{fpsr},~{flags}"(%struct.pair* @pair2, {{.*}}[[PAIR1_F9]], i8 [[C1_F9]], {{.*}} [[MEMCPY_S1_F9]])
219249

220250
; Three inputs and three outputs of different types: a pair, a char, a function pointer.

llvm/test/Instrumentation/MemorySanitizer/msan_x86_bts_asm.ll

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Test for the conservative assembly handling mode used by KMSAN.
2-
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S | FileCheck -check-prefixes=CHECK,CHECK-NONCONS %s
3-
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=1 -S | FileCheck -check-prefixes=CHECK,CHECK-CONS %s
2+
; RUN: opt < %s -msan -msan-kernel=1 -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S | FileCheck -check-prefixes=CHECK,CHECK-NONCONS %s
3+
; RUN: opt < %s -msan -msan-kernel=1 -msan-check-access-address=0 -msan-handle-asm-conservative=1 -S | FileCheck -check-prefixes=CHECK,CHECK-CONS %s
44

55
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
66
target triple = "x86_64-unknown-linux-gnu"
@@ -52,24 +52,34 @@ if.else: ; preds = %entry
5252
ret i32 1
5353
}
5454

55+
; %nr is first poisoned, then unpoisoned (written to). Need to optimize this in the future.
56+
; CHECK: [[NRC1:%.*]] = bitcast i64* %nr to i8*
57+
; CHECK: call void @__msan_poison_alloca(i8* [[NRC1]]{{.*}})
58+
; CHECK: [[NRC2:%.*]] = bitcast i64* %nr to i8*
59+
; CHECK: call { i8*, i32* } @__msan_metadata_ptr_for_store_8(i8* [[NRC2]])
60+
5561
; Hooks for inputs usually go before the assembly statement. But here we have none,
5662
; because %nr is passed by value. However we check %nr for being initialized.
57-
; CHECK-CONS: [[NRC:%.*]] = ptrtoint i64* %nr to i64
63+
; CHECK-CONS: [[NRC3:%.*]] = bitcast i64* %nr to i8*
64+
; CHECK-CONS: call { i8*, i32* } @__msan_metadata_ptr_for_load_8(i8* [[NRC3]])
5865

5966
; In the conservative mode, call the store hooks for %bit and %addr:
6067
; CHECK-CONS: call void @__msan_instrument_asm_store(i8* %bit, i64 1)
6168
; CHECK-CONS: [[ADDR8S:%.*]] = bitcast i64** %addr to i8*
6269
; CHECK-CONS: call void @__msan_instrument_asm_store(i8* [[ADDR8S]], i64 8)
6370

6471
; Landing pad for the %nr check above.
65-
; CHECK-CONS: call void @__msan_warning_noreturn()
72+
; CHECK-CONS: call void @__msan_warning
6673

6774
; CHECK: call void asm "btsq $2, $1; setc $0"
6875

6976
; Calculating the shadow offset of %bit.
70-
; CHECK: [[PTR:%.*]] = ptrtoint {{.*}} %bit to i64
71-
; CHECK: [[SH_NUM:%.*]] = xor i64 [[PTR]]
72-
; CHECK: [[SHADOW:%.*]] = inttoptr i64 [[SH_NUM]] {{.*}}
77+
; CHECKz: [[PTR:%.*]] = ptrtoint {{.*}} %bit to i64
78+
; CHECKz: [[SH_NUM:%.*]] = xor i64 [[PTR]]
79+
; CHECKz: [[SHADOW:%.*]] = inttoptr i64 [[SH_NUM]] {{.*}}
80+
81+
; CHECK: [[META:%.*]] = call {{.*}} @__msan_metadata_ptr_for_load_1(i8* %bit)
82+
; CHECK: [[SHADOW:%.*]] = extractvalue { i8*, i32* } [[META]], 0
7383

7484
; Now load the shadow value for the boolean.
7585
; CHECK: [[MSLD:%.*]] = load {{.*}} [[SHADOW]]
@@ -81,5 +91,5 @@ if.else: ; preds = %entry
8191

8292
; If yes, raise a warning.
8393
; CHECK: <label>:[[IFTRUE]]
84-
; CHECK: call void @__msan_warning_noreturn()
94+
; CHECK: call void @__msan_warning
8595

0 commit comments

Comments
 (0)