[Bug target/117941] Partial backtrace on C++ exception on ARM

2024-12-09 Thread m.othacehe at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117941

--- Comment #4 from Mathieu Othacehe  ---
(In reply to Richard Earnshaw from comment #3)
> The Arm unwind section tables are defined by the Arm EABI; they only provide
> enough data for call-based exceptions to be unwound.  It is not the same as
> the dwarf based tables and cannot support non-call exceptions.  Leaf
> functions are therefore always marked as can't unwind (this is necessary
> because the search algorithm for unwind data will just look for the latest
> entry in the table that is before the current PC value).  The data is not
> intended to permit arbitrary backtraces to be printed out.  The compressed
> tables can save significant amounts of space in the binary compared with the
> dwarf based tables; that's important in some embedded environments where all
> this data needs to be saved in flash on the device.
> 
> Performing a full backtrace from arbitrary code requires using dwarf unwind
> data (eg as produced with -g).

Thanks for your answer! Is it then possible to have dwarf data on ARM in
addition to the EABI defined unwind section? The backtrace program compiled
above has an almost empty .eh_frame section and no .eh_frame_hdr section:

$ arm-linux-gnueabihf-readelf -S a.out|grep eh_frame
  [18] .eh_frame PROGBITS000d8614 0c8614 04 00   A  0   0 
4
(4 bytes size)

[Bug target/117941] Partial backtrace on C++ exception on ARM

2024-12-27 Thread m.othacehe at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117941

