2014-12-12 05:53:03 +08:00
|
|
|
; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca \
|
|
|
|
; RUN: -asan-use-after-return -S | FileCheck %s
|
2017-11-17 09:15:31 +08:00
|
|
|
; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca -asan-mapping-scale=5 \
|
|
|
|
; RUN: -asan-use-after-return -S | FileCheck %s
|
2014-12-12 05:53:03 +08:00
|
|
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
|
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
|
|
|
|
define void @Func1() sanitize_address {
|
|
|
|
entry:
|
|
|
|
; CHECK-LABEL: Func1
|
|
|
|
|
|
|
|
; CHECK: entry:
|
2015-02-28 05:17:42 +08:00
|
|
|
; CHECK: load i32, i32* @__asan_option_detect_stack_use_after_return
|
2014-12-12 05:53:03 +08:00
|
|
|
|
IR: Support parsing numeric block ids, and emit them in textual output.
Just as as llvm IR supports explicitly specifying numeric value ids
for instructions, and emits them by default in textual output, now do
the same for blocks.
This is a slightly incompatible change in the textual IR format.
Previously, llvm would parse numeric labels as string names. E.g.
define void @f() {
br label %"55"
55:
ret void
}
defined a label *named* "55", even without needing to be quoted, while
the reference required quoting. Now, if you intend a block label which
looks like a value number to be a name, you must quote it in the
definition too (e.g. `"55":`).
Previously, llvm would print nameless blocks only as a comment, and
would omit it if there was no predecessor. This could cause confusion
for readers of the IR, just as unnamed instructions did prior to the
addition of "%5 = " syntax, back in 2008 (PR2480).
Now, it will always print a label for an unnamed block, with the
exception of the entry block. (IMO it may be better to print it for
the entry-block as well. However, that requires updating many more
tests.)
Thus, the following is supported, and is the canonical printing:
define i32 @f(i32, i32) {
%3 = add i32 %0, %1
br label %4
4:
ret i32 %3
}
New test cases covering this behavior are added, and other tests
updated as required.
Differential Revision: https://reviews.llvm.org/D58548
llvm-svn: 356789
2019-03-23 02:27:13 +08:00
|
|
|
; CHECK: [[UAR_ENABLED_BB:^[0-9]+]]:
|
2014-12-12 05:53:03 +08:00
|
|
|
; CHECK: [[FAKE_STACK_RT:%[0-9]+]] = call i64 @__asan_stack_malloc_
|
|
|
|
|
IR: Support parsing numeric block ids, and emit them in textual output.
Just as as llvm IR supports explicitly specifying numeric value ids
for instructions, and emits them by default in textual output, now do
the same for blocks.
This is a slightly incompatible change in the textual IR format.
Previously, llvm would parse numeric labels as string names. E.g.
define void @f() {
br label %"55"
55:
ret void
}
defined a label *named* "55", even without needing to be quoted, while
the reference required quoting. Now, if you intend a block label which
looks like a value number to be a name, you must quote it in the
definition too (e.g. `"55":`).
Previously, llvm would print nameless blocks only as a comment, and
would omit it if there was no predecessor. This could cause confusion
for readers of the IR, just as unnamed instructions did prior to the
addition of "%5 = " syntax, back in 2008 (PR2480).
Now, it will always print a label for an unnamed block, with the
exception of the entry block. (IMO it may be better to print it for
the entry-block as well. However, that requires updating many more
tests.)
Thus, the following is supported, and is the canonical printing:
define i32 @f(i32, i32) {
%3 = add i32 %0, %1
br label %4
4:
ret i32 %3
}
New test cases covering this behavior are added, and other tests
updated as required.
Differential Revision: https://reviews.llvm.org/D58548
llvm-svn: 356789
2019-03-23 02:27:13 +08:00
|
|
|
; CHECK: [[FAKE_STACK_BB:^[0-9]+]]:
|
2014-12-12 05:53:03 +08:00
|
|
|
; CHECK: [[FAKE_STACK:%[0-9]+]] = phi i64 [ 0, %entry ], [ [[FAKE_STACK_RT]], %[[UAR_ENABLED_BB]] ]
|
|
|
|
; CHECK: icmp eq i64 [[FAKE_STACK]], 0
|
|
|
|
|
IR: Support parsing numeric block ids, and emit them in textual output.
Just as as llvm IR supports explicitly specifying numeric value ids
for instructions, and emits them by default in textual output, now do
the same for blocks.
This is a slightly incompatible change in the textual IR format.
Previously, llvm would parse numeric labels as string names. E.g.
define void @f() {
br label %"55"
55:
ret void
}
defined a label *named* "55", even without needing to be quoted, while
the reference required quoting. Now, if you intend a block label which
looks like a value number to be a name, you must quote it in the
definition too (e.g. `"55":`).
Previously, llvm would print nameless blocks only as a comment, and
would omit it if there was no predecessor. This could cause confusion
for readers of the IR, just as unnamed instructions did prior to the
addition of "%5 = " syntax, back in 2008 (PR2480).
Now, it will always print a label for an unnamed block, with the
exception of the entry block. (IMO it may be better to print it for
the entry-block as well. However, that requires updating many more
tests.)
Thus, the following is supported, and is the canonical printing:
define i32 @f(i32, i32) {
%3 = add i32 %0, %1
br label %4
4:
ret i32 %3
}
New test cases covering this behavior are added, and other tests
updated as required.
Differential Revision: https://reviews.llvm.org/D58548
llvm-svn: 356789
2019-03-23 02:27:13 +08:00
|
|
|
; CHECK: [[NO_FAKE_STACK_BB:^[0-9]+]]:
|
2014-12-12 05:53:03 +08:00
|
|
|
; CHECK: %MyAlloca = alloca i8, i64
|
|
|
|
; CHECK: [[ALLOCA:%[0-9]+]] = ptrtoint i8* %MyAlloca
|
|
|
|
|
|
|
|
; CHECK: phi i64 [ [[FAKE_STACK]], %[[FAKE_STACK_BB]] ], [ [[ALLOCA]], %[[NO_FAKE_STACK_BB]] ]
|
|
|
|
|
|
|
|
; CHECK: ret void
|
|
|
|
|
|
|
|
%XXX = alloca [20 x i8], align 1
|
2015-02-27 11:12:36 +08:00
|
|
|
%arr.ptr = bitcast [20 x i8]* %XXX to i8*
|
|
|
|
store volatile i8 0, i8* %arr.ptr
|
2014-12-12 05:53:03 +08:00
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; Test that dynamic alloca is not used for functions with inline assembly.
|
|
|
|
define void @Func2() sanitize_address {
|
|
|
|
entry:
|
|
|
|
; CHECK-LABEL: Func2
|
|
|
|
; CHECK: alloca [96 x i8]
|
|
|
|
; CHECK: ret void
|
|
|
|
|
|
|
|
%XXX = alloca [20 x i8], align 1
|
2015-02-27 11:12:36 +08:00
|
|
|
%arr.ptr = bitcast [20 x i8]* %XXX to i8*
|
|
|
|
store volatile i8 0, i8* %arr.ptr
|
2014-12-12 05:53:03 +08:00
|
|
|
call void asm sideeffect "mov %%rbx, %%rcx", "~{dirflag},~{fpsr},~{flags}"() nounwind
|
|
|
|
ret void
|
|
|
|
}
|
[ASan] Disable dynamic alloca and UAR detection in presence of returns_twice calls.
Summary:
returns_twice (most importantly, setjmp) functions are
optimization-hostile: if local variable is promoted to register, and is
changed between setjmp() and longjmp() calls, this update will be
undone. This is the reason why "man setjmp" advises to mark all these
locals as "volatile".
This can not be enough for ASan, though: when it replaces static alloca
with dynamic one, optionally called if UAR mode is enabled, it adds a
whole lot of SSA values, and computations of local variable addresses,
that can involve virtual registers, and cause unexpected behavior, when
these registers are restored from buffer saved in setjmp.
To fix this, just disable dynamic alloca and UAR tricks whenever we see
a returns_twice call in the function.
Reviewers: rnk
Subscribers: llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D11495
llvm-svn: 243561
2015-07-30 03:36:08 +08:00
|
|
|
|
|
|
|
; Test that dynamic alloca is not used when setjmp is present.
|
|
|
|
%struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t }
|
|
|
|
%struct.__sigset_t = type { [16 x i64] }
|
|
|
|
@_ZL3buf = internal global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 16
|
|
|
|
|
|
|
|
define void @Func3() uwtable sanitize_address {
|
|
|
|
; CHECK-LABEL: define void @Func3
|
|
|
|
; CHECK-NOT: __asan_option_detect_stack_use_after_return
|
|
|
|
; CHECK-NOT: __asan_stack_malloc
|
|
|
|
; CHECK: call void @__asan_handle_no_return
|
|
|
|
; CHECK: call void @longjmp
|
|
|
|
; CHECK: ret void
|
|
|
|
entry:
|
|
|
|
%a = alloca i32, align 4
|
|
|
|
%call = call i32 @_setjmp(%struct.__jmp_buf_tag* getelementptr inbounds ([1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* @_ZL3buf, i32 0, i32 0)) nounwind returns_twice
|
|
|
|
%cmp = icmp eq i32 0, %call
|
|
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then: ; preds = %entry
|
|
|
|
call void @longjmp(%struct.__jmp_buf_tag* getelementptr inbounds ([1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* @_ZL3buf, i32 0, i32 0), i32 1) noreturn nounwind
|
|
|
|
unreachable
|
|
|
|
|
|
|
|
if.end: ; preds = %entry
|
|
|
|
call void @_Z10escape_ptrPi(i32* %a)
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
declare i32 @_setjmp(%struct.__jmp_buf_tag*) nounwind returns_twice
|
|
|
|
declare void @longjmp(%struct.__jmp_buf_tag*, i32) noreturn nounwind
|
|
|
|
declare void @_Z10escape_ptrPi(i32*)
|