Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Feb 2016 17:07:59 -0800
From:      Mark Millard <markmi@dsl-only.net>
To:        FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>, FreeBSD Toolchain <freebsd-toolchain@freebsd.org>
Cc:        Roman Divacky <rdivacky@vlakno.cz>, Dimitry Andric <dim@FreeBSD.org>
Subject:   Re: projects/clang380-import for TARGET_ARCH=powerpc64: /lib/libgcc_s.so.1 is incompatible with using the pair: /usr/lib/libc++.so.1 and /lib/libcxxrt.so.1 for C++ exception handling
Message-ID:  <B2EA9D1B-DCF0-4C98-AB83-F8C7B75F97BB@dsl-only.net>
In-Reply-To: <5B9137BF-0E86-4C4B-A3FB-18F444A850AC@dsl-only.net>
References:  <5B9137BF-0E86-4C4B-A3FB-18F444A850AC@dsl-only.net>

next in thread | previous in thread | raw e-mail | index | archive | help
[Deliberate top posting an history removal for significant new =
information.]

I've finally traced the low level details of the powerpc64 =
_Unwind_RaiseException stuck looping failure.  What I've submitted into =
the defect is basically that for clang 3.8.0's .eh_frame information =
generation in libcxxrt's code there is an error in the form of an =
incompleteness. . .


Starting from the observed low-level evidence based on observation via =
gdb and such:

A backtrace while stopped during the unbounded looping is:

> #0  uw_update_context (context=3Dcontext@entry=3D0xffffffffffffccf0, =
fs=3Dfs@entry=3D0xffffffffffffc370) at =
/usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind-dw2.c:1371
> #1  0x00000000501cb95c in _Unwind_RaiseException (exc=3D0x50815058) at =
/usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind.inc:126
> #2  0x000000005016e3a0 in throw_exception (ex=3D0x50815000) at =
/usr/src/lib/libcxxrt/../../contrib/libcxxrt/exception.cc:751
> #3  0x0000000010000d50 in main () at exception_test.cpp:5

_Unwind_RaiseException never returns for source code that looks like:

> #include <exception>
>=20
> int main(void)
> {
>     try { throw std::exception(); }
>     catch (std::exception& e) {}
>     return 0;
> }

where in /usr/lib/libc++.so.1 there is:

> 736	static void throw_exception(__cxa_exception *ex)
> 737	{
> . . .
> 751		_Unwind_Reason_Code err =3D =
_Unwind_RaiseException(&ex->unwindHeader);
> . . .
> 756	}

The unbounded loop in _Unwind_RaiseException is in the code:

> 85	_Unwind_Reason_Code
> 86	_Unwind_RaiseException(struct _Unwind_Exception *exc)
> 87	{
> 88	  struct _Unwind_Context this_context, cur_context;
> 89	  _Unwind_Reason_Code code;
> 90=09
> 91	  /* Set up this_context to describe the current stack frame.  =
*/
> 92	  uw_init_context (&this_context);
> 93	  cur_context =3D this_context;
> 94=09
> 95	  /* Phase 1: Search.  Unwind the stack, calling the personality =
routine
> 96	     with the _UA_SEARCH_PHASE flag set.  Do not modify the =
stack yet.  */
> 97	  while (1)
> 98	    {
> 99	      _Unwind_FrameState fs;
> 100=09
> 101	      /* Set up fs to describe the FDE for the caller of =
cur_context.  The
> 102		 first time through the loop, that means __cxa_throw.  =
*/
> 103	      code =3D uw_frame_state_for (&cur_context, &fs);
> . . .
> 125	      /* Update cur_context to describe the same frame as fs.  =
*/
> 126	      uw_update_context (&cur_context, &fs);
> 127	    }
> . . .
> 140	}

The uw_update_context call is doing the following before returning:

> 1367	  /* Compute the return address now, since the return address =
column
> 1368	     can change from frame to frame.  */
> 1369	  context->ra =3D __builtin_extract_return_addr
> 1370	    (_Unwind_GetPtr (context, fs->retaddr_column));

with context->ra before and after the call both being 0x5016e3a0 . In =
fact it was 0x5016e3a0 for the prior uw_frame_state_for call as well and =
continues to be so each loop iteration once the problem starts.

As for the code around 0x5016e3a0:

>    0x5016e398 <throw_exception(__cxxabiv1::__cxa_exception*)+136>:	=
stw     r10,48(r9)
>    0x5016e39c <throw_exception(__cxxabiv1::__cxa_exception*)+140>:	=
bl      0x50162ae0 <00000017.plt_call._Unwind_RaiseException@@GCC_3.0>
>    0x5016e3a0 <throw_exception(__cxxabiv1::__cxa_exception*)+144>:	=
ld      r2,40(r1)
>    0x5016e3a4 <throw_exception(__cxxabiv1::__cxa_exception*)+148>:	=
addi    r1,r1,128
>    0x5016e3a8 <throw_exception(__cxxabiv1::__cxa_exception*)+152>:	=
mr      r4,r31
>    0x5016e3ac <throw_exception(__cxxabiv1::__cxa_exception*)+156>:	=
ld      r0,16(r1)

 =46rom /usr/local/bin/objdump for FreeBSD projects/clang380-import =