--- Comment #6 from Mathieu Othacehe  ---
(In reply to Richard Earnshaw from comment #5)
> > Is it then possible to have dwarf data on ARM in addition to the EABI 
> > defined unwind section?
> 
> I don't know, honesty, because I've not tried it. I'd be surprised if it
> worked though, at least, not without hacking the linker scripts.  The dwarf
> data normally lives in the debug sections, which aren't loaded when the
> binary is executed (it's just available to a debugger).
> 
> The original version of the EABI specification did not support a frame
> chain, but this was added as an option in the recent versions.  This would
> enable a (nearly) complete backtrace of the call stack without needing other
> data (just access to the symbol table).  Sadly, however, this is yet to be
> implemented in gcc (the existing code doesn't correctly support thumb and
> certainly doesn't support Arm and thumb together in the same binary.

For the record, when using the .debug_frame section that is present on ARMv7
binaries, I am able to get full backtraces with libunwind:

Unexpected exception caught!
Backtrace:
  0x4b0c7d: unexpected_handler() + 0x1b
  0xb6dded55: __cxxabiv1::__terminate(void (*)()) + 0x3
  0xb6ddedb7: std::terminate() + 0x9
  0xb6ddf023: __cxa_rethrow + 0x2d
  0x4b0c61: uncaught_function() + 0x7
  0x4b0c9f: main + 0x11
  0xb6c317c7: __libc_start_call_main + 0x41
  0xb6c31871: __libc_start_main + 0x5f
  0x4b0901: _start + 0x27
Aborted

[Bug c++/117941] New: Partial backtrace on C++ exception on ARM

2024-12-06 Thread m.othacehe at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117941

Bug ID: 117941
   Summary: Partial backtrace on C++ exception on ARM
   Product: gcc
   Version: 15.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: m.othacehe at gmail dot com
  Target Milestone: ---

Created attachment 59806
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59806&action=edit
Backtrace program

When compiling and running the attached backtrace.cpp program with g++ built
from git (b3cb0c3), with libunwind built from git as well (73f1801), I have the
following result on x86_64:

Unexpected exception caught!
Backtrace:
  0x401465: unexpected_handler() + 0x18
  0x7f16440b0e6a: std::rethrow_exception(std::__exception_ptr::exception_ptr) +
0x7a
  0x7f16440b0ed5: std::terminate() + 0x15
  0x7f16440b1128: __cxa_throw + 0x48
  0x4014df: uncaught_function() + 0x27
  0x4014f2: main + 0x13
  0x7f1643e4bbf7: __libc_start_call_main + 0x67
  0x7f1643e4bcac: __libc_start_main + 0x7c
  0x4011b1: _start + 0x21

and a similar result on aarch64:

Unexpected exception caught!
Backtrace:
  0x401f48: unexpected_handler() + 0x24
  0x4001972010: 
  0x4001972094: std::terminate() + 0x14
  0x40019723e4: __cxa_throw + 0x64
  0x401fdc: uncaught_function() + 0x30
  0x401ff8: main + 0x1c
  0x4001bfb230: 
  0x4001bfb30c: __libc_start_main + 0x9c

However, on ARMv7, I have a partial backtrace:

Unexpected exception caught!
Backtrace:
  0x148b8: unexpected_handler() + 0x20
  0x2ddac: __cxxabiv1::__terminate(void (*)()) + 0x8
  0x12aa4: std::terminate() + 0xc

that does not allow me to find the source of the uncaught exception.
I can see that the std::terminate function has the 'cantunwind' flag in the
.ARM.exidx section, by running:

$ arm-linux-gnueabihf-readelf --unwind a.out
0x129e0 <_ZSt9terminatev>: 0x1 [cantunwind]

and that's what is preventing libunwind from unwinding further than
std::terminate:

  >_Uarm_arm_exidx_extract: 0x1 [can't unwind]
 >_Uarm_step: arm_exidx_step()=-5
(from the libunwind-log.txt attachment)

Out of curiosity, I have modified g++ so that it does not set that flag (see
the remove-unwind.patch attachment). The std::terminate function no longer has
the 'cantunwind' flag, but has no meaningful unwinding information either:

0x12a98 <_ZSt9terminatev>: 0x80b0b0b0
  Compact model index: 0
  0xb0  finish
  0xb0  finish
  0xb0  finish

which results in the same partial backtrace, but with an additional line:

Unexpected exception caught!
Backtrace:
  0x148b8: unexpected_handler() + 0x20
  0x2ddac: __cxxabiv1::__terminate(void (*)()) + 0x8
  0x12aa4: std::terminate() + 0xc
_Uarm_arm_exidx_step: ip and cfa unchanged; stopping here (ip=0x12aa4)

denoting that libunwind was still not able to unwind any further.

Would you see a way to allow unwinding from std::terminate on ARM, as it seems
to be possible on x86_64/aarch64, or is that an EHABI limitation?

Reproduction:
Configure and build libunwind this way:
mkdir build && ../configure --build=x86_64-linux-gnu --host=arm-linux-gnueabihf
--enable-cxx-exceptions --disable-minidebuginfo --disable-zlibdebuginfo
--enable-debug && make

Compile the backtrace program this way:
arm-linux-gnueabihf-g++ -g -O0 -fno-omit-frame-pointer -funwind-tables
-fexceptions -static-libstdc++ -D_GLIBCXX_ASSERTIONS backtrace.cpp -I include/
-I ../include/ src/.libs/libunwind.a src/.libs/libunwind-arm.a

Run the program this way:
QEMU_LD_PREFIX=/home/mathieu/arm_gcc/out/arm-linux-gnueabihf/ qemu-arm -E
UNW_DEBUG_LEVEL=100 -E UNW_ARM_UNWIND_METHOD=4 ./a.out
(remove -E UNW_DEBUG_LEVEL=100 to have the default verbosity)

Note that I first filed this bug in libunwind
(https://github.com/libunwind/libunwind/issues/814) before realizing that
without any suitable unwinding information for std::terminate, libunwind cannot
do anything.

[Bug c++/117941] Partial backtrace on C++ exception on ARM

2024-12-06 Thread m.othacehe at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117941

--- Comment #1 from Mathieu Othacehe  ---
Created attachment 59807
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59807&action=edit
Remove the cantunwind flag

[Bug c++/117941] Partial backtrace on C++ exception on ARM

2024-12-06 Thread m.othacehe at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117941

--- Comment #2 from Mathieu Othacehe  ---
Created attachment 59808
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59808&action=edit
libunwind full log