Stack overflow checking with stack probes.

This adds a libcall name, a calling convention, and settings for
emitting stack probes, and implements them for x86 system_v ABIs.
This commit is contained in:
Dan Gohman
2018-04-20 21:41:45 -07:00
parent c5b15c2396
commit 3b1d805758
20 changed files with 585 additions and 155 deletions

View File

@@ -392,19 +392,37 @@ ebb0:
; asm: popl %ecx
[-,%rcx] v512 = x86_pop.i32 ; bin: 59
; Adjust Stack Pointer
; Adjust Stack Pointer Up
; asm: addl $64, %esp
adjust_sp_imm 64 ; bin: 83 c4 40
adjust_sp_up_imm 64 ; bin: 83 c4 40
; asm: addl $-64, %esp
adjust_sp_imm -64 ; bin: 83 c4 c0
adjust_sp_up_imm -64 ; bin: 83 c4 c0
; asm: addl $1024, %esp
adjust_sp_imm 1024 ; bin: 81 c4 00000400
adjust_sp_up_imm 1024 ; bin: 81 c4 00000400
; asm: addl $-1024, %esp
adjust_sp_imm -1024 ; bin: 81 c4 fffffc00
adjust_sp_up_imm -1024 ; bin: 81 c4 fffffc00
; asm: addl $2147483647, %esp
adjust_sp_imm 2147483647 ; bin: 81 c4 7fffffff
adjust_sp_up_imm 2147483647 ; bin: 81 c4 7fffffff
; asm: addl $-2147483648, %esp
adjust_sp_imm -2147483648 ; bin: 81 c4 80000000
adjust_sp_up_imm -2147483648 ; bin: 81 c4 80000000
; Adjust Stack Pointer Down
; asm: subl %ecx, %esp
adjust_sp_down v1 ; bin: 29 cc
; asm: subl %esi, %esp
adjust_sp_down v2 ; bin: 29 f4
; asm: addl $64, %esp
adjust_sp_down_imm 64 ; bin: 83 ec 40
; asm: addl $-64, %esp
adjust_sp_down_imm -64 ; bin: 83 ec c0
; asm: addl $1024, %esp
adjust_sp_down_imm 1024 ; bin: 81 ec 00000400
; asm: addl $-1024, %esp
adjust_sp_down_imm -1024 ; bin: 81 ec fffffc00
; asm: addl $2147483647, %esp
adjust_sp_down_imm 2147483647 ; bin: 81 ec 7fffffff
; asm: addl $-2147483648, %esp
adjust_sp_down_imm -2147483648 ; bin: 81 ec 80000000
; Shift immediates
; asm: shll $2, %esi

View File

@@ -547,19 +547,37 @@ ebb0:
; asm: popq %r10
[-,%r10] v514 = x86_pop.i64 ; bin: 41 5a
; Adjust Stack Pointer
; Adjust Stack Pointer Up
; asm: addq $64, %rsp
adjust_sp_imm 64 ; bin: 48 83 c4 40
adjust_sp_up_imm 64 ; bin: 48 83 c4 40
; asm: addq $-64, %rsp
adjust_sp_imm -64 ; bin: 48 83 c4 c0
adjust_sp_up_imm -64 ; bin: 48 83 c4 c0
; asm: addq $1024, %rsp
adjust_sp_imm 1024 ; bin: 48 81 c4 00000400
adjust_sp_up_imm 1024 ; bin: 48 81 c4 00000400
; asm: addq $-1024, %rsp
adjust_sp_imm -1024 ; bin: 48 81 c4 fffffc00
adjust_sp_up_imm -1024 ; bin: 48 81 c4 fffffc00
; asm: addq $2147483647, %rsp
adjust_sp_imm 2147483647 ; bin: 48 81 c4 7fffffff
adjust_sp_up_imm 2147483647 ; bin: 48 81 c4 7fffffff
; asm: addq $-2147483648, %rsp
adjust_sp_imm -2147483648 ; bin: 48 81 c4 80000000
adjust_sp_up_imm -2147483648 ; bin: 48 81 c4 80000000
; Adjust Stack Pointer Down
; asm: subq %rcx, %rsp
adjust_sp_down v1 ; bin: 48 29 cc
; asm: subq %r10, %rsp
adjust_sp_down v3 ; bin: 4c 29 d4
; asm: subq $64, %rsp
adjust_sp_down_imm 64 ; bin: 48 83 ec 40
; asm: subq $-64, %rsp
adjust_sp_down_imm -64 ; bin: 48 83 ec c0
; asm: subq $1024, %rsp
adjust_sp_down_imm 1024 ; bin: 48 81 ec 00000400
; asm: subq $-1024, %rsp
adjust_sp_down_imm -1024 ; bin: 48 81 ec fffffc00
; asm: subq $2147483647, %rsp
adjust_sp_down_imm 2147483647 ; bin: 48 81 ec 7fffffff
; asm: subq $-2147483648, %rsp
adjust_sp_down_imm -2147483648 ; bin: 48 81 ec 80000000
; Shift immediates
; asm: shlq $12, %rsi

