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:
  0x4000001f48: unexpected_handler() + 0x24
  0x4001972010: <unknown>
  0x4001972094: std::terminate() + 0x14
  0x40019723e4: __cxa_throw + 0x64
  0x4000001fdc: uncaught_function() + 0x30
  0x4000001ff8: main + 0x1c
  0x4001bfb230: <unknown>
  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.

Reply via email to