The PPA1 contains fields recording the length of the prolog and the offset to the instruction updating the stack pointer register. The implementation consists of the following parts: - the end of the prolog is marked with a FENCE instruction which prevents scheduling from moving instructions across the barrier. - when emitting the PPA1, the FENCE instruction along with other stack update instructions are used to calculate the length and the offset. Co-authored-by: Tony Tao <tonytao@ca.ibm.com>
162 lines
6.3 KiB
LLVM
162 lines
6.3 KiB
LLVM
; Test the stack protector under XPLINK on z/OS
|
|
;
|
|
; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z13 --verify-machineinstrs | FileCheck --check-prefixes=CHECK %s
|
|
|
|
; Test stack protector for non-XPLEAF.
|
|
|
|
; Small stack frame.
|
|
; CHECK-LABEL: func0
|
|
; CHECK: * DSA Size [[#%#x,DSA_SIZE:]]
|
|
; CHECK: aghi 4,-[[#%u,mul(div(DSA_SIZE,32),32)]]
|
|
; CHECK: llgt [[REG1:[0-9]+]],1208
|
|
; CHECK: mvc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,4),152([[REG1]])
|
|
; ...
|
|
; CHECK: llgt [[REG3:[0-9]+]],1208
|
|
; CHECK: clc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,4),152([[REG3]])
|
|
; CHECK: jlh [[FAIL_LABEL:L#BB[0-9_]+]]
|
|
; success block
|
|
; CHECK: aghi 4,[[#%u,mul(div(DSA_SIZE,32),32)]]
|
|
; CHECK: b 2(7)
|
|
; failure block
|
|
; CHECK: [[FAIL_LABEL]] DS 0H
|
|
; invoke __stack_chk_fail
|
|
; CHECK: lg 6,[[#CHK_FAIL_OFF:]]({{[0-9]+}})
|
|
; CHECK: lg 5,[[#CHK_FAIL_OFF-8]]({{[0-9]+}})
|
|
; CHECK: basr 7,6
|
|
; CHECK-NEXT: bcr 0,0
|
|
|
|
define void @func0() sspreq {
|
|
call i64 (i64) @fun(i64 10)
|
|
ret void
|
|
}
|
|
|
|
; Large stack frame.
|
|
; Larger than 1M in XPLINK64.
|
|
; CHECK-LABEL: func1
|
|
; CHECK: * DSA Size [[#%#x,DSA_SIZE:]]
|
|
; CHECK: stmg 6,{{[0-9]+}},2064(4)
|
|
; CHECK: llgt [[REG1:[0-9]+]],1208
|
|
; CHECK: llilh [[REG_CANARY_OFF_HIGH:[0-9]+]],[[#%u,CANARY_OFF_HIGH:div(DSA_SIZE,65536)]]
|
|
; CHECK: la [[REG_CANARY_OFF_HIGH]],0([[REG_CANARY_OFF_HIGH]],4)
|
|
; CHECK: mvc [[#%u,2040+mul(div(DSA_SIZE,32),32)-mul(CANARY_OFF_HIGH,65536)]](8,[[REG_CANARY_OFF_HIGH]]),152([[REG1]])
|
|
; ...
|
|
; CHECK: llgt [[REG3:[0-9]+]],1208
|
|
; CHECK: llilh [[REG_CANARY_OFF_HIGH_2:[0-9]+]],[[#%u,CANARY_OFF_HIGH_2:div(DSA_SIZE,65536)]]
|
|
; CHECK: la [[REG_CANARY_OFF_HIGH_2]],0([[REG_CANARY_OFF_HIGH_2]],4)
|
|
; CHECK: clc [[#%u,2040+mul(div(DSA_SIZE,32),32)-mul(CANARY_OFF_HIGH_2,65536)]](8,[[REG_CANARY_OFF_HIGH_2]]),152([[REG3]])
|
|
; CHECK: jlh [[FAIL_LABEL:L#BB[0-9_]+]]
|
|
; success block
|
|
; CHECK: agfi 4,[[#%u,mul(div(DSA_SIZE,32),32)]]
|
|
; CHECK: b 2(7)
|
|
; failure block
|
|
; CHECK: [[FAIL_LABEL]] DS 0H
|
|
; invoke __stack_chk_fail
|
|
; CHECK: lg 6,[[#CHK_FAIL_OFF:]]({{[0-9]+}})
|
|
; CHECK: lg 5,[[#CHK_FAIL_OFF-8]]({{[0-9]+}})
|
|
; CHECK: basr 7,6
|
|
; CHECK-NEXT: bcr 0,0
|
|
|
|
define void @func1() sspreq {
|
|
%arr = alloca [131072 x i64], align 8
|
|
call i64 (ptr) @fun1(ptr %arr)
|
|
ret void
|
|
}
|
|
|
|
; Test converting XPLeaf functions to non-leaf functions if they need stack protection
|
|
|
|
; Based on func3_64 in call-zos-03.ll
|
|
; CHECK-LABEL: func2_64
|
|
; CHECK: * Entry Flags
|
|
; CHECK-NEXT: * Bit 1: 0 = Non-leaf function
|
|
define i64 @func2_64(i64 %arg0) sspreq {
|
|
%out = add i64 %arg0, 55
|
|
ret i64 %out
|
|
}
|
|
|
|
; Based on func6 in zos-prologue-epilog.ll. R15 is callee-saved, so needs to be
|
|
; spilled to the stack before we use it. As a result this currently gets
|
|
; converted to a non-leaf function (even without sspreq).
|
|
; CHECK-LABEL: func3
|
|
; CHECK: * Entry Flags
|
|
; CHECK-NEXT: * Bit 1: 0 = Non-leaf function
|
|
define void @func3() local_unnamed_addr sspreq #0 {
|
|
entry:
|
|
tail call void asm sideeffect " lhi 15,1\0A", "~{r15}"()
|
|
ret void
|
|
}
|
|
|
|
; Test stack protector for function that uses alloca()
|
|
|
|
; CHECK-LABEL: func4
|
|
; CHECK: * DSA Size [[#%#x,DSA_SIZE:]]
|
|
; CHECK: * Entry Flags
|
|
; CHECK-NEXT: * Bit 1: 0 = Non-leaf function
|
|
; CHECK-NEXT: * Bit 2: 1 = Uses alloca
|
|
; CHECK: stmg 4,[[SPILLHI:[0-9]+]],[[#%u,2048-mul(div(DSA_SIZE,32),32)]](4)
|
|
; CHECK: aghi 4,-[[#%u,mul(div(DSA_SIZE,32),32)]]
|
|
; CHECK: lgr [[ALLOCAREG:[0-9]+]],4
|
|
; CHECK: llgt [[REG1:[0-9]+]],1208
|
|
; CHECK: mvc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,[[ALLOCAREG]]),152([[REG1]])
|
|
; ...
|
|
; CHECK: llgt [[REG3:[0-9]+]],1208
|
|
; CHECK: clc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,[[ALLOCAREG]]),152([[REG3]])
|
|
; CHECK: jlh [[FAIL_LABEL:L#BB[0-9_]+]]
|
|
; success block
|
|
; CHECK: lmg 4,[[SPILLHI]],2048(4)
|
|
; CHECK: b 2(7)
|
|
; failure block
|
|
; CHECK: [[FAIL_LABEL]] DS 0H
|
|
; invoke __stack_chk_fail
|
|
; CHECK: lg 6,[[#CHK_FAIL_OFF:]]({{[0-9]+}})
|
|
; CHECK: lg 5,[[#CHK_FAIL_OFF-8]]({{[0-9]+}})
|
|
; CHECK: basr 7,6
|
|
; CHECK-NEXT: bcr 0,0
|
|
|
|
define i64 @func4(i64 %n) sspreq {
|
|
%vla = alloca i64, i64 %n, align 8
|
|
%call = call i64 @fun2(i64 %n, ptr nonnull %vla, ptr nonnull %vla)
|
|
ret i64 %call
|
|
}
|
|
|
|
; Test stack protector off.
|
|
|
|
; CHECK-LABEL: func5
|
|
define void @func5() {
|
|
call i64 (i64) @fun(i64 10)
|
|
ret void
|
|
}
|
|
|
|
declare i64 @fun(i64 %arg0)
|
|
declare i64 @fun1(ptr %ptr)
|
|
declare i64 @fun2(i64 %n, ptr %arr0, ptr %arr1)
|
|
|
|
; CHECK-LABEL: L#PPA1_func0_0 DS 0H
|
|
; CHECK: * PPA1 Flags 2
|
|
; CHECK-NOT: * PPA1 Flags 3
|
|
; CHECK: * Bit 3: 1 = STACKPROTECT is enabled
|
|
|
|
; CHECK-LABEL: L#PPA1_func1_0 DS 0H
|
|
; CHECK: * PPA1 Flags 2
|
|
; CHECK-NOT: * PPA1 Flags 3
|
|
; CHECK: * Bit 3: 1 = STACKPROTECT is enabled
|
|
|
|
; CHECK-LABEL: L#PPA1_func2_64_0 DS 0H
|
|
; CHECK: * PPA1 Flags 2
|
|
; CHECK-NOT: * PPA1 Flags 3
|
|
; CHECK: * Bit 3: 1 = STACKPROTECT is enabled
|
|
|
|
; CHECK-LABEL: L#PPA1_func3_0 DS 0H
|
|
; CHECK: * PPA1 Flags 2
|
|
; CHECK-NOT: * PPA1 Flags 3
|
|
; CHECK: * Bit 3: 1 = STACKPROTECT is enabled
|
|
|
|
; CHECK-LABEL: L#PPA1_func4_0 DS 0H
|
|
; CHECK: * PPA1 Flags 2
|
|
; CHECK-NOT: * PPA1 Flags 3
|
|
; CHECK: * Bit 3: 1 = STACKPROTECT is enabled
|
|
|
|
; CHECK-LABEL: L#PPA1_func5_0 DS 0H
|
|
; CHECK: * PPA1 Flags 2
|
|
; CHECK-NOT: * PPA1 Flags 3
|
|
; CHECK: * Bit 3: 0 = STACKPROTECT is not enabled
|