#include <asm/unistd.h>
#define sa_sz 32
#define sa_flags 8
#define sa_handler 0
#define sa_mask_sz 8
#define si_code 8
#define SIGINT 2
#define SIGABRT 6
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGTERM 15
#define SEGV_CPERR 10
#define SA_NODEFER 1073741824
#define SA_SIGINFO 4
#define ucontext_regs 184
#define PR_SET_SHADOW_STACK_STATUS 75
# define PR_SHADOW_STACK_ENABLE (1UL << 0)
#define GCSPR_EL0 S3_3_C2_C5_1
.macro function name
.macro endfunction
.type \name, @function
.purgem endfunction
.endm
\name:
.endm
function putc
str x0, [sp, #-16]!
mov x0, #1
mov x1, sp
mov x2, #1
mov x8, #__NR_write
svc #0
add sp, sp, #16
ret
endfunction
.globl putc
function puts
mov x1, x0
mov x2, #0
0: ldrb w3, [x0], #1
cbz w3, 1f
add x2, x2, #1
b 0b
1: mov w0, #1
mov x8, #__NR_write
svc #0
ret
endfunction
.globl puts
.macro puts string
.pushsection .rodata.str1.1, "aMS", @progbits, 1
.L__puts_literal\@: .string "\string"
.popsection
ldr x0, =.L__puts_literal\@
bl puts
.endm
function putdec
mov x1, sp
str x30, [sp, #-32]!
mov x2, #0
strb w2, [x1, #-1]!
mov x2, #10
0: udiv x3, x0, x2
msub x0, x3, x2, x0
add w0, w0, #'0'
strb w0, [x1, #-1]!
mov x0, x3
cbnz x3, 0b
ldrb w0, [x1]
cbnz w0, 1f
mov w0, #'0'
strb w0, [x1, #-1]!
1: mov x0, x1
bl puts
ldr x30, [sp], #32
ret
endfunction
.globl putdec
function putdecn
mov x5, x30
bl putdec
mov x0, #'\n'
bl putc
ret x5
endfunction
.globl putdecn
function memclr
mov w2, #0
endfunction
.globl memclr
function memfill
cmp x1, #0
b.eq 1f
0: strb w2, [x0], #1
subs x1, x1, #1
b.ne 0b
1: ret
endfunction
.globl memfill
function setsignal
str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
mov w4, w0
mov x5, x1
mov w6, w2
add x0, sp, #16
mov x1, #sa_sz
bl memclr
mov w0, w4
add x1, sp, #16
str w6, [x1, #sa_flags]
str x5, [x1, #sa_handler]
mov x2, #0
mov x3, #sa_mask_sz
mov x8, #__NR_rt_sigaction
svc #0
cbz w0, 1f
puts "sigaction failure\n"
b abort
1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
ret
endfunction
function tickle_handler
ret
endfunction
function terminate_handler
mov w21, w0
mov x20, x2
puts "Terminated by signal "
mov w0, w21
bl putdec
puts ", no error\n"
mov x0, #0
mov x8, #__NR_exit
svc #0
endfunction
function segv_handler
mov x20, x1
mov x0, PR_SET_SHADOW_STACK_STATUS
mov x1, xzr
mov x2, xzr
mov x3, xzr
mov x4, xzr
mov x5, xzr
mov x8, #__NR_prctl
svc #0
puts "Got SIGSEGV code "
ldr x21, [x20, #si_code]
mov x0, x21
bl putdec
cmp x21, #SEGV_CPERR
bne 1f
puts " (GCS violation)"
1:
mov x0, '\n'
bl putc
b abort
endfunction
.macro recurse id
function recurse\id
stp x29, x30, [sp, #-16]!
mov x29, sp
cmp x20, 0
beq 1f
sub x20, x20, 1
bl recurse\id
1:
ldp x29, x30, [sp], #16
mov x8, #__NR_getpid
svc #0
ret
endfunction
.endm
recurse 1
recurse 2
.globl _start
function _start
mov x0, PR_SET_SHADOW_STACK_STATUS
mov x1, PR_SHADOW_STACK_ENABLE
mov x2, xzr
mov x3, xzr
mov x4, xzr
mov x5, xzr
mov x8, #__NR_prctl
svc #0
cbz x0, 1f
puts "Failed to enable GCS\n"
b abort
1:
mov w0, #SIGTERM
adr x1, terminate_handler
mov w2, #SA_SIGINFO
bl setsignal
mov w0, #SIGUSR1
adr x1, tickle_handler
mov w2, #SA_SIGINFO
orr w2, w2, #SA_NODEFER
bl setsignal
mov w0, #SIGSEGV
adr x1, segv_handler
mov w2, #SA_SIGINFO
orr w2, w2, #SA_NODEFER
bl setsignal
puts "Running\n"
loop:
mov x20, #5
bl recurse1
mov x20, #5
bl recurse2
b loop
endfunction
abort:
mov x0, #255
mov x8, #__NR_exit
svc #0