CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
1519 lines
60 KiB
ArmAsm
1519 lines
60 KiB
ArmAsm
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
|
|
// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf --auth-traps-on-failure %t.exe 2>&1 | FileCheck %s
|
|
// RUN: llvm-bolt-binary-analysis --scanners=ptrauth-forward-cf %t.exe 2>&1 | FileCheck %s
|
|
|
|
.text
|
|
|
|
.globl callee
|
|
.type callee,@function
|
|
callee:
|
|
ret
|
|
.size callee, .-callee
|
|
|
|
.globl good_direct_call
|
|
.type good_direct_call,@function
|
|
good_direct_call:
|
|
// CHECK-NOT: good_direct_call
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
bl callee
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_direct_call, .-good_direct_call
|
|
|
|
.globl good_indirect_call_arg
|
|
.type good_indirect_call_arg,@function
|
|
good_indirect_call_arg:
|
|
// CHECK-NOT: good_indirect_call_arg
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
autia x0, x1
|
|
blr x0
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_arg, .-good_indirect_call_arg
|
|
|
|
.globl good_indirect_call_mem
|
|
.type good_indirect_call_mem,@function
|
|
good_indirect_call_mem:
|
|
// CHECK-NOT: good_indirect_call_mem
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem, .-good_indirect_call_mem
|
|
|
|
.globl good_indirect_call_arg_v83
|
|
.type good_indirect_call_arg_v83,@function
|
|
good_indirect_call_arg_v83:
|
|
// CHECK-NOT: good_indirect_call_arg_v83
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
blraa x0, x1
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_arg_v83, .-good_indirect_call_arg_v83
|
|
|
|
.globl good_indirect_call_mem_v83
|
|
.type good_indirect_call_mem_v83,@function
|
|
good_indirect_call_mem_v83:
|
|
// CHECK-NOT: good_indirect_call_mem_v83
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
blraa x16, x0
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem_v83, .-good_indirect_call_mem_v83
|
|
|
|
.globl bad_indirect_call_arg
|
|
.type bad_indirect_call_arg,@function
|
|
bad_indirect_call_arg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
blr x0
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_arg, .-bad_indirect_call_arg
|
|
|
|
.globl bad_indirect_call_mem
|
|
.type bad_indirect_call_mem,@function
|
|
bad_indirect_call_mem:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: paciasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov x29, sp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autiasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ret
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem, .-bad_indirect_call_mem
|
|
|
|
.globl bad_indirect_call_arg_clobber
|
|
.type bad_indirect_call_arg_clobber,@function
|
|
bad_indirect_call_arg_clobber:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg_clobber, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w0, w2
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: paciasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov x29, sp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autia x0, x1
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov w0, w2
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autiasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ret
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
autia x0, x1
|
|
mov w0, w2
|
|
blr x0
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_arg_clobber, .-bad_indirect_call_arg_clobber
|
|
|
|
.globl bad_indirect_call_mem_clobber
|
|
.type bad_indirect_call_mem_clobber,@function
|
|
bad_indirect_call_mem_clobber:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_clobber, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w16, w2
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: paciasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov x29, sp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autia x16, x0
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov w16, w2
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autiasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ret
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
mov w16, w2
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_clobber, .-bad_indirect_call_mem_clobber
|
|
|
|
.globl good_indirect_call_mem_chain_of_auts
|
|
.type good_indirect_call_mem_chain_of_auts,@function
|
|
good_indirect_call_mem_chain_of_auts:
|
|
// CHECK-NOT: good_indirect_call_mem_chain_of_auts
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
autia x16, x0
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem_chain_of_auts, .-good_indirect_call_mem_chain_of_auts
|
|
|
|
.globl bad_indirect_call_mem_chain_of_auts
|
|
.type bad_indirect_call_mem_chain_of_auts,@function
|
|
bad_indirect_call_mem_chain_of_auts:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_chain_of_auts, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x16]
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: paciasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov x29, sp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autda x16, x1
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x16]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autiasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ret
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
// Missing AUT of x16. The fact that x16 was authenticated above has nothing to do with it.
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_chain_of_auts, .-bad_indirect_call_mem_chain_of_auts
|
|
|
|
// Multi-BB test cases.
|
|
//
|
|
// Positive ("good") test cases are designed so that the register is made safe
|
|
// in one BB and used in the other. Negative ("bad") ones are designed so that
|
|
// there are two predecessors, one of them ends with the register in a safe
|
|
// state and the other ends with that register being unsafe.
|
|
|
|
.globl good_indirect_call_arg_multi_bb
|
|
.type good_indirect_call_arg_multi_bb,@function
|
|
good_indirect_call_arg_multi_bb:
|
|
// CHECK-NOT: good_indirect_call_arg_multi_bb
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
autia x0, x1
|
|
cbz x2, 1f
|
|
blr x0
|
|
1:
|
|
ldr x1, [x0] // prevent authentication oracle
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_arg_multi_bb, .-good_indirect_call_arg_multi_bb
|
|
|
|
.globl good_indirect_call_mem_multi_bb
|
|
.type good_indirect_call_mem_multi_bb,@function
|
|
good_indirect_call_mem_multi_bb:
|
|
// CHECK-NOT: good_indirect_call_mem_multi_bb
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
cbz x2, 1f
|
|
blr x16
|
|
1:
|
|
ldr w0, [x16] // prevent authentication oracle
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem_multi_bb, .-good_indirect_call_mem_multi_bb
|
|
|
|
.globl bad_indirect_call_arg_multi_bb
|
|
.type bad_indirect_call_arg_multi_bb,@function
|
|
bad_indirect_call_arg_multi_bb:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg_multi_bb, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
cbz x2, 1f
|
|
autia x0, x1
|
|
1:
|
|
blr x0
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_arg_multi_bb, .-bad_indirect_call_arg_multi_bb
|
|
|
|
.globl bad_indirect_call_mem_multi_bb
|
|
.type bad_indirect_call_mem_multi_bb,@function
|
|
bad_indirect_call_mem_multi_bb:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_multi_bb, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
cbz x2, 1f
|
|
autia x16, x1
|
|
1:
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_multi_bb, .-bad_indirect_call_mem_multi_bb
|
|
|
|
.globl bad_indirect_call_arg_clobber_multi_bb
|
|
.type bad_indirect_call_arg_clobber_multi_bb,@function
|
|
bad_indirect_call_arg_clobber_multi_bb:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg_clobber_multi_bb, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w0, w3
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
autia x0, x1
|
|
cbz x2, 1f
|
|
mov w0, w3
|
|
1:
|
|
blr x0
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_arg_clobber_multi_bb, .-bad_indirect_call_arg_clobber_multi_bb
|
|
|
|
.globl bad_indirect_call_mem_clobber_multi_bb
|
|
.type bad_indirect_call_mem_clobber_multi_bb,@function
|
|
bad_indirect_call_mem_clobber_multi_bb:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_clobber_multi_bb, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w16, w2
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
cbz x2, 1f
|
|
mov w16, w2
|
|
1:
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_clobber_multi_bb, .-bad_indirect_call_mem_clobber_multi_bb
|
|
|
|
.globl good_indirect_call_mem_chain_of_auts_multi_bb
|
|
.type good_indirect_call_mem_chain_of_auts_multi_bb,@function
|
|
good_indirect_call_mem_chain_of_auts_multi_bb:
|
|
// CHECK-NOT: good_indirect_call_mem_chain_of_auts_multi_bb
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
autia x16, x0
|
|
cbz x2, 1f
|
|
blr x16
|
|
1:
|
|
ldr w0, [x16] // prevent authentication oracle
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem_chain_of_auts_multi_bb, .-good_indirect_call_mem_chain_of_auts_multi_bb
|
|
|
|
.globl bad_indirect_call_mem_chain_of_auts_multi_bb
|
|
.type bad_indirect_call_mem_chain_of_auts_multi_bb,@function
|
|
bad_indirect_call_mem_chain_of_auts_multi_bb:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_chain_of_auts_multi_bb, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x16]
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
cbz x2, 1f
|
|
autia x16, x0
|
|
1:
|
|
blr x16
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_chain_of_auts_multi_bb, .-bad_indirect_call_mem_chain_of_auts_multi_bb
|
|
|
|
// Tests for CFG-unaware analysis.
|
|
//
|
|
// All these tests use an instruction sequence like this
|
|
//
|
|
// adr x2, 1f
|
|
// br x2
|
|
// 1:
|
|
// ; ...
|
|
//
|
|
// to make BOLT unable to reconstruct the control flow. Note that one can easily
|
|
// tell whether the report corresponds to a function with or without CFG:
|
|
// normally, the location of the gadget is described like this:
|
|
//
|
|
// ... found in function <function_name>, basic block <basic block name>, at address <address>
|
|
//
|
|
// When CFG information is not available, this is reduced to
|
|
//
|
|
// ... found in function <function_name>, at address <address>
|
|
|
|
.globl good_direct_call_nocfg
|
|
.type good_direct_call_nocfg,@function
|
|
good_direct_call_nocfg:
|
|
// CHECK-NOT: good_direct_call_nocfg
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
bl callee
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_direct_call_nocfg, .-good_direct_call_nocfg
|
|
|
|
.globl good_indirect_call_arg_nocfg
|
|
.type good_indirect_call_arg_nocfg,@function
|
|
good_indirect_call_arg_nocfg:
|
|
// CHECK-NOT: good_indirect_call_arg_nocfg
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
autia x0, x1
|
|
blr x0
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_arg_nocfg, .-good_indirect_call_arg_nocfg
|
|
|
|
.globl good_indirect_call_mem_nocfg
|
|
.type good_indirect_call_mem_nocfg,@function
|
|
good_indirect_call_mem_nocfg:
|
|
// CHECK-NOT: good_indirect_call_mem_nocfg
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
blr x16
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem_nocfg, .-good_indirect_call_mem_nocfg
|
|
|
|
.globl good_indirect_call_arg_v83_nocfg
|
|
.type good_indirect_call_arg_v83_nocfg,@function
|
|
good_indirect_call_arg_v83_nocfg:
|
|
// CHECK-NOT: good_indirect_call_arg_v83_nocfg
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
blraa x0, x1
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_arg_v83_nocfg, .-good_indirect_call_arg_v83_nocfg
|
|
|
|
.globl good_indirect_call_mem_v83_nocfg
|
|
.type good_indirect_call_mem_v83_nocfg,@function
|
|
good_indirect_call_mem_v83_nocfg:
|
|
// CHECK-NOT: good_indirect_call_mem_v83_nocfg
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
blraa x16, x0
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem_v83_nocfg, .-good_indirect_call_mem_v83_nocfg
|
|
|
|
.globl bad_indirect_call_arg_nocfg
|
|
.type bad_indirect_call_arg_nocfg,@function
|
|
bad_indirect_call_arg_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
blr x0
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_arg_nocfg, .-bad_indirect_call_arg_nocfg
|
|
|
|
.globl obscure_indirect_call_arg_nocfg
|
|
.type obscure_indirect_call_arg_nocfg,@function
|
|
obscure_indirect_call_arg_nocfg:
|
|
// CHECK-NOCFG-LABEL: GS-PAUTH: non-protected call found in function obscure_indirect_call_arg_nocfg, at address
|
|
// CHECK-NOCFG-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NOCFG-NEXT: The 0 instructions that write to the affected registers after any authentication are:
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
autia x0, x1 // not observed by the checker
|
|
b 1f
|
|
1:
|
|
// The register state is pessimistically reset after a label, thus
|
|
// the below branch instruction is reported as non-protected - this is
|
|
// a known false-positive.
|
|
blr x0
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size obscure_good_indirect_call_arg_nocfg, .-obscure_good_indirect_call_arg_nocfg
|
|
|
|
.globl safe_lr_at_function_entry_nocfg
|
|
.type safe_lr_at_function_entry_nocfg,@function
|
|
safe_lr_at_function_entry_nocfg:
|
|
// Due to state being reset after a label, paciasp is reported as
|
|
// a signing oracle - this is a known false positive, ignore it.
|
|
// CHECK-NOT: non-protected call{{.*}}safe_lr_at_function_entry_nocfg
|
|
cbz x0, 1f
|
|
ret // LR is safe at the start of the function
|
|
1:
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
adr x2, 2f
|
|
br x2
|
|
2:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size safe_lr_at_function_entry_nocfg, .-safe_lr_at_function_entry_nocfg
|
|
|
|
.globl lr_is_never_unsafe_before_first_inst_nocfg
|
|
.type lr_is_never_unsafe_before_first_inst_nocfg,@function
|
|
// CHECK-NOT: lr_is_never_unsafe_before_first_inst_nocfg
|
|
lr_is_never_unsafe_before_first_inst_nocfg:
|
|
1:
|
|
// The register state is never reset before the first instruction of
|
|
// the function. This can lead to a known false-negative if LR is
|
|
// clobbered and then a jump to the very first instruction of the
|
|
// function is performed.
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
mov x30, x0
|
|
cbz x1, 1b
|
|
|
|
adr x2, 2f
|
|
br x2
|
|
2:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size lr_is_never_unsafe_before_first_inst_nocfg, .-lr_is_never_unsafe_before_first_inst_nocfg
|
|
|
|
.globl bad_indirect_call_mem_nocfg
|
|
.type bad_indirect_call_mem_nocfg,@function
|
|
bad_indirect_call_mem_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
blr x16
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_nocfg, .-bad_indirect_call_mem_nocfg
|
|
|
|
.globl bad_indirect_call_arg_clobber_nocfg
|
|
.type bad_indirect_call_arg_clobber_nocfg,@function
|
|
bad_indirect_call_arg_clobber_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg_clobber_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w0, w2
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
autia x0, x1
|
|
mov w0, w2
|
|
blr x0
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_arg_clobber_nocfg, .-bad_indirect_call_arg_clobber_nocfg
|
|
|
|
.globl bad_indirect_call_mem_clobber_nocfg
|
|
.type bad_indirect_call_mem_clobber_nocfg,@function
|
|
bad_indirect_call_mem_clobber_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_clobber_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w16, w2
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
mov w16, w2
|
|
blr x16
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_clobber_nocfg, .-bad_indirect_call_mem_clobber_nocfg
|
|
|
|
.globl good_indirect_call_mem_chain_of_auts_nocfg
|
|
.type good_indirect_call_mem_chain_of_auts_nocfg,@function
|
|
good_indirect_call_mem_chain_of_auts_nocfg:
|
|
// CHECK-NOT: good_indirect_call_mem_chain_of_auts_nocfg
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
autia x16, x0
|
|
blr x16
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_indirect_call_mem_chain_of_auts_nocfg, .-good_indirect_call_mem_chain_of_auts_nocfg
|
|
|
|
.globl bad_indirect_call_mem_chain_of_auts_nocfg
|
|
.type bad_indirect_call_mem_chain_of_auts_nocfg,@function
|
|
bad_indirect_call_mem_chain_of_auts_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_chain_of_auts_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x16]
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
// Missing AUT of x16. The fact that x16 was authenticated above has nothing to do with it.
|
|
blr x16
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_indirect_call_mem_chain_of_auts_nocfg, .-bad_indirect_call_mem_chain_of_auts_nocfg
|
|
|
|
// Test tail calls. To somewhat decrease the number of test cases and not
|
|
// duplicate all of the above, only implement "mem" variant of test cases and
|
|
// mostly test negative cases.
|
|
|
|
.globl good_direct_tailcall
|
|
.type good_direct_tailcall,@function
|
|
good_direct_tailcall:
|
|
// CHECK-NOT: good_direct_tailcall
|
|
b callee
|
|
.size good_direct_tailcall, .-good_direct_tailcall
|
|
|
|
.globl good_indirect_tailcall_mem
|
|
.type good_indirect_tailcall_mem,@function
|
|
good_indirect_tailcall_mem:
|
|
// CHECK-NOT: good_indirect_tailcall_mem
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
br x16
|
|
.size good_indirect_tailcall_mem, .-good_indirect_tailcall_mem
|
|
|
|
.globl good_indirect_tailcall_mem_v83
|
|
.type good_indirect_tailcall_mem_v83,@function
|
|
good_indirect_tailcall_mem_v83:
|
|
// CHECK-NOT: good_indirect_tailcall_mem_v83
|
|
ldr x16, [x0]
|
|
braa x16, x0
|
|
.size good_indirect_tailcall_mem_v83, .-good_indirect_tailcall_mem_v83
|
|
|
|
.globl bad_indirect_tailcall_mem
|
|
.type bad_indirect_tailcall_mem,@function
|
|
bad_indirect_tailcall_mem:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: br x16
|
|
ldr x16, [x0]
|
|
br x16
|
|
.size bad_indirect_tailcall_mem, .-bad_indirect_tailcall_mem
|
|
|
|
.globl bad_indirect_tailcall_mem_clobber
|
|
.type bad_indirect_tailcall_mem_clobber,@function
|
|
bad_indirect_tailcall_mem_clobber:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem_clobber, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w16, w2
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autia x16, x0
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov w16, w2
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: br x16
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
mov w16, w2
|
|
br x16
|
|
.size bad_indirect_tailcall_mem_clobber, .-bad_indirect_tailcall_mem_clobber
|
|
|
|
.globl bad_indirect_tailcall_mem_chain_of_auts
|
|
.type bad_indirect_tailcall_mem_chain_of_auts,@function
|
|
bad_indirect_tailcall_mem_chain_of_auts:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem_chain_of_auts, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x16]
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autda x16, x1
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x16]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: br x16
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
// Missing AUT of x16. The fact that x16 was authenticated above has nothing to do with it.
|
|
br x16
|
|
.size bad_indirect_tailcall_mem_chain_of_auts, .-bad_indirect_tailcall_mem_chain_of_auts
|
|
|
|
.globl bad_indirect_tailcall_mem_multi_bb
|
|
.type bad_indirect_tailcall_mem_multi_bb,@function
|
|
bad_indirect_tailcall_mem_multi_bb:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem_multi_bb, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
ldr x16, [x0]
|
|
cbz x2, 1f
|
|
autia x16, x1
|
|
1:
|
|
br x16
|
|
.size bad_indirect_tailcall_mem_multi_bb, .-bad_indirect_tailcall_mem_multi_bb
|
|
|
|
.globl bad_indirect_tailcall_mem_clobber_multi_bb
|
|
.type bad_indirect_tailcall_mem_clobber_multi_bb,@function
|
|
bad_indirect_tailcall_mem_clobber_multi_bb:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem_clobber_multi_bb, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w16, w2
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
cbz x2, 1f
|
|
mov w16, w2
|
|
1:
|
|
br x16
|
|
.size bad_indirect_tailcall_mem_clobber_multi_bb, .-bad_indirect_tailcall_mem_clobber_multi_bb
|
|
|
|
.globl good_direct_tailcall_nocfg
|
|
.type good_direct_tailcall_nocfg,@function
|
|
good_direct_tailcall_nocfg:
|
|
// CHECK-NOT: good_direct_tailcall_nocfg
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
b callee
|
|
.size good_direct_tailcall_nocfg, .-good_direct_tailcall_nocfg
|
|
|
|
.globl good_indirect_tailcall_mem_nocfg
|
|
.type good_indirect_tailcall_mem_nocfg,@function
|
|
good_indirect_tailcall_mem_nocfg:
|
|
// CHECK-NOT: good_indirect_tailcall_mem_nocfg
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
br x16
|
|
.size good_indirect_tailcall_mem_nocfg, .-good_indirect_tailcall_mem_nocfg
|
|
|
|
.globl good_indirect_tailcall_mem_v83_nocfg
|
|
.type good_indirect_tailcall_mem_v83_nocfg,@function
|
|
good_indirect_tailcall_mem_v83_nocfg:
|
|
// CHECK-NOT: good_indirect_tailcall_mem_v83_nocfg
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldr x16, [x0]
|
|
braa x16, x0
|
|
.size good_indirect_tailcall_mem_v83_nocfg, .-good_indirect_tailcall_mem_v83_nocfg
|
|
|
|
.globl bad_indirect_tailcall_mem_nocfg
|
|
.type bad_indirect_tailcall_mem_nocfg,@function
|
|
bad_indirect_tailcall_mem_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldr x16, [x0]
|
|
br x16
|
|
.size bad_indirect_tailcall_mem_nocfg, .-bad_indirect_tailcall_mem_nocfg
|
|
|
|
.globl bad_indirect_tailcall_mem_clobber_nocfg
|
|
.type bad_indirect_tailcall_mem_clobber_nocfg,@function
|
|
bad_indirect_tailcall_mem_clobber_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem_clobber_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w16, w2
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldr x16, [x0]
|
|
autia x16, x0
|
|
mov w16, w2
|
|
br x16
|
|
.size bad_indirect_tailcall_mem_clobber_nocfg, .-bad_indirect_tailcall_mem_clobber_nocfg
|
|
|
|
.globl bad_indirect_tailcall_mem_chain_of_auts_nocfg
|
|
.type bad_indirect_tailcall_mem_chain_of_auts_nocfg,@function
|
|
bad_indirect_tailcall_mem_chain_of_auts_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_tailcall_mem_chain_of_auts_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x16]
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldr x16, [x0]
|
|
autda x16, x1
|
|
ldr x16, [x16]
|
|
// Missing AUT of x16. The fact that x16 was authenticated above has nothing to do with it.
|
|
br x16
|
|
.size bad_indirect_tailcall_mem_chain_of_auts_nocfg, .-bad_indirect_tailcall_mem_chain_of_auts_nocfg
|
|
|
|
.globl state_is_reset_at_branch_destination_nocfg
|
|
.type state_is_reset_at_branch_destination_nocfg,@function
|
|
state_is_reset_at_branch_destination_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function state_is_reset_at_branch_destination_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
b 1f
|
|
autia x0, x1 // skipped
|
|
1:
|
|
blr x0
|
|
|
|
adr x2, 2f
|
|
br x2
|
|
2:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size state_is_reset_at_branch_destination_nocfg, .-state_is_reset_at_branch_destination_nocfg
|
|
|
|
// Test that calling a function is considered as invalidating safety of every
|
|
// register. Note that we only have to consider "returning" function calls
|
|
// (via branch-with-link), but both direct and indirect variants.
|
|
// Checking different registers:
|
|
// * x2 - function argument
|
|
// * x8 - indirect result location
|
|
// * x10 - temporary
|
|
// * x16 - intra-procedure-call scratch register
|
|
// * x18 - platform register
|
|
// * x20 - callee-saved register
|
|
|
|
.globl direct_call_invalidates_safety
|
|
.type direct_call_invalidates_safety,@function
|
|
direct_call_invalidates_safety:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x2
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x8
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x10
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x18
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x20
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
mov x2, x0
|
|
autiza x2
|
|
bl callee
|
|
blr x2
|
|
|
|
mov x8, x0
|
|
autiza x8
|
|
bl callee
|
|
blr x8
|
|
|
|
mov x10, x0
|
|
autiza x10
|
|
bl callee
|
|
blr x10
|
|
|
|
mov x16, x0
|
|
autiza x16
|
|
bl callee
|
|
blr x16
|
|
|
|
mov x18, x0
|
|
autiza x18
|
|
bl callee
|
|
blr x18
|
|
|
|
mov x20, x0
|
|
autiza x20
|
|
bl callee
|
|
blr x20
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size direct_call_invalidates_safety, .-direct_call_invalidates_safety
|
|
|
|
.globl indirect_call_invalidates_safety
|
|
.type indirect_call_invalidates_safety,@function
|
|
indirect_call_invalidates_safety:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x2
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x2
|
|
// Check that only one error is reported per pair of BLRs.
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x2
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x8
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x8
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x8
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x10
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x10
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x10
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x18
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x18
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x18
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x20
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x20
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x20
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
mov x2, x0
|
|
autiza x2
|
|
blr x2 // protected call, but makes x2 unsafe
|
|
blr x2 // unprotected call
|
|
|
|
mov x8, x0
|
|
autiza x8
|
|
blr x8 // protected call, but makes x8 unsafe
|
|
blr x8 // unprotected call
|
|
|
|
mov x10, x0
|
|
autiza x10
|
|
blr x10 // protected call, but makes x10 unsafe
|
|
blr x10 // unprotected call
|
|
|
|
mov x16, x0
|
|
autiza x16
|
|
blr x16 // protected call, but makes x16 unsafe
|
|
blr x16 // unprotected call
|
|
|
|
mov x18, x0
|
|
autiza x18
|
|
blr x18 // protected call, but makes x18 unsafe
|
|
blr x18 // unprotected call
|
|
|
|
mov x20, x0
|
|
autiza x20
|
|
blr x20 // protected call, but makes x20 unsafe
|
|
blr x20 // unprotected call
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size indirect_call_invalidates_safety, .-indirect_call_invalidates_safety
|
|
|
|
.globl direct_call_invalidates_safety_nocfg
|
|
.type direct_call_invalidates_safety_nocfg,@function
|
|
direct_call_invalidates_safety_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x2
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x8
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x10
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x18
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function direct_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x20
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl callee
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
mov x2, x0
|
|
autiza x2
|
|
bl callee
|
|
blr x2
|
|
|
|
mov x8, x0
|
|
autiza x8
|
|
bl callee
|
|
blr x8
|
|
|
|
mov x10, x0
|
|
autiza x10
|
|
bl callee
|
|
blr x10
|
|
|
|
mov x16, x0
|
|
autiza x16
|
|
bl callee
|
|
blr x16
|
|
|
|
mov x18, x0
|
|
autiza x18
|
|
bl callee
|
|
blr x18
|
|
|
|
mov x20, x0
|
|
autiza x20
|
|
bl callee
|
|
blr x20
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size direct_call_invalidates_safety_nocfg, .-direct_call_invalidates_safety_nocfg
|
|
|
|
.globl indirect_call_invalidates_safety_nocfg
|
|
.type indirect_call_invalidates_safety_nocfg,@function
|
|
indirect_call_invalidates_safety_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x2
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x2
|
|
// Check that only one error is reported per pair of BLRs.
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x2
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x8
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x8
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x8
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x10
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x10
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x10
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x18
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x18
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x18
|
|
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function indirect_call_invalidates_safety_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x20
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blr x20
|
|
// CHECK-NOT: The instruction is {{[0-9a-f]+}}: blr x20
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
mov x2, x0
|
|
autiza x2
|
|
blr x2 // protected call, but makes x2 unsafe
|
|
blr x2 // unprotected call
|
|
|
|
mov x8, x0
|
|
autiza x8
|
|
blr x8 // protected call, but makes x8 unsafe
|
|
blr x8 // unprotected call
|
|
|
|
mov x10, x0
|
|
autiza x10
|
|
blr x10 // protected call, but makes x10 unsafe
|
|
blr x10 // unprotected call
|
|
|
|
mov x16, x0
|
|
autiza x16
|
|
blr x16 // protected call, but makes x16 unsafe
|
|
blr x16 // unprotected call
|
|
|
|
mov x18, x0
|
|
autiza x18
|
|
blr x18 // protected call, but makes x18 unsafe
|
|
blr x18 // unprotected call
|
|
|
|
mov x20, x0
|
|
autiza x20
|
|
blr x20 // protected call, but makes x20 unsafe
|
|
blr x20 // unprotected call
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size indirect_call_invalidates_safety_nocfg, .-indirect_call_invalidates_safety_nocfg
|
|
|
|
// Test that fused auth+use Armv8.3 instruction do not mark register as safe.
|
|
|
|
.globl blraa_no_mark_safe
|
|
.type blraa_no_mark_safe,@function
|
|
blraa_no_mark_safe:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function blraa_no_mark_safe, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blraa x0, x1
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: paciasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov x29, sp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blraa x0, x1
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autiasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ret
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
blraa x0, x1 // safe, no write-back, clobbers everything
|
|
blr x0 // unsafe
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size blraa_no_mark_safe, .-blraa_no_mark_safe
|
|
|
|
.globl blraa_no_mark_safe_nocfg
|
|
.type blraa_no_mark_safe_nocfg,@function
|
|
blraa_no_mark_safe_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function blraa_no_mark_safe_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: blraa x0, x1
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
blraa x0, x1 // safe, no write-back, clobbers everything
|
|
blr x0 // detected as unsafe
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size blraa_no_mark_safe_nocfg, .-blraa_no_mark_safe_nocfg
|
|
|
|
// Check that the correct set of registers is used to compute the set of last
|
|
// writing instructions: both x16 and x17 are tracked in this function, but
|
|
// only one particular register is used to compute the set of clobbering
|
|
// instructions in each report.
|
|
|
|
.globl last_insts_writing_to_reg
|
|
.type last_insts_writing_to_reg,@function
|
|
last_insts_writing_to_reg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function last_insts_writing_to_reg, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: paciasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov x29, sp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x17, [x1]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x17
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autiasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ret
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function last_insts_writing_to_reg, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x17
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x17, [x1]
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: paciasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: mov x29, sp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x17, [x1]
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: blr x17
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: autiasp
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ret
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
blr x16
|
|
ldr x17, [x1]
|
|
blr x17
|
|
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size last_insts_writing_to_reg, .-last_insts_writing_to_reg
|
|
|
|
.globl last_insts_writing_to_reg_nocfg
|
|
.type last_insts_writing_to_reg_nocfg,@function
|
|
last_insts_writing_to_reg_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function last_insts_writing_to_reg_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function last_insts_writing_to_reg_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x17
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x17, [x1]
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
ldr x16, [x0]
|
|
blr x16
|
|
ldr x17, [x1]
|
|
blr x17
|
|
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size last_insts_writing_to_reg_nocfg, .-last_insts_writing_to_reg_nocfg
|
|
|
|
// Test that the instructions reported to the user are not cluttered with
|
|
// annotations attached by data-flow analysis or its CFG-unaware counterpart.
|
|
|
|
.globl printed_instrs_dataflow
|
|
.type printed_instrs_dataflow,@function
|
|
printed_instrs_dataflow:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function printed_instrs_dataflow, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x0 # TAILCALL{{ *$}}
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x0, [x0]{{ *$}}
|
|
// CHECK-NEXT: This happens in the following basic block:
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: ldr x0, [x0]{{ *$}}
|
|
// CHECK-NEXT: {{[0-9a-f]+}}: br x0 # TAILCALL{{ *$}}
|
|
ldr x0, [x0]
|
|
br x0
|
|
.size printed_instrs_dataflow, .-printed_instrs_dataflow
|
|
|
|
.globl printed_instrs_nocfg
|
|
.type printed_instrs_nocfg,@function
|
|
printed_instrs_nocfg:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function printed_instrs_nocfg, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: br x0 # UNKNOWN CONTROL FLOW # Offset: 12{{ *$}}
|
|
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x0, [x0]{{ *$}}
|
|
adr x2, 1f
|
|
br x2
|
|
1:
|
|
ldr x0, [x0]
|
|
br x0
|
|
.size printed_instrs_nocfg, .-printed_instrs_nocfg
|
|
|
|
// Test handling of unreachable basic blocks.
|
|
//
|
|
// Basic blocks without any predecessors were observed in real-world optimized
|
|
// code. At least sometimes they were actually reachable via jump table, which
|
|
// was not detected, but the function was processed as if its CFG was
|
|
// reconstructed successfully.
|
|
//
|
|
// As a more predictable model example, let's use really unreachable code
|
|
// for testing.
|
|
|
|
.globl bad_unreachable_call
|
|
.type bad_unreachable_call,@function
|
|
bad_unreachable_call:
|
|
// CHECK-LABEL: GS-PAUTH: Warning: possibly imprecise CFG, the analysis quality may be degraded in this function. According to BOLT, unreachable code is found in function bad_unreachable_call, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NOT: instructions that write to the affected registers after any authentication are:
|
|
// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_unreachable_call, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
b 1f
|
|
// unreachable basic block:
|
|
blr x0
|
|
|
|
1: // reachable basic block:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size bad_unreachable_call, .-bad_unreachable_call
|
|
|
|
.globl good_unreachable_call
|
|
.type good_unreachable_call,@function
|
|
good_unreachable_call:
|
|
// CHECK-NOT: non-protected call{{.*}}good_unreachable_call
|
|
// CHECK-LABEL: GS-PAUTH: Warning: possibly imprecise CFG, the analysis quality may be degraded in this function. According to BOLT, unreachable code is found in function good_unreachable_call, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: autia x0, x1
|
|
// CHECK-NOT: instructions that write to the affected registers after any authentication are:
|
|
// CHECK-NOT: non-protected call{{.*}}good_unreachable_call
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
b 1f
|
|
// unreachable basic block:
|
|
autia x0, x1
|
|
blr x0 // <-- this call is definitely protected provided at least
|
|
// basic block boundaries are detected correctly
|
|
|
|
1: // reachable basic block:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size good_unreachable_call, .-good_unreachable_call
|
|
|
|
.globl unreachable_loop_of_bbs
|
|
.type unreachable_loop_of_bbs,@function
|
|
unreachable_loop_of_bbs:
|
|
// CHECK-NOT: unreachable basic blocks{{.*}}unreachable_loop_of_bbs
|
|
// CHECK-NOT: non-protected call{{.*}}unreachable_loop_of_bbs
|
|
// CHECK-LABEL: GS-PAUTH: Warning: possibly imprecise CFG, the analysis quality may be degraded in this function. According to BOLT, unreachable code is found in function unreachable_loop_of_bbs, basic block {{[^,]+}}, at address
|
|
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
|
|
// CHECK-NOT: unreachable basic blocks{{.*}}unreachable_loop_of_bbs
|
|
// CHECK-NOT: non-protected call{{.*}}unreachable_loop_of_bbs
|
|
paciasp
|
|
stp x29, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
b .Lreachable_epilogue_bb
|
|
|
|
.Lfirst_unreachable_bb:
|
|
blr x0 // <-- this call is not analyzed
|
|
b .Lsecond_unreachable_bb
|
|
.Lsecond_unreachable_bb:
|
|
blr x1 // <-- this call is not analyzed
|
|
b .Lfirst_unreachable_bb
|
|
|
|
.Lreachable_epilogue_bb:
|
|
ldp x29, x30, [sp], #16
|
|
autiasp
|
|
ret
|
|
.size unreachable_loop_of_bbs, .-unreachable_loop_of_bbs
|
|
|
|
.globl main
|
|
.type main,@function
|
|
main:
|
|
mov x0, 0
|
|
ret
|
|
.size main, .-main
|