1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10// REQUIRES: linux && target={{aarch64-.+}}
11// XFAIL: no-exceptions
12
13// This test ensures the .cfi_negate_ra_state the RA_SIGN_STATE pseudo register
14// could be set directly set by a DWARF expression and the unwinder handles it
15// correctly. The two directives can't be mixed in one CIE/FDE sqeuence.
16
17#include <stdlib.h>
18
19__attribute__((noinline, target("branch-protection=pac-ret+leaf")))
20void bar() {
21 // ".cfi_negate_ra_state" is emitted by the compiler.
22 throw 1;
23}
24
25__attribute__((noinline, target("branch-protection=none")))
26void foo() {
27 // Here a DWARF expression sets RA_SIGN_STATE.
28 // The LR is signed manually and stored on the stack.
29 asm volatile(
30 ".cfi_escape 0x16," // DW_CFA_val_expression
31 "34," // REG_34(RA_SIGN_STATE)
32 "1," // expression_length(1)
33 "0x31\n" // DW_OP_lit1
34 "add sp, sp, 16\n" // Restore SP's value before the stack frame is
35 // created.
36 "paciasp\n" // Sign the LR.
37 "str lr, [sp, -0x8]\n" // Overwrite LR on the stack.
38 "sub sp, sp, 16\n" // Restore SP's value.
39 );
40 bar();
41 _Exit(status: -1);
42}
43
44__attribute__((noinline, target("branch-protection=pac-ret")))
45void bazz() {
46 // ".cfi_negate_ra_state" is emitted by the compiler.
47 try {
48 foo();
49 } catch (int i) {
50 if (i == 1)
51 throw i;
52 throw 2;
53 }
54}
55
56int main() {
57 try {
58 bazz();
59 } catch (int i) {
60 if (i == 1)
61 _Exit(status: 0);
62 }
63 return -1;
64}
65

source code of libcxxabi/test/native/AArch64/ra_sign_state.pass.cpp