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.

Reply via email to