-r295902's /usr/lib/libc++.so.1 for the same code (to match up with the =
.eh_frame dwarf information):

> 0000000000015398 <.__cxa_end_catch+0x4d8> stw     r10,48(r9)
> 000000000001539c <.__cxa_end_catch+0x4dc> bl      0000000000009ae0 =
<CXXABI_1.3+0x9ae0>
> 00000000000153a0 <.__cxa_end_catch+0x4e0> ld      r2,40(r1)
> 00000000000153a4 <.__cxa_end_catch+0x4e4> addi    r1,r1,128
> 00000000000153a8 <.__cxa_end_catch+0x4e8> mr      r4,r31
> 00000000000153ac <.__cxa_end_catch+0x4ec> ld      r0,16(r1)

The code block above from 153a0 up to 153a8 is being given 153a0 as its =
"return address" (context->ra) by uw_update_context via interpreting the =
dwarf .eh_frame information. So once in that range there it never leaves =
that range.

The relevant dwarfdump output spanning that area is:
(Note that 153a0 up to 153a8 is part of the range that includes the bl =
to _Unwind_RaiseException .)

> <    0><0x00015310:0x000153dc><><fde offset 0x000010d8 length: =
0x00000034><eh aug data len 0x0>
>         0x00015310: <off cfa=3D00(r1) >=20
>         0x00015318: <off cfa=3D00(r1) > <off r31=3D-8(cfa) > <off =
r65=3Dr0 >=20
>         0x00015324: <off cfa=3D128(r1) > <off r31=3D-8(cfa) > <off =
r65=3D16(cfa) >=20
>         0x00015368: <off cfa=3D00(r1) > <off r31=3D-8(cfa) > <off =
r65=3D16(cfa) >=20
>         0x00015378: <off cfa=3D00(r1) >=20
>         0x00015380: <off cfa=3D128(r1) > <off r31=3D-8(cfa) > <off =
r65=3D16(cfa) >=20
>         0x000153a8: <off cfa=3D00(r1) > <off r31=3D-8(cfa) > <off =
r65=3D16(cfa) >=20
>         0x000153b8: <off cfa=3D00(r1) >=20
>         0x000153c0: <off cfa=3D128(r1) > <off r31=3D-8(cfa) > <off =
r65=3D16(cfa) >=20
>  fde section offset 4312 0x000010d8 cie offset for fde: 4316 =
0x000010dc
>          0 DW_CFA_advance_loc 8  (2 * 4)
>          1 DW_CFA_register r65 =3D r0
>          4 DW_CFA_offset r31 -8  (1 * -8)
>          6 DW_CFA_advance_loc 12  (3 * 4)
>          7 DW_CFA_def_cfa_offset 128
>         10 DW_CFA_offset_extended_sf r65 16  (-2 * -8)
>         13 DW_CFA_advance_loc 68  (17 * 4)
>         14 DW_CFA_remember_state
>         15 DW_CFA_def_cfa_offset 0
>         17 DW_CFA_advance_loc 16  (4 * 4)
>         18 DW_CFA_restore_extended r65
>         20 DW_CFA_restore r31
>         21 DW_CFA_advance_loc 8  (2 * 4)
>         22 DW_CFA_restore_state
>         23 DW_CFA_advance_loc 40  (10 * 4)
>         24 DW_CFA_remember_state
>         25 DW_CFA_def_cfa_offset 0
>         27 DW_CFA_advance_loc 16  (4 * 4)
>         28 DW_CFA_restore_extended r65
>         30 DW_CFA_restore r31
>         31 DW_CFA_advance_loc 8  (2 * 4)
>         32 DW_CFA_restore_state
>         33 DW_CFA_nop
>         34 DW_CFA_nop
>         35 DW_CFA_nop
>         36 DW_CFA_nop
>         37 DW_CFA_nop
>         38 DW_CFA_nop

Note that the stack pointer manipulation (incrementing/popping) *after* =
the return from the bl. 15339c, 153a0, and 153a4 should be 3 or so =
distinct contexts in the .eh_frame information but are not. The code is:

> 000000000001539c <.__cxa_end_catch+0x4dc> bl      0000000000009ae0 =
<CXXABI_1.3+0x9ae0>
> 00000000000153a0 <.__cxa_end_catch+0x4e0> ld      r2,40(r1)
> 00000000000153a4 <.__cxa_end_catch+0x4e4> addi    r1,r1,128

So there is a missing step or more of frame-context tracking in the =
.eh_frame information.


=3D=3D=3D
Mark Millard
markmi at dsl-only.net




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?B2EA9D1B-DCF0-4C98-AB83-F8C7B75F97BB>