diff mbox

eh_personality.cc: unwinding on ARM

Message ID 4F675AE8.9060505@codesourcery.com
State New
Headers show

Commit Message

Andrew Stubbs March 19, 2012, 4:12 p.m. UTC
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.

Andrew

Comments

Daniel Jacobowitz March 19, 2012, 4:38 p.m. UTC | #1
On Mon, Mar 19, 2012 at 12:12 PM, Andrew Stubbs <ams@codesourcery.com> 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.

>
> Anyway, as far as copyright goes, I don't believe CodeSourcery has any
> problem with this being committed.
>
> Andrew
EXTERNAL Waechtler Peter (Fa. TCP, CM-AI/PJ-CF31) March 19, 2012, 5:10 p.m. UTC | #2
> On Mon, Mar 19, 2012 at 12:12 PM, Andrew Stubbs
> <ams@codesourcery.com> 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<int>  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 = 0x00000000, ERROR_CODE = 0x00000000, OLDMASK =0x00000000
R0  = 0x00000000, R1  = 0x00000a36, R2  = 0x00000006, R3  = 0x2aab5460
R4  = 0x00000a36, R5  = 0x00000006, R6  = 0x4c97f000, R7  = 0x0000010c
R8  = 0x2aab4fc0, R9  = 0x2aab5460, R10 = 0x00000bfc, FP  = 0x7eacec14
IP  = 0x7eaceb98, SP  = 0x7eacea78, LR  = 0x4c8823e8, PC  = 0x4c88241c
CPSR = 0x20000010, FAULT_ADDRESS = 0x00000000
====== 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++.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++.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++.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]
====== memory map ======
(map) 00008000-0001a000 r-xp 00000000 b3:06 785        /eh
(map) 00021000-00024000 rwxp 00011000 b3:06 785        /eh
(map) 00024000-0006f000 rwxp 00000000 00:00 0          [heap]
(map) 2aaab000-2aaad000 rwxp 00000000 00:00 0
(map) 2aab4000-2aab6000 rwxp 00000000 00:00 0
(map) 4be48000-4be65000 r-xp 00000000 b3:02 32840      /lib/ld-2.8.so
(map) 4be6d000-4be6e000 r-xp 0001d000 b3:02 32840      /lib/ld-2.8.so
(map) 4be6e000-4be6f000 rwxp 0001e000 b3:02 32840      /lib/ld-2.8.so
(map) 4c840000-4c84b000 r-xp 00000000 b3:02 33010      /lib/libgcc_s.so.1
(map) 4c84b000-4c852000 ---p 0000b000 b3:02 33010      /lib/libgcc_s.so.1
(map) 4c852000-4c853000 rwxp 0000a000 b3:02 33010      /lib/libgcc_s.so.1
(map) 4c858000-4c975000 r-xp 00000000 b3:02 32933      /lib/libc-2.8.so
(map) 4c975000-4c97d000 ---p 0011d000 b3:02 32933      /lib/libc-2.8.so
(map) 4c97d000-4c97f000 r-xp 0011d000 b3:02 32933      /lib/libc-2.8.so
(map) 4c97f000-4c980000 rwxp 0011f000 b3:02 32933      /lib/libc-2.8.so
(map) 4c980000-4c983000 rwxp 00000000 00:00 0
(map) 4c988000-4c99c000 r-xp 00000000 b3:02 33026      /lib/libpthread-2.8.so
(map) 4c99c000-4c9a3000 ---p 00014000 b3:02 33026      /lib/libpthread-2.8.so
(map) 4c9a3000-4c9a4000 r-xp 00013000 b3:02 33026      /lib/libpthread-2.8.so
(map) 4c9a4000-4c9a5000 rwxp 00014000 b3:02 33026      /lib/libpthread-2.8.so
(map) 4c9a5000-4c9a7000 rwxp 00000000 00:00 0
(map) 4c9c8000-4c9cc000 r-xp 00000000 b3:02 33039      /lib/libdl-2.8.so
(map) 4c9cc000-4c9d3000 ---p 00004000 b3:02 33039      /lib/libdl-2.8.so
(map) 4c9d3000-4c9d4000 r-xp 00003000 b3:02 33039      /lib/libdl-2.8.so
(map) 4c9d4000-4c9d5000 rwxp 00004000 b3:02 33039      /lib/libdl-2.8.so
(map) 4c9d8000-4ca49000 r-xp 00000000 b3:02 32937      /lib/libm-2.8.so
(map) 4ca49000-4ca50000 ---p 00071000 b3:02 32937      /lib/libm-2.8.so
(map) 4ca50000-4ca51000 r-xp 00070000 b3:02 32937      /lib/libm-2.8.so
(map) 4ca51000-4ca52000 rwxp 00071000 b3:02 32937      /lib/libm-2.8.so
(map) 4ca78000-4cb40000 r-xp 00000000 b3:02 32516      /lib/libstdc++.so.6.0.10
(map) 4cb40000-4cb41000 ---p 000c8000 b3:02 32516      /lib/libstdc++.so.6.0.10
(map) 4cb41000-4cb44000 r-xp 000c9000 b3:02 32516      /lib/libstdc++.so.6.0.10
(map) 4cb44000-4cb46000 rwxp 000cc000 b3:02 32516      /lib/libstdc++.so.6.0.10
(map) 4cb46000-4cb4b000 rwxp 00000000 00:00 0
(map) 7eaae000-7eacf000 rwxp 00000000 00:00 0          [stack]
======= Memory around last code executed:
0x4c8823fc :      0xe3a070e0
0x4c882400 :      0xef000000
0x4c882404 :      0xe1a04000
0x4c882408 :      0xe5030458
0x4c88240c :      0xe1a01004
0x4c882410 :      0xe1a02005
0x4c882414 :      0xe3a07f43
0x4c882418 :      0xef000000
0x4c88241c :  --> 0xe3700a01
0x4c882420 :      0xe1a02000
0x4c882424 :      0x8a000003
0x4c882428 :      0xe3700001
0x4c88242c :      0x0a000006
0x4c882430 :      0xe1a00002
0x4c882434 :      0xe8bd80b0
0x4c882438 :      0xe59f3084
0x4c88243c :      0xebffac43
======= stack memory:
0x7eacea78 :  --> 0x00000001
0x7eacea7c :      0x4c97fbfc
0x7eacea80 :      0x4c97fbfc
0x7eacea84 :      0x4c88680c
0x7eacea88 :      0x00000001
0x7eacea8c :      0x00000058
0x7eacea90 :      0xffff3218
0x7eacea94 :      0x00000058
0x7eacea98 :      0xffff3218
0x7eacea9c :      0x4be6e000
0x7eaceaa0 :      0x2aaabd38
0x7eaceaa4 :      0x4be6e000
0x7eaceaa8 :      0x2aaabd38
0x7eaceaac :      0x7eaceb5c
0x7eaceab0 :      0x2aaabb80
0x7eaceab4 :      0x2aab4a40
0x7eaceab8 :      0x00000001
0x7eaceabc :      0x00000000
0x7eaceac0 :      0x00000001
0x7eaceac4 :      0x00000058
0x7eaceac8 :      0xffff3218
*** end of exception log *****
Paul Brook March 19, 2012, 5:32 p.m. UTC | #3
> 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
Peter Waechtler March 19, 2012, 8:43 p.m. UTC | #4
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
EXTERNAL Waechtler Peter (Fa. TCP, CM-AI/PJ-CF31) March 23, 2012, 4:51 p.m. UTC | #5
> -----Ursprüngliche Nachricht-----
> Von: Andrew Stubbs [mailto:ams@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; libstdc++@gcc.gnu.org;
> paul@codesourcery.com; pwaechtler@mac.com; drow@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 <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <execinfo.h>

#include <iostream>
#include <vector>
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<int>  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
Peter Waechtler March 29, 2012, 6:09 p.m. UTC | #6
On 19.03.2012 17:38, Daniel Jacobowitz wrote:
> On Mon, Mar 19, 2012 at 12:12 PM, Andrew Stubbs<ams@codesourcery.com>  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.
>

Here's another version using siglongjmp to avoid VERIFY in signal handler:
Can someone (maybe you) put that at the appropriate place?
Please don't let the integration being a pain as well

         Peter

seehttp://gcc.gnu.org/ml/gcc-patches/2012-03/msg01161.html


/*
         author: Peter Waechtler (pwaechtler at mac.com)
         Copyright FSF or whatever is needed

         A simple test case to verify if backtrace(3) goes into
         a loop while unwinding on ARM with cxx_personality routine.
*/
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<execinfo.h>
#include<setjmp.h>

#include<iostream>
#include<vector>
using namespace std;

//#include "testsuite.h"

#define WE_PASSED 42
#define WE_FAILED 0xff

sigjmp_buf env;

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*))
                 siglongjmp(env, WE_FAILED);
         else
                 siglongjmp(env, WE_PASSED);
}

