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>