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
[In part: My references to libc++ should have been to libcxxrt. Also: devel/powerpc64-gcc produced the incomplete .eh_frame information.] On 2016-Feb-24, at 5:07 PM, Mark Millard wrote: > > [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=context@entry=0xccf0, >> fs=fs@entry=0xc370) at >> /usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind-dw2.c:1371 >> #1 0x501cb95c in _Unwind_RaiseException (exc=0x50815058) at >> /usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind.inc:126 >> #2 0x5016e3a0 in throw_exception (ex=0x50815000) at >> /usr/src/lib/libcxxrt/../../contrib/libcxxrt/exception.cc:751 >> #3 0x1d50 in main () at exception_test.cpp:5 > > _Unwind_RaiseException never returns for source code that looks like: > >> #include >> >> 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 = >> _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 >> 91 /* Set up this_context to describe the current stack frame. */ >> 92 uw_init_context (&this_context); >> 93 cur_context = this_context; >> 94 >> 95 /* Phase 1: Search. Unwind the stack, calling the personality routine >> 96with the _UA_SEARCH_PHASE flag set. Do not modify the stack yet. >> */ >> 97 while (1) >> 98 { >> 99 _Unwind_FrameState fs; >> 100 >> 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. */ >> 103code = uw_frame_state_for (&cur_context, &fs); >> . . . >> 125/* Update cur_context to describe the same frame as fs. */ >> 126uw_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 = __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 :stw >> r10,48(r9) >> 0x5016e39c :bl >> 0x50162ae0 <0017.plt_call._Unwind_RaiseException@@GCC_3.0> >> 0x5016e3a0 :ld >> r2,40(r1) >> 0x5016e3a4 :addi >> r1,r1,128 >> 0x5016e3a8 :mr >> r4,r31 >> 0x5016e3ac :ld >> r0,16(r1) > > From /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): > >> 00015398 <.__cxa_end_catch+0x4d8> stw r10,48(r9) >> 0001539c <.__cxa_end_catch+0x4dc> bl 9ae0 >> >> 000153a0 <.__cxa_end_catch+0x4e0> ld r2,40(r1) >> 000153a4 <.__cxa_end_catch+0x4e4> addir1,r1,128 >> 000153a8 <.__cxa_end_catch+0x4e8> mr r4,r31 >> 000153ac <.__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><>> 0x0034> >>0x00015310: >>0x00015318: >>0x00015324: >>0x00015368: >>0x00015378: >>0x00015380: >>0x000153a8: >>0x000153b8: >>0x000153c0: >> fde section offset 4312 0x10d8 cie offset for fde: 4316 0x10dc >> 0 DW_CFA_advance
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
[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=context@entry=0xccf0, > fs=fs@entry=0xc370) at > /usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind-dw2.c:1371 > #1 0x501cb95c in _Unwind_RaiseException (exc=0x50815058) at > /usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind.inc:126 > #2 0x5016e3a0 in throw_exception (ex=0x50815000) at > /usr/src/lib/libcxxrt/../../contrib/libcxxrt/exception.cc:751 > #3 0x1d50 in main () at exception_test.cpp:5 _Unwind_RaiseException never returns for source code that looks like: > #include > > 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 = > _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 > 91 /* Set up this_context to describe the current stack frame. */ > 92 uw_init_context (&this_context); > 93 cur_context = this_context; > 94 > 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 > 101 /* Set up fs to describe the FDE for the caller of cur_context. > The > 102first time through the loop, that means __cxa_throw. */ > 103 code = 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. */ > 1369context->ra = __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 :stw > r10,48(r9) >0x5016e39c :bl > 0x50162ae0 <0017.plt_call._Unwind_RaiseException@@GCC_3.0> >0x5016e3a0 :ld > r2,40(r1) >0x5016e3a4 :addi > r1,r1,128 >0x5016e3a8 :mr > r4,r31 >0x5016e3ac :ld > r0,16(r1) From /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): > 00015398 <.__cxa_end_catch+0x4d8> stw r10,48(r9) > 0001539c <.__cxa_end_catch+0x4dc> bl 9ae0 > > 000153a0 <.__cxa_end_catch+0x4e0> ld r2,40(r1) > 000153a4 <.__cxa_end_catch+0x4e4> addir1,r1,128 > 000153a8 <.__cxa_end_catch+0x4e8> mr r4,r31 > 000153ac <.__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><> aug data len 0x0> > 0x00015310: > 0x00015318: > 0x00015324: > 0x00015368: > 0x00015378: > 0x00015380: > 0x000153a8: > 0x000153b8: > 0x000153c0: > fde section offset 4312 0x10d8 cie offset for fde: 4316 0x10dc > 0 DW_CFA_advance_loc 8 (2 * 4) > 1 DW_CFA_register r65 = 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_sta
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
For TARGET_ARCH=powerpc64 it looks like FreeBSD's /lib/libgcc_s.so.1 is incompatible with using the pair: /usr/lib/libc++.so.1 and /lib/libcxxrt.so.1 . Evidence details follow. (Now using projects/clang380-import -r295902 as a context.) src.conf was set up to have things such that the buildworld/buildkernel that this is based on was via : devel/powerpc64-gcc as the (self hosted) cross compiler ( /usr/local/bin/powerpc64-portbld-freebsd11.0-g++ ) and clang 3.8.0 as the "host" compiler. Later below I list the ldd output for compiling the exception_test.cpp example under different compilers with different options that change what ldd shows and how .so's are found/bound. Some are implicitly using. . . ELF ldconfig path: /lib /usr/lib /usr/lib/compat /usr/local/lib /usr/local/lib/compat/pkg /usr/local/lib/compat/pkg /usr/local/lib/gcc49 /usr/local/lib/gcc6 and others are explicitly bound, such as by -Wl,-rpath= . The only combinations that get the unbounded looping internal to exception handling are the ones that mix 3 things together: /usr/lib/libc++.so.1 /lib/libcxxrt.so.1 /lib/libgcc_s.so.1 That is: exception_test.clang++380.powerpc64 and exception_test.powerpc64-gcc.powerpc64 get the unbounded looping and the others work fine. Note that all 3 libraries were built by devel/powerpc64-gcc during buildworld, not by clang 3.8.0 . And exception_test.powerpc64-gcc.powerpc64 does not involve clang 3.8.0 based code at all. Still libc++.so.1 and libcxxrt.so.1 are "foreign" relative to libgcc_s.so.1 and so there being some form of mismatch possible makes some sense. That same /lib/libgcc_s.so.1 works fine with: /usr/local/lib/gcc49/libstdc++.so.6 and /usr/local/lib/gcc6/libstdc++.so.6 Of course a matched libstdc++/libgcc_s pair for a specific g++ compiler also works. The combinations tested are . . . # ldd *powerpc64 exception_test.clang++380.powerpc64: libc++.so.1 => /usr/lib/libc++.so.1 (0x50054000) libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x5015a000) libm.so.5 => /lib/libm.so.5 (0x50181000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x501be000) libc.so.7 => /lib/libc.so.7 (0x501e4000) exception_test.g++49-implicitgcc49.powerpc64: libstdc++.so.6 => /usr/local/lib/gcc49/libstdc++.so.6 (0x50054000) libm.so.5 => /lib/libm.so.5 (0x501ed000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x5022a000) libc.so.7 => /lib/libc.so.7 (0x5025) exception_test.g++49.powerpc64: libstdc++.so.6 => /usr/local/lib/gcc49/libstdc++.so.6 (0x50054000) libm.so.5 => /lib/libm.so.5 (0x501ed000) libgcc_s.so.1 => /usr/local/lib/gcc49/libgcc_s.so.1 (0x5022a000) libc.so.7 => /lib/libc.so.7 (0x50253000) exception_test.g++6-implicitgcc49.powerpc64: libstdc++.so.6 => /usr/local/lib/gcc49/libstdc++.so.6 (0x50054000) libm.so.5 => /lib/libm.so.5 (0x501ed000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x5022a000) libc.so.7 => /lib/libc.so.7 (0x5025) exception_test.g++6.powerpc64: libstdc++.so.6 => /usr/local/lib/gcc6/libstdc++.so.6 (0x50054000) libm.so.5 => /lib/libm.so.5 (0x502a6000) libgcc_s.so.1 => /usr/local/lib/gcc6/libgcc_s.so.1 (0x502e3000) libc.so.7 => /lib/libc.so.7 (0x5030a000) exception_test.powerpc64-gcc.powerpc64: libc++.so.1 => /usr/lib/libc++.so.1 (0x50053000) libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x50159000) libm.so.5 => /lib/libm.so.5 (0x5018) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x501bd000) libc.so.7 => /lib/libc.so.7 (0x501e3000) NOTE: Why no g++5 test using its /usr/local/lib/gcc5/libstdc++.so.6? Currently devel/powerpc64-gcc and lang/gcc5 are both at 5.3 and that makes them conflict on files if one tries to build both ports. So I have just devel/powerpc64-gcc, the "officially produced" cross compiler port for targeting modernized powerpc64 builds. === Mark Millard markmi at dsl-only.net ___ freebsd-toolchain@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"