View File

@@ -0,0 +1,29 @@
test compile
set is_64bit=1
set colocated_libcalls=1
set probestack_func_adjusts_sp=1
isa x86
; Like %big in probestack.cton, but with the probestack function adjusting
; the stack pointer itself.
function %big() system_v {
ss0 = explicit_slot 300000
ebb0:
return
}
; check: function %big(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 300000, offset -300016
; nextln: ss1 = incoming_arg 16, offset -16
; nextln: sig0 = (i64 [%rax]) probestack
; nextln: fn0 = colocated %Probestack sig0
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1pu_id#b8,%rax] v1 = iconst.i64 0x0004_93e0
; nextln: [Op1call_id#e8] call fn0(v1)
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 0x0004_93e0
; nextln: [RexOp1popq#58,%rbp] v2 = x86_pop.i64
; nextln: [Op1ret#c3] return v2
; nextln: }

View File

@@ -0,0 +1,25 @@
test compile
set is_64bit=1
set colocated_libcalls=1
set probestack_enabled=0
isa x86
; Like %big in probestack.cton, but with probes disabled.
function %big() system_v {
ss0 = explicit_slot 300000
ebb0:
return
}
; check: function %big(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 300000, offset -300016
; nextln: ss1 = incoming_arg 16, offset -16
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1adjustsp_id#d081] adjust_sp_down_imm 0x0004_93e0
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 0x0004_93e0
; nextln: [RexOp1popq#58,%rbp] v1 = x86_pop.i64
; nextln: [Op1ret#c3] return v1
; nextln: }

View File

@@ -0,0 +1,28 @@
test compile
set is_64bit=1
isa x86
; Like %big in probestack.cton, but without a colocated libcall.
function %big() system_v {
ss0 = explicit_slot 300000
ebb0:
return
}
; check: function %big(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 300000, offset -300016
; nextln: ss1 = incoming_arg 16, offset -16
; nextln: sig0 = (i64 [%rax]) -> i64 [%rax] probestack
; nextln: fn0 = %Probestack sig0
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1pu_id#b8,%rax] v1 = iconst.i64 0x0004_93e0
; nextln: [RexOp1fnaddr8#80b8,%r11] v2 = func_addr.i64 fn0
; nextln: [RexOp1call_r#20ff,%rax] v3 = call_indirect sig0, v2(v1)
; nextln: [RexOp1adjustsp#8029] adjust_sp_down v3
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 0x0004_93e0
; nextln: [RexOp1popq#58,%rbp] v4 = x86_pop.i64
; nextln: [Op1ret#c3] return v4
; nextln: }

View File

@@ -0,0 +1,75 @@
test compile
set is_64bit=1
set colocated_libcalls=1
set probestack_size_log2=13
isa x86
; Like %big in probestack.cton, but now the probestack size is bigger
; and it no longer needs a probe.
function %big() system_v {
ss0 = explicit_slot 4097
ebb0:
return
}
; check: function %big(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 4097, offset -4113
; nextln: ss1 = incoming_arg 16, offset -16
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1adjustsp_id#d081] adjust_sp_down_imm 4112
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 4112
; nextln: [RexOp1popq#58,%rbp] v1 = x86_pop.i64
; nextln: [Op1ret#c3] return v1
; nextln: }
; Like %big; still doesn't need a probe.
function %bigger() system_v {
ss0 = explicit_slot 8192
ebb0:
return
}
; check: function %bigger(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 8192, offset -8208
; nextln: ss1 = incoming_arg 16, offset -16
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1adjustsp_id#d081] adjust_sp_down_imm 8192
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 8192
; nextln: [RexOp1popq#58,%rbp] v1 = x86_pop.i64
; nextln: [Op1ret#c3] return v1
; nextln: }
; Like %bigger; this needs a probe.
function %biggest() system_v {
ss0 = explicit_slot 8193
ebb0:
return
}
; check: function %biggest(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 8193, offset -8209
; nextln: ss1 = incoming_arg 16, offset -16
; nextln: sig0 = (i64 [%rax]) -> i64 [%rax] probestack
; nextln: fn0 = colocated %Probestack sig0
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1pu_id#b8,%rax] v1 = iconst.i64 8208
; nextln: [Op1call_id#e8,%rax] v2 = call fn0(v1)
; nextln: [RexOp1adjustsp#8029] adjust_sp_down v2
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 8208
; nextln: [RexOp1popq#58,%rbp] v3 = x86_pop.i64
; nextln: [Op1ret#c3] return v3
; nextln: }

View File

@@ -0,0 +1,50 @@
test compile
set is_64bit=1
set colocated_libcalls=1
isa x86
; A function with a big stack frame. This should have a stack probe.
function %big() system_v {
ss0 = explicit_slot 4097
ebb0:
return
}
; check: function %big(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 4097, offset -4113
; nextln: ss1 = incoming_arg 16, offset -16
; nextln: sig0 = (i64 [%rax]) -> i64 [%rax] probestack
; nextln: fn0 = colocated %Probestack sig0
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1pu_id#b8,%rax] v1 = iconst.i64 4112
; nextln: [Op1call_id#e8,%rax] v2 = call fn0(v1)
; nextln: [RexOp1adjustsp#8029] adjust_sp_down v2
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 4112
; nextln: [RexOp1popq#58,%rbp] v3 = x86_pop.i64
; nextln: [Op1ret#c3] return v3
; nextln: }
; A function with a small enough stack frame. This shouldn't have a stack probe.
function %small() system_v {
ss0 = explicit_slot 4096
ebb0:
return
}
; check: function %small(i64 fp [%rbp]) -> i64 fp [%rbp] system_v {
; nextln: ss0 = explicit_slot 4096, offset -4112
; nextln: ss1 = incoming_arg 16, offset -16
; nextln:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: [RexOp1pushq#50] x86_push v0
; nextln: [RexOp1copysp#8089] copy_special %rsp -> %rbp
; nextln: [RexOp1adjustsp_id#d081] adjust_sp_down_imm 4096
; nextln: [RexOp1adjustsp_id#8081] adjust_sp_up_imm 4096
; nextln: [RexOp1popq#58,%rbp] v1 = x86_pop.i64
; nextln: [Op1ret#c3] return v1
; nextln: }

View File

@@ -36,8 +36,8 @@ ebb0:
; nextln: ebb0(v0: i64 [%rbp]):
; nextln: x86_push v0
; nextln: copy_special %rsp -> %rbp
; nextln: adjust_sp_imm -176
; nextln: adjust_sp_imm 176
; nextln: adjust_sp_down_imm 176
; nextln: adjust_sp_up_imm 176
; nextln: v1 = x86_pop.i64
; nextln: return v1
; nextln: }
@@ -109,7 +109,7 @@ ebb0(v0: i64, v1: i64):
; nextln: x86_push v18
; nextln: x86_push v19
; nextln: x86_push v20
; nextln: adjust_sp_imm -8
; nextln: adjust_sp_down_imm 8
; nextln: v2 = load.i32 v0
; nextln: v3 = load.i32 v0+8
; nextln: v4 = load.i32 v0+16
@@ -136,7 +136,7 @@ ebb0(v0: i64, v1: i64):
; nextln: store v12, v1+80
; nextln: store v13, v1+88
; nextln: store v14, v1+96
; nextln: adjust_sp_imm 8
; nextln: adjust_sp_up_imm 8
; nextln: v26 = x86_pop.i64
; nextln: v25 = x86_pop.i64
; nextln: v24 = x86_pop.i64
@@ -192,13 +192,13 @@ ebb0(v0: i64, v1: i64):
; nextln: x86_push v51
; nextln: x86_push v52
; nextln: x86_push v53
; nextln: adjust_sp_imm
; nextln: adjust_sp_down_imm
; check: spill
; check: fill
; check: adjust_sp_imm
; check: adjust_sp_up_imm
; nextln: v59 = x86_pop.i64
; nextln: v58 = x86_pop.i64
; nextln: v57 = x86_pop.i64