1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[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
This commit is contained in:
Alexander Potapenko 2018-12-03 10:15:43 +00:00
parent 3e533dcfa4
commit 8e6b80a242
3 changed files with 77 additions and 34 deletions

View File

@ -255,10 +255,13 @@ static cl::opt<bool> ClHandleICmpExact("msan-handle-icmp-exact",
// passed into an assembly call. Note that this may cause false positives.
// Because it's impossible to figure out the array sizes, we can only unpoison
// the first sizeof(type) bytes for each type* pointer.
// The instrumentation is only enabled in KMSAN builds, and only if
// -msan-handle-asm-conservative is on. This is done because we may want to
// quickly disable assembly instrumentation when it breaks.
static cl::opt<bool> ClHandleAsmConservative(
"msan-handle-asm-conservative",
cl::desc("conservative handling of inline assembly"), cl::Hidden,
cl::init(false));
cl::init(true));
// This flag controls whether we check the shadow of the address
// operand of load or store. Such bugs are very rare, since load from
@ -3118,7 +3121,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// outputs as clean. Note that any side effects of the inline asm that are
// not immediately visible in its constraints are not handled.
if (Call->isInlineAsm()) {
if (ClHandleAsmConservative)
if (ClHandleAsmConservative && MS.CompileKernel)
visitAsmInstruction(I);
else
visitInstruction(I);

View File

@ -1,6 +1,6 @@
; Test for handling of asm constraints in MSan instrumentation.
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S | FileCheck -check-prefixes=CHECK,CHECK-NONCONS %s
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=1 -S | FileCheck -check-prefixes=CHECK,CHECK-CONS %s
; 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
; 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
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -40,9 +40,12 @@ entry:
; CHECK-LABEL: @f_1i_1o_reg
; CHECK: [[IS1_F1:%.*]] = load i32, i32* @is1, align 4
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning
; CHECK: call i32 asm "",{{.*}}(i32 [[IS1_F1]])
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
; CHECK: [[PACK1_F1:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
; CHECK: [[EXT1_F1:%.*]] = extractvalue { i8*, i32* } [[PACK1_F1]], 0
; CHECK: [[CAST1_F1:%.*]] = bitcast i8* [[EXT1_F1]] to i32*
; CHECK: store i32 0, i32* [[CAST1_F1]]
; Two input registers, two output registers:
@ -62,11 +65,17 @@ entry:
; CHECK-LABEL: @f_2i_2o_reg
; CHECK: [[IS1_F2:%.*]] = load i32, i32* @is1, align 4
; CHECK: [[IS2_F2:%.*]] = load i32, i32* @is2, align 4
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning
; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[IS1_F2]], i32 [[IS2_F2]])
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
; CHECK: [[PACK1_F2:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
; CHECK: [[EXT1_F2:%.*]] = extractvalue { i8*, i32* } [[PACK1_F2]], 0
; CHECK: [[CAST1_F2:%.*]] = bitcast i8* [[EXT1_F2]] to i32*
; CHECK: store i32 0, i32* [[CAST1_F2]]
; CHECK: [[PACK2_F2:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
; CHECK: [[EXT2_F2:%.*]] = extractvalue { i8*, i32* } [[PACK2_F2]], 0
; CHECK: [[CAST2_F2:%.*]] = bitcast i8* [[EXT2_F2]] to i32*
; CHECK: store i32 0, i32* [[CAST2_F2]]
; Input same as output, used twice:
; asm("" : "=r" (id1), "=r" (id2) : "r" (id1), "r" (id2));
@ -85,11 +94,17 @@ entry:
; CHECK-LABEL: @f_2i_2o_reuse2_reg
; CHECK: [[ID1_F3:%.*]] = load i32, i32* @id1, align 4
; CHECK: [[ID2_F3:%.*]] = load i32, i32* @id2, align 4
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning
; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[ID1_F3]], i32 [[ID2_F3]])
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
; CHECK: [[PACK1_F3:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
; CHECK: [[EXT1_F3:%.*]] = extractvalue { i8*, i32* } [[PACK1_F3]], 0
; CHECK: [[CAST1_F3:%.*]] = bitcast i8* [[EXT1_F3]] to i32*
; CHECK: store i32 0, i32* [[CAST1_F3]]
; CHECK: [[PACK2_F3:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
; CHECK: [[EXT2_F3:%.*]] = extractvalue { i8*, i32* } [[PACK2_F3]], 0
; CHECK: [[CAST2_F3:%.*]] = bitcast i8* [[EXT2_F3]] to i32*
; CHECK: store i32 0, i32* [[CAST2_F3]]
; One of the input registers is also an output:
@ -109,11 +124,17 @@ entry:
; CHECK-LABEL: @f_2i_2o_reuse1_reg
; CHECK: [[ID1_F4:%.*]] = load i32, i32* @id1, align 4
; CHECK: [[IS1_F4:%.*]] = load i32, i32* @is1, align 4
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning
; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[ID1_F4]], i32 [[IS1_F4]])
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
; CHECK: [[PACK1_F4:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
; CHECK: [[EXT1_F4:%.*]] = extractvalue { i8*, i32* } [[PACK1_F4]], 0
; CHECK: [[CAST1_F4:%.*]] = bitcast i8* [[EXT1_F4]] to i32*
; CHECK: store i32 0, i32* [[CAST1_F4]]
; CHECK: [[PACK2_F4:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
; CHECK: [[EXT2_F4:%.*]] = extractvalue { i8*, i32* } [[PACK2_F4]], 0
; CHECK: [[CAST2_F4:%.*]] = bitcast i8* [[EXT2_F4]] to i32*
; CHECK: store i32 0, i32* [[CAST2_F4]]
; One input register, three output registers:
@ -133,11 +154,20 @@ entry:
; CHECK-LABEL: @f_1i_3o_reg
; CHECK: [[IS1_F5:%.*]] = load i32, i32* @is1, align 4
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning
; CHECK: call { i32, i32, i32 } asm "",{{.*}}(i32 [[IS1_F5]])
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id1 to i64)
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id2 to i64)
; CHECK: store i32 0,{{.*}}ptrtoint (i32* @id3 to i64)
; CHECK: [[PACK1_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})
; CHECK: [[EXT1_F5:%.*]] = extractvalue { i8*, i32* } [[PACK1_F5]], 0
; CHECK: [[CAST1_F5:%.*]] = bitcast i8* [[EXT1_F5]] to i32*
; CHECK: store i32 0, i32* [[CAST1_F5]]
; CHECK: [[PACK2_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})
; CHECK: [[EXT2_F5:%.*]] = extractvalue { i8*, i32* } [[PACK2_F5]], 0
; CHECK: [[CAST2_F5:%.*]] = bitcast i8* [[EXT2_F5]] to i32*
; CHECK: store i32 0, i32* [[CAST2_F5]]
; CHECK: [[PACK3_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id3{{.*}})
; CHECK: [[EXT3_F5:%.*]] = extractvalue { i8*, i32* } [[PACK3_F5]], 0
; CHECK: [[CAST3_F5:%.*]] = bitcast i8* [[EXT3_F5]] to i32*
; CHECK: store i32 0, i32* [[CAST3_F5]]
; 2 input memory args, 2 output memory args:
@ -170,7 +200,7 @@ entry:
; CHECK: [[IS1_F7:%.*]] = load i32, i32* @is1, align 4
; CHECK-CONS: call void @__msan_instrument_asm_load({{.*}}@is1{{.*}}, i64 4)
; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@id1{{.*}}, i64 4)
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning
; CHECK: call i32 asm "", "=r,=*m,r,*m,~{dirflag},~{fpsr},~{flags}"(i32* @id1, i32 [[IS1_F7]], i32* @is1)
@ -212,9 +242,9 @@ entry:
; CHECK: [[C1_F9:%.*]] = load {{.*}} @c1
; CHECK: [[MEMCPY_S1_F9:%.*]] = load {{.*}} @memcpy_s1
; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@pair2{{.*}}, i64 8)
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning
; 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]])
; Three inputs and three outputs of different types: a pair, a char, a function pointer.

View File

@ -1,6 +1,6 @@
; Test for the conservative assembly handling mode used by KMSAN.
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S | FileCheck -check-prefixes=CHECK,CHECK-NONCONS %s
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-handle-asm-conservative=1 -S | FileCheck -check-prefixes=CHECK,CHECK-CONS %s
; 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
; 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
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -52,9 +52,16 @@ if.else: ; preds = %entry
ret i32 1
}
; %nr is first poisoned, then unpoisoned (written to). Need to optimize this in the future.
; CHECK: [[NRC1:%.*]] = bitcast i64* %nr to i8*
; CHECK: call void @__msan_poison_alloca(i8* [[NRC1]]{{.*}})
; CHECK: [[NRC2:%.*]] = bitcast i64* %nr to i8*
; CHECK: call { i8*, i32* } @__msan_metadata_ptr_for_store_8(i8* [[NRC2]])
; Hooks for inputs usually go before the assembly statement. But here we have none,
; because %nr is passed by value. However we check %nr for being initialized.
; CHECK-CONS: [[NRC:%.*]] = ptrtoint i64* %nr to i64
; CHECK-CONS: [[NRC3:%.*]] = bitcast i64* %nr to i8*
; CHECK-CONS: call { i8*, i32* } @__msan_metadata_ptr_for_load_8(i8* [[NRC3]])
; In the conservative mode, call the store hooks for %bit and %addr:
; CHECK-CONS: call void @__msan_instrument_asm_store(i8* %bit, i64 1)
@ -62,14 +69,17 @@ if.else: ; preds = %entry
; CHECK-CONS: call void @__msan_instrument_asm_store(i8* [[ADDR8S]], i64 8)
; Landing pad for the %nr check above.
; CHECK-CONS: call void @__msan_warning_noreturn()
; CHECK-CONS: call void @__msan_warning
; CHECK: call void asm "btsq $2, $1; setc $0"
; Calculating the shadow offset of %bit.
; CHECK: [[PTR:%.*]] = ptrtoint {{.*}} %bit to i64
; CHECK: [[SH_NUM:%.*]] = xor i64 [[PTR]]
; CHECK: [[SHADOW:%.*]] = inttoptr i64 [[SH_NUM]] {{.*}}
; CHECKz: [[PTR:%.*]] = ptrtoint {{.*}} %bit to i64
; CHECKz: [[SH_NUM:%.*]] = xor i64 [[PTR]]
; CHECKz: [[SHADOW:%.*]] = inttoptr i64 [[SH_NUM]] {{.*}}
; CHECK: [[META:%.*]] = call {{.*}} @__msan_metadata_ptr_for_load_1(i8* %bit)
; CHECK: [[SHADOW:%.*]] = extractvalue { i8*, i32* } [[META]], 0
; Now load the shadow value for the boolean.
; CHECK: [[MSLD:%.*]] = load {{.*}} [[SHADOW]]
@ -81,5 +91,5 @@ if.else: ; preds = %entry
; If yes, raise a warning.
; CHECK: <label>:[[IFTRUE]]
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning