https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119610
Bug ID: 119610
Summary: aarch64: Wrong unwind info with
-fstack-clash-protection -fstack-protector-strong
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: acoplan at gcc dot gnu.org
Target Milestone: ---
The following fails:
$ cat t.cc
void foo() {
int c[1024*128];
throw 1;
}
int main()
{
try {
foo();
} catch(int x) {
return 0;
}
}
$ g++ t.cc -fstack-clash-protection -fstack-protector-strong
$ ./a.out
Segmentation fault
GDB shows us crashing in the unwinder at runtime:
(gdb) bt
#0 0x0000fffff7ee5ec4 in aarch64_fallback_frame_state (context=0xfffffff7e938,
fs=0xfffffff7ecf8) at ./md-unwind-support.h:74
#1 uw_frame_state_for (context=context@entry=0xfffffff7e938,
fs=fs@entry=0xfffffff7ecf8) at
/home/alecop01/toolchain/src/gcc/libgcc/unwind-dw2.c:1016
#2 0x0000fffff7ee73d8 in _Unwind_RaiseException (exc=0x424310) at
/home/alecop01/toolchain/src/gcc/libgcc/unwind.inc:104
#3 0x0000fffff7cb7174 in __cxxabiv1::__cxa_throw (obj=0x424330, tinfo=0x410d90
<typeinfo for int@CXXABI_1.3>, dest=<optimized out>) at
/home/alecop01/toolchain/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:93
#4 0x0000000000400a44 in foo() ()
#5 0xdcbbeb69daccf500 in ?? ()
compiling to an object file and looking at the codegen we have:
0000000000000000 <_Z3foov>:
0: a9bf7bfd stp x29, x30, [sp, #-16]!
4: 910003fd mov x29, sp
8: d14203ed sub x13, sp, #0x80, lsl #12
c: d14043ff sub sp, sp, #0x10, lsl #12
10: f90203ff str xzr, [sp, #1024]
14: eb2d63ff cmp sp, x13
18: 54ffffa1 b.ne c <_Z3foov+0xc> // b.any
1c: d10043ff sub sp, sp, #0x10
20: f90203ff str xzr, [sp, #1024]
24: 90000000 adrp x0, 0 <__stack_chk_guard>
28: 91000000 add x0, x0, #0x0
2c: 914203e1 add x1, sp, #0x80, lsl #12
30: f9400002 ldr x2, [x0]
34: f9000422 str x2, [x1, #8]
38: d2800002 mov x2, #0x0 // #0
3c: d2800080 mov x0, #0x4 // #4
40: 94000000 bl 0 <__cxa_allocate_exception>
44: 52800021 mov w1, #0x1 // #1
48: b9000001 str w1, [x0]
4c: 90000001 adrp x1, 0 <__stack_chk_guard>
50: 91000021 add x1, x1, #0x0
54: 914203e3 add x3, sp, #0x80, lsl #12
58: f9400464 ldr x4, [x3, #8]
5c: f9400022 ldr x2, [x1]
60: eb020084 subs x4, x4, x2
64: d2800002 mov x2, #0x0 // #0
68: 54000040 b.eq 70 <_Z3foov+0x70> // b.none
6c: 94000000 bl 0 <__stack_chk_fail>
70: d2800002 mov x2, #0x0 // #0
74: 90000001 adrp x1, 0 <_ZTIi>
78: 91000021 add x1, x1, #0x0
7c: 94000000 bl 0 <__cxa_throw>
and readelf -w shows the following DWARF for this function:
00000014 0000000000000024 00000018 FDE cie=00000000
pc=0000000000000000..0000000000000080
DW_CFA_advance_loc: 4 to 0000000000000004
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r29 (x29) at cfa-16
DW_CFA_offset: r30 (x30) at cfa-8
DW_CFA_advance_loc: 8 to 000000000000000c
DW_CFA_def_cfa: r13 (x13) ofs 524288
DW_CFA_advance_loc: 16 to 000000000000001c
DW_CFA_def_cfa_register: r31 (sp)
DW_CFA_advance_loc: 4 to 0000000000000020
DW_CFA_def_cfa_offset: 524304
DW_CFA_nop
DW_CFA_nop
so after the first stp insn we have:
DW_CFA_def_cfa_offset: 16
which tells us the CFA is the value of the sp on entry to the function. Things
get more interesting with:
DW_CFA_advance_loc: 8 to 000000000000000c
DW_CFA_def_cfa: r13 (x13) ofs 524288
This tells us that at foo+0xc, we should have:
x13 + 524288 == CFA,
but looking at the generated code, we actually have:
x13 + 524288 == CFA - 16
since x13 is computed with:
8: d14203ed sub x13, sp, #0x80, lsl #12
i.e. x13 = sp - 524288. But at this point we should have:
sp + 16 == CFA
due to the initial adjustment from the stp. Hence the unwind info is
inconsistent.
Looking at the generated code with:
$ g++ -fstack-protector-strong -fstack-clash-protection t.cc -c -S -o -
_Z3foov:
.LFB0:
.cfi_startproc
stp x29, x30, [sp, -16]!
.cfi_def_cfa_offset 16
.cfi_offset 29, -16
.cfi_offset 30, -8
mov x29, sp
sub x13, sp, #524288
.cfi_def_cfa 13, 524288 // shouldn't this be 524304?
This seems to reproduce with at least GCC 14 and trunk.