llvm-mirror/test/Instrumentation/MemorySanitizer/msan_x86_bts_asm.ll
Alexander Potapenko 35b6dc44d1 MSan: introduce the conservative assembly handling mode.
The default assembly handling mode may introduce false positives in the
cases when MSan doesn't understand that the assembly call initializes
the memory pointed to by one of its arguments.

We introduce the conservative mode, which initializes the first
|sizeof(type)| bytes for every |type*| pointer passed into the
assembly statement.

llvm-svn: 329054
2018-04-03 09:50:06 +00:00

84 lines
3.0 KiB
LLVM

; 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
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; The IR below was generated from the following source:
; int main() {
; bool bit;
; unsigned long value = 2;
; long nr = 0;
; unsigned long *addr = &value;
; asm("btsq %2, %1; setc %0" : "=qm" (bit), "=m" (addr): "Ir" (nr));
; if (bit)
; return 0
; else
; return 1;
; }
;
; In the regular instrumentation mode MSan is unable to understand that |bit|
; is initialized by the asm() call, and therefore reports a false positive on
; the if-statement.
; The conservative assembly handling mode initializes every memory location
; passed by pointer into an asm() call. This prevents false positive reports,
; but may introduce false negatives.
;
; This test makes sure that the conservative mode unpoisons the shadow of |bit|
; by writing 0 to it.
define dso_local i32 @main() sanitize_memory {
entry:
%retval = alloca i32, align 4
%bit = alloca i8, align 1
%value = alloca i64, align 8
%nr = alloca i64, align 8
%addr = alloca i64*, align 8
store i32 0, i32* %retval, align 4
store i64 2, i64* %value, align 8
store i64 0, i64* %nr, align 8
store i64* %value, i64** %addr, align 8
%0 = load i64, i64* %nr, align 8
call void asm "btsq $2, $1; setc $0", "=*qm,=*m,Ir,~{dirflag},~{fpsr},~{flags}"(i8* %bit, i64** %addr, i64 %0)
%1 = load i8, i8* %bit, align 1
%tobool = trunc i8 %1 to i1
br i1 %tobool, label %if.then, label %if.else
if.then: ; preds = %entry
ret i32 0
if.else: ; preds = %entry
ret i32 1
}
; Start with the asm call
; 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]], [[OFF:[0-9]*]]
; CHECK: [[SHADOW:%.*]] = inttoptr i64 [[SH_NUM]] {{.*}}
; In the conservative mode, unpoison the shadow.
; CHECK-CONS: store i8 0, i8* [[SHADOW]]
; Now calculate the shadow address again, because MSan does this for every
; shadow access.
; CHECK-CONS: [[PTR2:%.*]] = ptrtoint {{.*}} %bit to i64
; CHECK-CONS: [[SH_NUM2:%.*]] = xor i64 [[PTR2]], [[OFF]]
; CHECK-CONS: [[SHADOW2:%.*]] = inttoptr i64 [[SH_NUM2]] {{.*}}
; Now load the shadow value for the boolean.
; CHECK-NONCONS: [[MSLD:%.*]] = load {{.*}} [[SHADOW]]
; CHECK-CONS: [[MSLD:%.*]] = load {{.*}} [[SHADOW2]]
; CHECK: [[MSPROP:%.*]] = trunc i8 [[MSLD]] to i1
; Is the shadow poisoned?
; CHECK: [[MSCMP:%.*]] = icmp ne i1 [[MSPROP]], false
; CHECK: br i1 [[MSCMP]], label %[[IFTRUE:.*]], label {{.*}}
; If yes, raise a warning.
; CHECK: <label>:[[IFTRUE]]
; CHECK: call void @__msan_warning_noreturn()