Date: Sun, 06 Mar 2016 00:59:49 +0000 From: bugzilla-noreply@freebsd.org To: freebsd-bugs@FreeBSD.org Subject: [Bug 207732] libgcc_s .eh_frame handling messes up interpreting powerpc/powerpc64 frame pointer register use produced by clang 3.8.0 Message-ID: <bug-207732-8@https.bugs.freebsd.org/bugzilla/>
next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D207732 Bug ID: 207732 Summary: libgcc_s .eh_frame handling messes up interpreting powerpc/powerpc64 frame pointer register use produced by clang 3.8.0 Product: Base System Version: 11.0-CURRENT Hardware: ppc OS: Any Status: New Severity: Affects Only Me Priority: --- Component: bin Assignee: freebsd-bugs@FreeBSD.org Reporter: markmi@dsl-only.net Because I'm pointing at long standing FreeBSD libgcc_s code that is not lim= ited to the example TARGET_ARCH's taht I'm using I first review some dwarf CFA material. Based on dwarf-2.0.0.pdf (with my notes added): =E2=80=A2 The algorithm to compute the CFA changes as you pro= gress through the prologue and epilogue code. (By definition, the CFA value does = not change.)=20 So as I understand for the "Call Frame Instruction Usage" . . . 1. Initialize a register set by reading the initial_instructio= ns field of the associated CIE.=20 The initial CFA value in/for _Unwind_RaiseException is to be established as initialization before interpreting the first instruction of the initial_instructions field of the CIE, which is the initial CIE for the internal exception handling activity. For that initial CIE (for _Unwind_RaiseException for exception handling): W= hile not part of the Itanium C++ exception ABI (as I understand) this initializa= tion of the initial CFA value is based on starting from the value returned by __builtin_dwarf_cfa(), used in the likes of _Unwind_RaiseException. (For TARGET_ARCH=3Dpowerpc or powerpc64 or possibly others clang 3.8.0 vs. gcc4.2.1/4.9/5.3/6.0 do not agree about which frame boundary _builtin_drawf_cfa() returns. So as stands the value may sometimes need conversion to a standardized-frame-boundary. This is a somewhat separate is= sue separately reported.) Relative to the CFA value: The CIE/FDE instructions for the locations of a specific routine only change the CFA rule that would reproduce the CFA valu= e. (Which would allow back calculating the the value in REG from the CFA value= for CFA=3DOFFSET(REG) contexts: REG=3DCFA-OFFSET.) Any computation that results= in a changed value while interpreting that routines .ef_frame instructions must = be wrong. So finding a CFA for, say, the caller of _Unwind_RaiseException is not via execution of one of the CIE/FDE "instructions" stored in the .eh_frame information for _Unwind_RaiseException or for its caller: it is a separate, additional step based on the information available that may extract some of= the .eh_frame information from the two routines. 2. Read and process the FDE=E2=80=99s instruction sequence unt= il a DW_CFA_advance_loc, DW_CFA_set_loc, or the end of the instruction stream is encountered.=20 3. If a DW_CFA_advance_loc or DW_CFA_set_loc instruction was encountered, then compute a new location value (L2). If L1 >=3D L2 then pro= cess the instruction and go back to step 2.=20 4. The end of the instruction stream can be thought of as a = =E2=80=A8=20=20=20 DW_CFA_set_loc( initial_location + address_range )=E2=80=A8instruction. Unl= ess the FDE is ill-formed, L1 should be less than L2 at this point.=20 The rules in the register set now apply to location L1.=20 So given that dwarf CFA material. . . As compiled by clang 3.8.0 for powerpc (for example): libcxxrt ends up with (dwarfdump -v -v -F output for __cxa_throw): < =C2=A0=C2=A0=C2=A00><0x00010620:0x00010794><__cxa_throw><fde offset 0x000= 006c0 length: 0x00000028><eh aug data len 0x0> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00x00010620: <off cfa=3D00(r1) >=20 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00x00010634: <off cfa=3D48(r1) > <= off r30=3D-8(cfa) > <off r31=3D-4(cfa) > <off r65=3D04(cfa) >=20 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00x00010638: <off cfa=3D48(r31) > = <off r25=3D-28(cfa) > <off r26=3D-24(cfa) > <off r27=3D-20(cfa) > <off r28=3D-16(cfa) > <off r29=3D-12(cfa) > <off r30= =3D-8(cfa) > <off r31=3D-4(cfa) > <off r65=3D04(cfa) >=20 fde section offset 1728 0x000006c0 cie offset for fde: 1732 0x000006c4 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A00 DW_CFA_advance_loc 20 =C2= =A0(5 * 4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A01 DW_CFA_def_cfa_offset 48 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A03 DW_CFA_offset r31 -4 =C2= =A0(1 * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A05 DW_CFA_offset r30 -8 =C2= =A0(2 * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A07 DW_CFA_offset_extended_sf= r65 4 =C2=A0(-1 * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A010 DW_CFA_advance_loc 4 =C2=A0(1 = * 4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A011 DW_CFA_def_cfa_register r31 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A013 DW_CFA_offset r25 -28 =C2=A0(7= * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A015 DW_CFA_offset r26 -24 =C2=A0(6= * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A017 DW_CFA_offset r27 -20 =C2=A0(5= * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A019 DW_CFA_offset r28 -16 =C2=A0(4= * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A021 DW_CFA_offset r29 -12 =C2=A0(3= * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A023 DW_CFA_offset r30 -8 =C2=A0(2 = * -4) =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A025 DW_CFA_nop =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A026 DW_CFA_nop Note the cfa and r31 references in: 0x00010634: <off cfa=3D48(r1) > =C2=A0. . . <off r31=3D-4(cfa) > . . . 0x00010638: <off cfa=3D48(r31) > . . . <off r31=3D-4(cfa) > . . . The use of r31 to define cfa is from (in part) the clang++ 3.8.0 code generation using r31 as a frame pointer in addition to r1 as the stack poin= ter. The matching actual sequence of operations listed above is: =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A01 DW_CFA_def_cfa_offset 48 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A03 DW_CFA_offset r31 -4 =C2= =A0(1 * -4) . . . =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A011 DW_CFA_def_cfa_register r31 The "1 DW_CFA_def_cfa_offset 48" just notes that r1 (the stack pointer) was decremented by 48 by the prior instruction so 48 needs to be added to the n= ew r1 value to reference the same _Unwind_Context cfa value as the prior "<off cfa=3D00(r1) >" status (from the CIE the FDE references) does. The "3 DW_CFA_offset r31 -4 =C2=A0(1 * -4)" was generated because (soon old= ) r31 value was saved at address cfa-4 ("<off r31=3D-4(cfa) >"). This address to = access what will be the old/saved r31 value is recorded in the _Unwind_Context reg[31]. The "11 DW_CFA_def_cfa_register r31" was generated because the prior instruction r31 was updated to be a copy of r1 for use as a frame pointer. = Note that such does not change the _Unwind_Context cfa value. At this stage r1= =3Dr31 and 48(r1)=3D48(r31) and such will hold until either r1 or r31 is changed i= n the routine (if either is). The repeat of "<off r31=3D-4(cfa) >" on the "0x00010638: <off cfa=3D48(r31)= >" line indicates that there is no change to where/how to find the pointer to the old/saved r31 value relative to the CFA value: no new DW_CFA_offset r31 "instruction" for interpretation. [Note the messy mix of different r31's. gcc 4.2.1 does not (normally?) gene= rate such TARGET_ARCH=3Dpowerpc code but clang++ 3.8.0 normally does generate su= ch a Frame Pointer and use it in places. Thus clang++ touches an error that g++ 4.2.1 and the like normally do not.] Unfortunately the above is not the interpretation given by the interpreter = in libgcc_s: "11 DW_CFA_def_cfa_register r31" instead accesses the old/saved r31 value v= ia the pointer in _Unwind_Context reg[31] and then applies the offset 48 to th= at value. The result is the wrong cfa value (which should not have changed at all) and all else based on the cfa value is messed up after that. In essence the reg= [31] value and the offset value used are of mixed vintages/mixed frames: an arbitrary combination. Code for a routine that sticks to cfa=3DOFFSET(r1) for the cfa will not see= this error in the .eh_frame information's interpretation. [r1=3D powerpc/powerpc= 64 stack pointer.] --=20 You are receiving this mail because: You are the assignee for the bug.=
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-207732-8>