[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 <mar...@dsl-only.net> 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=0xffffffffffffccf0, 
>> fs=fs@entry=0xffffffffffffc370) at 
>> /usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind-dw2.c:1371
>> #1  0x00000000501cb95c in _Unwind_RaiseException (exc=0x50815058) at 
>> /usr/src/gnu/lib/libgcc/../../../contrib/gcc/unwind.inc:126
>> #2  0x000000005016e3a0 in throw_exception (ex=0x50815000) 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>
>> 
>> 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
>> 102           first 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.  */
>> 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 <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)
> 
> 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):
> 
>> 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=00(r1) > 
>>        0x00015318: <off cfa=00(r1) > <off r31=-8(cfa) > <off r65=r0 > 
>>        0x00015324: <off cfa=128(r1) > <off r31=-8(cfa) > <off r65=16(cfa) > 
>>        0x00015368: <off cfa=00(r1) > <off r31=-8(cfa) > <off r65=16(cfa) > 
>>        0x00015378: <off cfa=00(r1) > 
>>        0x00015380: <off cfa=128(r1) > <off r31=-8(cfa) > <off r65=16(cfa) > 
>>        0x000153a8: <off cfa=00(r1) > <off r31=-8(cfa) > <off r65=16(cfa) > 
>>        0x000153b8: <off cfa=00(r1) > 
>>        0x000153c0: <off cfa=128(r1) > <off r31=-8(cfa) > <off r65=16(cfa) > 
>> fde section offset 4312 0x000010d8 cie offset for fde: 4316 0x000010dc
>>         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_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.

I should have noted that devel/powerpc64-gcc was used for buildworld of 
projects/clang380-import -r295902 (and other  versions) --and so for libcxxrt 
as well.

So it is g++ 5.3 that put out the incomplete .eh_frame frame-context tracking, 
not clang 3.8.0.



There is also the point that I typed "libc++" in places that I should have 
typed "libcxxrt".

===
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"

Reply via email to