65 lines · cpp
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-exception7//8//===----------------------------------------------------------------------===//9 10// REQUIRES: linux && target={{aarch64-.+}}11// XFAIL: no-exceptions12 13// This test ensures the .cfi_negate_ra_state the RA_SIGN_STATE pseudo register14// could be set directly set by a DWARF expression and the unwinder handles it15// 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_expression31 "34," // REG_34(RA_SIGN_STATE)32 "1," // expression_length(1)33 "0x31\n" // DW_OP_lit134 "add sp, sp, 16\n" // Restore SP's value before the stack frame is35 // 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(-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(int, char**) {57 try {58 bazz();59 } catch (int i) {60 if (i == 1)61 _Exit(0);62 }63 return -1;64}65