https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114843
Bug ID: 114843 Summary: AArch64: Wrong Register Reload in _Unwind_RaiseException causes corrupt return value on _URC_END_OF_STACK Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libgcc Assignee: unassigned at gcc dot gnu.org Reporter: hugo at algoriddim dot com Target Milestone: --- Created attachment 58034 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58034&action=edit Small test for reproduction When raising an Exception with `_Unwind_RaiseException` on Ubuntu 23.10 aarch64, instead of returning _URC_END_OF_STACK, the function returns the first argument previously passed to `_Unwind_RaisedException` as part of an (incorrect) reload. This happens with the Ubuntu GCC Version (13.2.0), Clang 18.1.0 Using libgcc_s, and the GCC version + libgcc_s build from master. ## Build GCC Version GCC Version: commit ca00bf02dcc37f9ff1028ca1d90e8b8d95d69683 (HEAD -> master, origin/trunk, origin/master, origin/HEAD) ```sh hmelder@ubuntu:~/gcc/objdir$ ./gcc/xgcc --version xgcc (GCC) 14.0.1 20240423 (experimental) Copyright (C) 2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ``` ```sh mkdir objdir cd objdir ../configure --enable-languages=c make all-gcc -j 12 make all-target-libgcc -j 12 ``` # Test See `ReproduceUnwindTest-main.i`. Test was compiled with the following flags: ```sh gcc -v -Wall -Wextra main.c -o ReproduceUnwindTest -save-temps ``` Expected: `Output RaiseException returned 0x5` (_URC_END_OF_STACK). This is the behaviour on FreeBSD with CompilerRT and libunwind and Darwin. Actual: Returns the first parameter passed to _Unwind_RaiseException because of a reload of spilled registers before returning _URC_END_OF_STACK in unwind.inc:108. # Diagnosis Here is the assembly of the `_Unwind_RaiseException` function. We are currently right after `if (code == _URC_END_OF_STACK)` in unwind.inc:108. The return value of `uw_frame_state_for` is 5 (_URC_END_OF_STACK). ```asm libgcc_s.so.1`_Unwind_RaiseException: 0xfffff7f27700 <+0>: sub sp, sp, #0xc10 0xfffff7f27704 <+4>: stp x29, x30, [sp] 0xfffff7f27708 <+8>: mov x29, sp 0xfffff7f2770c <+12>: xpaclri 0xfffff7f27710 <+16>: stp x21, x22, [sp, #0x40] 0xfffff7f27714 <+20>: add x22, sp, #0xc0 0xfffff7f27718 <+24>: add x21, sp, #0x840 0xfffff7f2771c <+28>: stp x0, x1, [sp, #0x10] 0xfffff7f27720 <+32>: add x1, sp, #0xc10 0xfffff7f27724 <+36>: stp x2, x3, [sp, #0x20] 0xfffff7f27728 <+40>: mov x2, x30 0xfffff7f2772c <+44>: stp x19, x20, [sp, #0x30] 0xfffff7f27730 <+48>: mov x20, x0 0xfffff7f27734 <+52>: add x19, sp, #0x480 0xfffff7f27738 <+56>: mov x0, x22 0xfffff7f2773c <+60>: stp x23, x24, [sp, #0x50] 0xfffff7f27740 <+64>: stp x25, x26, [sp, #0x60] 0xfffff7f27744 <+68>: stp x27, x28, [sp, #0x70] 0xfffff7f27748 <+72>: stp d8, d9, [sp, #0x80] 0xfffff7f2774c <+76>: stp d10, d11, [sp, #0x90] 0xfffff7f27750 <+80>: stp d12, d13, [sp, #0xa0] 0xfffff7f27754 <+84>: stp d14, d15, [sp, #0xb0] 0xfffff7f27758 <+88>: bl 0xfffff7f27020 ; uw_init_context_1 at unwind-dw2.c:1324:1 0xfffff7f2775c <+92>: mov x1, x22 0xfffff7f27760 <+96>: mov x0, x19 0xfffff7f27764 <+100>: mov x2, #0x3c0 ; =960 0xfffff7f27768 <+104>: bl 0xfffff7f13740 0xfffff7f2776c <+108>: b 0xfffff7f277a0 ; <+160> at unwind.inc:104:14 0xfffff7f27770 <+112>: cbnz w2, 0xfffff7f27814 ; <+276> at unwind.inc:113:9 0xfffff7f27774 <+116>: ldr x5, [sp, #0xbe0] 0xfffff7f27778 <+120>: cbz x5, 0xfffff7f27794 ; <+148> at unwind.inc:127:7 0xfffff7f2777c <+124>: ldr x2, [x20] 0xfffff7f27780 <+128>: blr x5 0xfffff7f27784 <+132>: cmp w0, #0x6 0xfffff7f27788 <+136>: b.eq 0xfffff7f2781c ; <+284> at unwind.inc:132:18 0xfffff7f2778c <+140>: cmp w0, #0x8 0xfffff7f27790 <+144>: b.ne 0xfffff7f27814 ; <+276> at unwind.inc:113:9 0xfffff7f27794 <+148>: mov x1, x21 0xfffff7f27798 <+152>: mov x0, x19 0xfffff7f2779c <+156>: bl 0xfffff7f27264 ; uw_update_context at unwind-dw2.c:1266:1 0xfffff7f277a0 <+160>: mov x1, x21 0xfffff7f277a4 <+164>: mov x0, x19 0xfffff7f277a8 <+168>: bl 0xfffff7f25f00 ; uw_frame_state_for at unwind-dw2.c:997:3 0xfffff7f277ac <+172>: mov w2, w0 0xfffff7f277b0 <+176>: mov w1, #0x1 ; =1 0xfffff7f277b4 <+180>: mov x4, x19 0xfffff7f277b8 <+184>: mov x3, x20 0xfffff7f277bc <+188>: mov w0, w1 0xfffff7f277c0 <+192>: cmp w2, #0x5 0xfffff7f277c4 <+196>: b.ne 0xfffff7f27770 ; <+112> at unwind.inc:110:10 -> 0xfffff7f277c8 <+200>: mov x4, #0x0 ; =0 0xfffff7f277cc <+204>: mov w0, w2 0xfffff7f277d0 <+208>: ldp x29, x30, [sp] 0xfffff7f277d4 <+212>: ldp x0, x1, [sp, #0x10] 0xfffff7f277d8 <+216>: ldp x2, x3, [sp, #0x20] 0xfffff7f277dc <+220>: ldp x19, x20, [sp, #0x30] 0xfffff7f277e0 <+224>: ldp x21, x22, [sp, #0x40] 0xfffff7f277e4 <+228>: ldp x23, x24, [sp, #0x50] 0xfffff7f277e8 <+232>: ldp x25, x26, [sp, #0x60] 0xfffff7f277ec <+236>: ldp x27, x28, [sp, #0x70] 0xfffff7f277f0 <+240>: ldp d8, d9, [sp, #0x80] 0xfffff7f277f4 <+244>: ldp d10, d11, [sp, #0x90] 0xfffff7f277f8 <+248>: ldp d12, d13, [sp, #0xa0] 0xfffff7f277fc <+252>: ldp d14, d15, [sp, #0xb0] 0xfffff7f27800 <+256>: add sp, sp, #0xc10 0xfffff7f27804 <+260>: cbz x4, 0xfffff7f27810 ; <+272> at unwind.inc:141:1 0xfffff7f27808 <+264>: add sp, sp, x5 0xfffff7f2780c <+268>: br x6 0xfffff7f27810 <+272>: ret 0xfffff7f27814 <+276>: mov w2, #0x3 ; =3 0xfffff7f27818 <+280>: b 0xfffff7f277c8 ; <+200> at unwind.inc:141:1 0xfffff7f2781c <+284>: str xzr, [x20, #0x10] 0xfffff7f27820 <+288>: mov x0, x19 0xfffff7f27824 <+292>: bl 0xfffff7f13860 ; symbol stub for: pthread_key_create 0xfffff7f27828 <+296>: mov x4, x0 0xfffff7f2782c <+300>: ldr x3, [sp, #0x7c0] 0xfffff7f27830 <+304>: mov x1, x22 0xfffff7f27834 <+308>: mov x2, #0x3c0 ; =960 0xfffff7f27838 <+312>: mov x0, x19 0xfffff7f2783c <+316>: sub x3, x4, x3, lsr #63 0xfffff7f27840 <+320>: str x3, [x20, #0x18] 0xfffff7f27844 <+324>: bl 0xfffff7f13740 0xfffff7f27848 <+328>: mov x2, x21 0xfffff7f2784c <+332>: mov x1, x19 0xfffff7f27850 <+336>: mov x0, x20 0xfffff7f27854 <+340>: bl 0xfffff7f273ac ; _Unwind_RaiseException_Phase2 at unwind.inc:41:1 0xfffff7f27858 <+344>: mov w2, #0x2 ; =2 0xfffff7f2785c <+348>: cmp w0, #0x7 0xfffff7f27860 <+352>: b.ne 0xfffff7f277c8 ; <+200> at unwind.inc:141:1 0xfffff7f27864 <+356>: mov x1, x19 0xfffff7f27868 <+360>: mov x0, x22 0xfffff7f2786c <+364>: bl 0xfffff7f24a60 ; uw_install_context_1 at unwind-dw2.c:1405:1 0xfffff7f27870 <+368>: mov x19, x0 0xfffff7f27874 <+372>: ldr x20, [sp, #0x798] 0xfffff7f27878 <+376>: ldr x0, [sp, #0x790] 0xfffff7f2787c <+380>: mov x1, x20 0xfffff7f27880 <+384>: bl 0xfffff7f276f0 ; _Unwind_DebugHook at unwind-dw2.c:1382:1 0xfffff7f27884 <+388>: bl 0xfffff7f2af40 ; __arm_za_disable 0xfffff7f27888 <+392>: mov x5, x19 0xfffff7f2788c <+396>: mov x6, x20 0xfffff7f27890 <+400>: mov x4, #0x1 ; =1 0xfffff7f27894 <+404>: b 0xfffff7f277cc ; <+204> at unwind.inc:141:1 ``` We write the return value from `uw_frame_state_for` which was moved into w2 at 0xfffff7f277ac into w0. # After mov w0, w2 (-> 0xfffff7f277d0 <+208>: ldp x29, x30, [sp]) 0xfffff7f27894 <+404>: b 0xfffff7f277cc ; <+204> at unwind.inc:141:1 (lldb) register read General Purpose Registers: x0 = 0x0000000000000005 x1 = 0x0000000000000001 x2 = 0x0000000000000005 x3 = 0x0000aaaaaaafa790 x4 = 0x0000000000000000 x5 = 0x0000ffffffffe160 x6 = 0xfffffffffffffff8 x7 = 0x0000000000000004 x8 = 0x0000000000000001 x9 = 0x0000fffff7f402a8 x10 = 0x0000000000000000 x11 = 0x0000fffff7f40308 x12 = 0x0000fffff7ff77c0 x13 = 0x0000000000000010 x14 = 0x0000000000000000 x15 = 0x0000fffff7bc63c0 x16 = 0x0000fffff7f40000 x17 = 0x0000000000000000 x18 = 0x0000000000000007 x19 = 0x0000ffffffffe610 x20 = 0x0000aaaaaaafa790 x21 = 0x0000ffffffffe9d0 x22 = 0x0000ffffffffe250 x23 = 0x0000ffffffffefc8 x24 = 0x0000fffff7ffdb90 ld-linux-aarch64.so.1`_rtld_global_ro x25 = 0x0000000000000000 x26 = 0x0000fffff7ffe008 _rtld_global x27 = 0x0000aaaaaaabfda0 UnexpectedExceptionDebug`__do_global_dtors_aux_fini_array_entry x28 = 0x0000000000000000 fp = 0x0000ffffffffe190 lr = 0x0000fffff7f277ac libgcc_s.so.1`_Unwind_RaiseException + 172 at unwind.inc:104:14 sp = 0x0000ffffffffe190 pc = 0x0000fffff7f277d0 libgcc_s.so.1`_Unwind_RaiseException + 208 at unwind.inc:141:1 cpsr = 0x60201000 However, we then continue to reload the register state from the function entry. # After ldp x0, x1 (lldb) register read General Purpose Registers: x0 = 0x0000aaaaaaafa790 x1 = 0x0000000000000000 x2 = 0x0000000000000058 x3 = 0x0000000000000000 x4 = 0x0000000000000000 x5 = 0x0000ffffffffe160 x6 = 0xfffffffffffffff8 x7 = 0x0000000000000004 x8 = 0x0000000000000001 x9 = 0x0000fffff7f402a8 x10 = 0x0000000000000000 x11 = 0x0000fffff7f40308 x12 = 0x0000fffff7ff77c0 x13 = 0x0000000000000010 x14 = 0x0000000000000000 x15 = 0x0000fffff7bc63c0 x16 = 0x0000fffff7f40000 x17 = 0x0000000000000000 x18 = 0x0000000000000007 x19 = 0x0000ffffffffefb8 x20 = 0x0000000000000001 x21 = 0x0000aaaaaaabfda0 UnexpectedExceptionDebug`__do_global_dtors_aux_fini_array_entry x22 = 0x0000aaaaaaaa0ae8 UnexpectedExceptionDebug`main at UnexpectedException.m:33 x23 = 0x0000ffffffffefc8 x24 = 0x0000fffff7ffdb90 ld-linux-aarch64.so.1`_rtld_global_ro x25 = 0x0000000000000000 x26 = 0x0000fffff7ffe008 _rtld_global x27 = 0x0000aaaaaaabfda0 UnexpectedExceptionDebug`__do_global_dtors_aux_fini_array_entry x28 = 0x0000000000000000 fp = 0x0000ffffffffee00 lr = 0x0000fffff7f76d38 libobjc.so.4.6`objc_exception_throw + 520 at eh_personality.c:256:22 sp = 0x0000ffffffffeda0 pc = 0x0000fffff7f27810 libgcc_s.so.1`_Unwind_RaiseException + 272 at unwind.inc:141:1 cpsr = 0x60201000 (lldb)