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.