AW: [PATCH] eh_personality.cc: unwinding on ARM
> -Ursprüngliche Nachricht- > Von: Andrew Stubbs [mailto:a...@codesourcery.com] > Gesendet: Montag, 19. März 2012 17:12 > An: EXTERNAL Waechtler Peter (Fa. TCP, CM-AI/PJ-CF31) > Cc: gcc-patches@gcc.gnu.org; libstd...@gcc.gnu.org; > p...@codesourcery.com; pwaecht...@mac.com; d...@false.org > Betreff: Re: [PATCH] eh_personality.cc: unwinding on ARM > > On 16/03/12 13:29, EXTERNAL Waechtler Peter (Fa. TCP, > CM-AI/PJ-CF31) wrote: > > The CodeSourcery toolchain contains a "fix" like the following, > > please consider for adding it. > > Here's the full original patch with ChangeLog. > > I don't know why Dan never submitted this one. Perhaps it's > not suitable > for upstream or not considered the correct fix? > > Anyway, as far as copyright goes, I don't believe > CodeSourcery has any > problem with this being committed. > And here is a stub for a test case. I don't know how to run the testsuite, just put in include and VERIFY-thingie #include #include #include #include #include #include #include using namespace std; static void abort_handler(int n_signal, siginfo_t *siginfo, void *ptr); static void abort_handler(int n_signal, siginfo_t *siginfo, void *ptr) { void *address[20]; int depth; depth = backtrace(address, sizeof(address)/sizeof(void*)); backtrace_symbols_fd(address, depth, 0); /* this is a dumb check, better look for main */ if (depth == sizeof(address)/sizeof(void*)) cerr << "failed" << endl; else cerr << "passed" << endl; } int tst_eh01(void) { int rc = 0; std::vector v(10); rc = v.at(42); return rc; } int main(int argc, char *argv[]) { int c; struct sigaction sa; memset(&sa, 0 , sizeof(sa)); sa.sa_sigaction = abort_handler; sa.sa_flags = SA_SIGINFO; sigaction(SIGABRT, &sa, NULL); c = tst_eh01(); return c; } With a fixed CodeSourcery version: cs-minimal-sysroot/usr/lib/bin/sysroot-qemu src/bt/tst-eh01 terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check src/bt/tst-eh01[0x9654] cs-minimal-sysroot/usr/lib/bin/../../../lib/libc.so.6(__default_rt_sa_restorer_v1+0x0)[0x40a06ce0] cs-minimal-sysroot/usr/lib/bin/../../../lib/libc.so.6(gsignal+0x40)[0x40a059bc] cs-minimal-sysroot/usr/lib/bin/../../../lib/libc.so.6(abort+0x1d4)[0x40a0acec] cs-minimal-sysroot/usr/lib/bin/../../../usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x110)[0x408e5f4c] cs-minimal-sysroot/usr/lib/bin/../../../usr/lib/libstdc++.so.6(+0xa707c)[0x408e407c] cs-minimal-sysroot/usr/lib/bin/../../../usr/lib/libstdc++.so.6(_ZSt9terminatev+0x1c)[0x408e40a4] cs-minimal-sysroot/usr/lib/bin/../../../usr/lib/libstdc++.so.6(__cxa_throw+0x9c)[0x408e4220] cs-minimal-sysroot/usr/lib/bin/../../../usr/lib/libstdc++.so.6(_ZSt20__throw_out_of_rangePKc+0x64)[0x4088dc04] src/bt/tst-eh01(_ZNKSt6vectorIiSaIiEE14_M_range_checkEj+0x44)[0x9c24] src/bt/tst-eh01(_ZNSt6vectorIiSaIiEE2atEj+0x20)[0x99a8] src/bt/tst-eh01(_Z8tst_eh01v+0x5c)[0x972c] src/bt/tst-eh01(main+0x50)[0x97c8] cs-minimal-sysroot/usr/lib/bin/../../../lib/libc.so.6(__libc_start_main+0x114)[0x409ee754] passed qemu: uncaught target signal 6 (Aborted) - core dumped Aborted with an unfixed version: $ ./tst-eh01 terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check ./tst-eh01[0x9580] /lib/libc.so.6(__default_rt_sa_restorer_v2+0x0)[0x4c883770] /lib/libc.so.6(gsignal+0x40)[0x4c88241c] /lib/libc.so.6(abort+0x1c0)[0x4c88680c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] /lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x134)[0x4cb2ca0c] failed Aborted
Re: AW: [PATCH] eh_personality.cc: unwinding on ARM
On 19.03.2012 18:32, Paul Brook wrote: while I have your attention: what is an virtual unwind frame? ;) No such thing exists. Throwing an exception is a muti-stage process. It requires unwinding the stack frame twice, taking different actions in the process. "Forced" unwinding and backtracing add extra complications. The _US_* flags tell the PR which stage in the process we're at. IIRC the ARM EABI doesn't officially include forced unwinding, it's something we had to bolt on afterwards. For added fun the ARM EABI defines the set of states/actions somewhat differently to the DWARF unwinder. Forced unwinding is one of the warts that come from interaction between C++ and POSIX. Almost noone really understands how all these bits fit together. Thanx Paul, that one gave me a good laugh. :)) I worked several months (not full-time, only every now and then) to nail this loop down. It's definitely a fix for upstream - saving the sanity of some souls. Peter
Re: AW: [PATCH] eh_personality.cc: unwinding on ARM
> while I have your attention: what is an virtual unwind frame? ;) No such thing exists. Throwing an exception is a muti-stage process. It requires unwinding the stack frame twice, taking different actions in the process. "Forced" unwinding and backtracing add extra complications. The _US_* flags tell the PR which stage in the process we're at. IIRC the ARM EABI doesn't officially include forced unwinding, it's something we had to bolt on afterwards. For added fun the ARM EABI defines the set of states/actions somewhat differently to the DWARF unwinder. Forced unwinding is one of the warts that come from interaction between C++ and POSIX. Almost noone really understands how all these bits fit together. Paul
AW: [PATCH] eh_personality.cc: unwinding on ARM
> On Mon, Mar 19, 2012 at 12:12 PM, Andrew Stubbs > wrote: > > On 16/03/12 13:29, EXTERNAL Waechtler Peter (Fa. TCP, > CM-AI/PJ-CF31) wrote: > >> > >> The CodeSourcery toolchain contains a "fix" like the following, > >> please consider for adding it. > > > > > > Here's the full original patch with ChangeLog. > > > > I don't know why Dan never submitted this one. Perhaps it's > not suitable for > > upstream or not considered the correct fix? > > I think it was just a pain to write a test for. > Gentlemen, while I have your attention: what is an virtual unwind frame? ;) One test case is quite simple: std::vector v(10); rc = v.at(42); The versions of glibc and libstdc++ looks quite old, but montavista patches them up (but if the customer insists on such an old version...) So this is the unwind entry by readelf -u : 0xa518 <_Z6nqueenPiii>: @0x10c88 Personality routine: 0xa33c <__gxx_personality_v0@@CXXABI_1.3> 0x9b vsp = r11 0x42 vsp = vsp - 12 0x84 0x83 pop {r4, r5, r11, r14} 0xb0 finish 0xb0 finish 0xb0 finish no better output for libstdc++ 0xaa1b0 <__gxx_personality_v0>: @0xbd0f4 Personality routine: 0x3dd10 <_init+0xc8c> 0xad1f0 <_ZN9__gnu_cxx27__verbose_terminate_handlerEv>: @0xbd364 Personality routine: 0x3dd10 <_init+0xc8c> So far, I think if the personality routine is called _and_ there is something like __gnu_cxx::__verbose_terminate_handler on the stack (with attribute noreturn) it enters the loop. Perhaps a function that "noreturn"s has a virtual unwind frame - i.e. no unwind entry exists? Peter # ./eh -V Starting up terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check sigaction_func:(6, info:0x4dc98, context:0x4dd18) si_code: -6 eh_stack_unwind: enter eh_stack_unwind: after backtrace: used_pointers: 100 (asm: 0) ** EXCEPTION in process PID=2614 *** signal "Aborted" command line : "./eh" thread ./eh (TID 2614) == registers : TRAP_NO = 0x, ERROR_CODE = 0x, OLDMASK =0x R0 = 0x, R1 = 0x0a36, R2 = 0x0006, R3 = 0x2aab5460 R4 = 0x0a36, R5 = 0x0006, R6 = 0x4c97f000, R7 = 0x010c R8 = 0x2aab4fc0, R9 = 0x2aab5460, R10 = 0x0bfc, FP = 0x7eacec14 IP = 0x7eaceb98, SP = 0x7eacea78, LR = 0x4c8823e8, PC = 0x4c88241c CPSR = 0x2010, FAULT_ADDRESS = 0x == backtrace (orig glibc): ./eh( eh_stack_unwind +0x18c)[0xde0c] ./eh[0xdfac] /lib/libc.so.6( __default_rt_sa_restorer_v2 +0x0)[0x4c883770] /lib/libc.so.6( gsignal +0x40)[0x4c88241c] /lib/libc.so.6( abort +0x1c0)[0x4c88680c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.so.6( __gnu_cxx::__verbose_terminate_handler() +0x134)[0x4cb2ca0c] /lib/libstdc++.s