From owner-freebsd-toolchain@freebsd.org Fri Feb 26 13:25:41 2016 Return-Path: Delivered-To: freebsd-toolchain@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 2C12BAB418F for ; Fri, 26 Feb 2016 13:25:41 +0000 (UTC) (envelope-from markmi@dsl-only.net) Received: from asp.reflexion.net (outbound-mail-211-154.reflexion.net [208.70.211.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DCED511F0 for ; Fri, 26 Feb 2016 13:25:40 +0000 (UTC) (envelope-from markmi@dsl-only.net) Received: (qmail 14212 invoked from network); 26 Feb 2016 13:25:37 -0000 Received: from unknown (HELO rtc-sm-01.app.dca.reflexion.local) (10.81.150.1) by 0 (rfx-qmail) with SMTP; 26 Feb 2016 13:25:37 -0000 Received: by rtc-sm-01.app.dca.reflexion.local (Reflexion email security v7.80.0) with SMTP; Fri, 26 Feb 2016 08:25:42 -0500 (EST) Received: (qmail 25529 invoked from network); 26 Feb 2016 13:25:42 -0000 Received: from unknown (HELO iron2.pdx.net) (69.64.224.71) by 0 (rfx-qmail) with SMTP; 26 Feb 2016 13:25:42 -0000 X-No-Relay: not in my network X-No-Relay: not in my network X-No-Relay: not in my network X-No-Relay: not in my network X-No-Relay: not in my network X-No-Relay: not in my network Received: from [192.168.1.8] (c-76-115-7-162.hsd1.or.comcast.net [76.115.7.162]) by iron2.pdx.net (Postfix) with ESMTPSA id D04FA1C43BC; Fri, 26 Feb 2016 05:25:36 -0800 (PST) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 8.2 \(2104\)) Subject: Re: r207471 submitted against devel/powerpc64-gcc for _Unwind_RaiseException's internal unbounded looping; matching up with 207359 against base system From: Mark Millard In-Reply-To: <6B1B4F5B-659B-4142-8B16-283E572C25B1@dsl-only.net> Date: Fri, 26 Feb 2016 05:25:37 -0800 Cc: Andreas Tobler , Konstantin Belousov , Baptiste Daroussin Content-Transfer-Encoding: quoted-printable Message-Id: References: <38D884F8-0EB4-4F3E-9475-7465FE173D79@dsl-only.net> <6B1B4F5B-659B-4142-8B16-283E572C25B1@dsl-only.net> To: FreeBSD PowerPC ML , FreeBSD Toolchain , Roman Divacky X-Mailer: Apple Mail (2.2104) X-BeenThere: freebsd-toolchain@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Maintenance of FreeBSD's integrated toolchain List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Feb 2016 13:25:41 -0000 On 2016-Feb-26, at 3:16 AM, Mark Millard wrote: >=20 > [Top post for a new, level level detail tracking of the error. It may = be libgcc_s's .eh_frame handling instead of a comiler output problem = after all. Both 207471 and 207359 have this material now.] >=20 > I state the relationship below from the point of view of what the = existing fde operations would need to do to be correct as they are. The = alternate is that the missing activity is missing operations in the list = instead of the activity being "inside" DW_CFA_remember_state and = DW_CFA_restore_state. >=20 > The problem is that the DW_CFA_remember_state and later = DW_CFA_restore_state do not in fact restore the fs->cfa_offset (in this = case 128 as it was at the time of the DW_CFA_remember_state). >=20 > dwarfdump shows in its notation that the DW_CFA_restore_state should = restore the "off cfa=3D128(r1)" status that was in place at the time of = the DW_CFA_remember_state. This makes sense for the code in question: = otherwise it would be wrong for the purpose. But = DW_CFA_remember_state/DW_CFA_restore_state do not save and restore the = cfa_offset (128 here). >=20 > DW_CFA_remember_state only saves fs->regs. > DW_CFA_restore_state only restores fs->regs. >=20 > fs->cfa_offset is not part of regs but is later used by = uw_update_context_1 for: >=20 > /* Compute this frame's CFA. */ > switch (fs->cfa_how) > { > case CFA_REG_OFFSET: > cfa =3D _Unwind_GetPtr (&orig_context, fs->cfa_reg); > cfa +=3D fs->cfa_offset; > break; > . . . > context->cfa =3D cfa; >=20 >=20 > In the example fs->cfa_offset ends up being 0 instead of 128 after the = DW_CFA_restore_state, causing the wrong frame's return address to be = used. >=20 > For reference: The below is the dwarfdump -v -v -F for throw_exception = (where the "stuck" return address vale problem [0x000153a0] is = observed): >=20 >=20 > < 0><0x00015310:0x000153dc> > 0x00015310: =20 > 0x00015318: =20 > 0x00015324: =20 > 0x00015368: =20 > 0x00015378: =20 > 0x00015380: =20 > 0x000153a8: =20 > 0x000153b8: =20 > 0x000153c0: =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 >=20 >=20 > Note that if fs->cfa_reg could be varying then DW_CFA_remember_state = and DW_CFA_restore_state would need to do appropriate save/restore = activity for that too. >=20 > =3D=3D=3D > Mark Millard > markmi at dsl-only.net I have verified that dwarfdump and its libdwarf do save and restore the = following for the cfa for DW_CFA_remember_state/DW_CFA_restore_state: A) If the offset is relevant or not (if it has a offset style rule) B) the rule-value type C) the register number that the cfa is based on D) the offset or block length by naming conventions E) the block pointer I do not claim that all that applies to the mostly dwarf2 FreeBSD = context. But I expect that (A)-(D) apply, (D) just for the offset case. I do not expect this issue to be strictly TARGET_ARCH=3Dpowerpc64 (or = powerpc): This is a very general property of = DW_CFA_remember_state/DW_CFA_restore_state use for .eh_frame that just = depends on code generation accidental-details for if it will be touched = or not. I've also found that the working simple examples [g++ 4.9, 5.3, 6.0(?) = using their own libraries] happen to leave the CFA =3D OFFSET(r1) with a = constant OFFSET over the throw routine (from libstdc++) that calls = _Unwind_RaiseException. So even if their libgcc_s's have the incomplete = save/restore problem those throw routines do not happen to get code that = touches the problem. But I did find other examples in libstdc++ that did not have the CFA's = involved OFFSET constant over whole routines. Detailed "accidents" of = inlining and other code generation issues lead to such being involved in = places. These code generators can also generate examples of the issue. And, of course, devel/powerpc64-gcc has a g++ 5.3 vintage but is used = with the system's libgcc_s and that combination has the problem in the = throw code's use of _Unwind_RaiseException and attempting to unwind back = out of _Unwind_RaiseException. I conclude that FreeBSD's libgcc_s libraries' .eh_frame handling is = insufficient for general C++ exception handling, be it via g++ vintages = or, probably, clang++ as well. It takes some luck to avoid the problems. = Turing off in-lining, using -O0, and the like would probably make the = problems less likely. FreeBSD's libgcc_s may not be the only example of the problem. I have included the older note below for reference, but with the = mistaken analysis details omitted. =3D=3D=3D Mark Millard markmi at dsl-only.net On 2016-Feb-24, at 8:46 PM, Mark Millard wrote: > #include >=20 > int main(void) > { > try { throw std::exception(); } > catch (std::exception& e) {} // same result without & > return 0; > } >=20 > compiled under devel/powerpc64-gcc (gcc 5.3 based) on a FreeBSD = projects/clang380-import (-r295902, for example) that was also built = (buildworld/buildkernel) with the same devel/powerpc64-gcc demonstrates: >=20 > _Unwind_RaiseException never returns because it is stuck in a = unbounded loop. >=20 > [clang380-import vs. 11.0-CURRENT is not likely to be a big = distinction here. PowerPC64 might be or might not be relative to g++ 5.3 = .] >=20 >=20 > [. . .] >=20 > I use a mix of . . . >=20 > # /usr/local/bin/objdump -d --prefix-addresses libcxxrt.so.1.full >=20 > output and the matching . . . >=20 > # dwarfdump -v -v -F libcxxrt.so.1.full | more >=20 > output to show this. >=20 > 0000000000015350 <.__cxa_end_catch+0x490> addi r3,r31,88 > 0000000000015354 <.__cxa_end_catch+0x494> addi r10,r10,1 > 0000000000015358 <.__cxa_end_catch+0x498> stw r10,48(r9) > 000000000001535c <.__cxa_end_catch+0x49c> bl 0000000000009ae0 = <00000017.plt_call._Unwind_RaiseException@@GCC_3.0> > 0000000000015360 <.__cxa_end_catch+0x4a0> ld r2,40(r1) > 0000000000015364 <.__cxa_end_catch+0x4a4> addi r1,r1,128 > 0000000000015368 <.__cxa_end_catch+0x4a8> mr r4,r31 > vs. > < 0><0x00015050:0x00015310> > 0x00015050: =20 > 0x0001506c: =20 > 0x000150b8: =20 > 0x000150d0: =20 > 0x000150e0: =20 >=20 > [. . .] >=20 > So when _Unwind_RaiseException attempts to walk up the stack from = itself for the first pass up the stack it gets to 0000000000015360. >=20 > And from there it gets to 0000000000015360 and loops. > And from there it gets to 0000000000015360 and loops. > And from there it gets to 0000000000015360 and loops. > And from there it gets to 0000000000015360 and loops. > . . . >=20 > This code/.eh_frame pattern occurs again a little later (and this is = where the original problem was observed for this low-level-detail view). = . . >=20 > 0000000000015380 <.__cxa_end_catch+0x4c0> addis r8,r2,-1 > 0000000000015384 <.__cxa_end_catch+0x4c4> addi r3,r31,88 > 0000000000015388 <.__cxa_end_catch+0x4c8> ld r10,28144(r8) > 000000000001538c <.__cxa_end_catch+0x4cc> std r10,32(r31) > 0000000000015390 <.__cxa_end_catch+0x4d0> lwz r10,48(r9) > 0000000000015394 <.__cxa_end_catch+0x4d4> addi r10,r10,1 > 0000000000015398 <.__cxa_end_catch+0x4d8> stw r10,48(r9) > 000000000001539c <.__cxa_end_catch+0x4dc> bl 0000000000009ae0 = <00000017.plt_call._Unwind_RaiseException@@GCC_3.0> > 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) > vs. > < 0><0x00015310:0x000153dc> > 0x00015310: =20 > 0x00015318: =20 > 0x00015324: =20 > 0x00015368: =20 > 0x00015378: =20 > 0x00015380: =20 > 0x000153a8: =20 > 0x000153b8: =20 > 0x000153c0: =20 >=20 > This leads to (during _Unwind_RaiseException's loop): >=20 > . . . > And from there it gets to 00000000000153a0 and loops. > And from there it gets to 00000000000153a0 and loops. > And from there it gets to 00000000000153a0 and loops. > And from there it gets to 00000000000153a0 and loops. > . . . >=20 >=20 > [. . .] =3D=3D=3D Mark Millard markmi at dsl-only.net