static int tst_eh01(void)
{
         int rc = 0;

         std::vector<int>   v(10);
         rc = v.at(42);

         return rc;
}

int main(int argc, char *argv[])
{
         int c = 1;
         struct sigaction sa;

         memset(&sa, 0 , sizeof(sa));
         sa.sa_sigaction = abort_handler;
         sa.sa_flags = SA_SIGINFO;

         sigaction(SIGABRT,&sa, NULL);

         switch (sigsetjmp(env, 1)) {
                 case 0: /* the context was set */
                         c = tst_eh01();
                         break;
                 case WE_PASSED:
                         // VERIFY( true );
                         cerr<<  "PASSED"<<  endl;
                         break;
                 default:
                         // VERIFY( false );
                         cerr<<  "FAILED"<<  endl;
                         break;
         }

         return c;
}
diff mbox

Patch

2010-02-04  Daniel Jacobowitz  <dan@codesourcery.com>

	libstdc++-v3/
	* libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): For
	ARM EABI, skip handlers for _US_VIRTUAL_UNWIND_FRAME
	| _US_FORCE_UNWIND.

--- libstdc++-v3/libsupc++/eh_personality.cc
+++ libstdc++-v3/libsupc++/eh_personality.cc
@@ -384,6 +384,8 @@ 
   switch (state & _US_ACTION_MASK)
     {
     case _US_VIRTUAL_UNWIND_FRAME:
+      if (state & _US_FORCE_UNWIND)
+	CONTINUE_UNWINDING;
       actions = _UA_SEARCH_PHASE;
       break;