https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94515
Bug ID: 94515 Summary: aarch64: broken unwind information for pac-ret Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: nsz at gcc dot gnu.org Target Milestone: --- pac-ret uses the .cfi_window_save directive to toggle between signed/unsigned return address, alternatively .cfi_remember_state and .cfi_restore_state pair can be used to keep track of the "return address signedness" state. in some cases, when there are several return paths, gcc fails to generate the correct cfi directives for all return paths which can cause the unwinder not to authenticate a signed return address leading to a runtime crash on pauth enabled systems. example c++ test that segfaults (after fixing bug 94514 ): volatile int zero = 0; __attribute__((noinline)) void unwind (void) { if (zero == 0) throw 42; } __attribute__((noinline,noipa)) static int test (int z) { if (z) { asm volatile("":::"x20","x21"); unwind(); return 1; } else { unwind(); return 2; } } int main () { try { test (zero); __builtin_abort (); } catch (...) { return 0; } __builtin_abort (); } the test() function with -mbranch-protection=standard -O2 compiles to _ZL4testi: .LFB1: .cfi_startproc hint 25 // paciasp .cfi_window_save // pauth on stp x29, x30, [sp, -32]! .cfi_def_cfa_offset 32 .cfi_offset 29, -32 .cfi_offset 30, -24 mov x29, sp cbz w0, .L9 stp x20, x21, [sp, 16] .cfi_offset 21, -8 .cfi_offset 20, -16 bl _Z6unwindv mov w0, 1 ldp x20, x21, [sp, 16] .cfi_restore 21 .cfi_restore 20 ldp x29, x30, [sp], 32 .cfi_restore 30 .cfi_restore 29 .cfi_def_cfa_offset 0 hint 29 // autiasp .cfi_window_save // pauth off ret .p2align 2,,3 .L9: //// ret addr pauth state is wrong here ! .cfi_def_cfa_offset 32 .cfi_offset 29, -32 .cfi_offset 30, -24 bl _Z6unwindv ldp x29, x30, [sp], 32 .cfi_restore 30 .cfi_restore 29 .cfi_def_cfa_offset 0 hint 29 // autiasp .cfi_window_save mov w0, 2 ret .cfi_endproc .LFE1: .size _ZL4testi, .-_ZL4testi