Date: Sat, 27 Feb 2016 15:31:58 -0800 From: Mark Millard <markmi@dsl-only.net> To: FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>, FreeBSD Toolchain <freebsd-toolchain@freebsd.org>, Roman Divacky <rdivacky@freebsd.org>, Dimitry Andric <dim@FreeBSD.org> Subject: clang 3.8.0 can mess up __builtin_dwarf_cfa (), at least for TARGET_ARCH=powerpc: a bug 207325 update Message-ID: <F23112FF-C417-4757-96FF-4E93C259DC9D@dsl-only.net> In-Reply-To: <80EA4460-E842-46F5-B006-2A83FBBEE845@dsl-only.net> References: <83B8741C-B4C9-4EFB-A3B4-473F8F165984@dsl-only.net> <80EA4460-E842-46F5-B006-2A83FBBEE845@dsl-only.net>
next in thread | previous in thread | raw e-mail | index | archive | help
[Top post for dinging the low level problem that directly breaks c++ = exception handling for TARGET_ARCH=3Dpowerpc for clang 3.8.0 generated = code.] I've tracked down the c++ exception problem for TARGET_ARCH=3Dpowerpc = via clang 3.8.0: misbehavior of clang 3.8.0 code generation for = __builtin_dwarf_cfa () as used in: #define uw_init_context(CONTEXT) = \ do = \ { = \ /* Do any necessary initialization to access arbitrary stack = frames. \ On the SPARC, this means flushing the register windows. */ = \ __builtin_unwind_init (); = \ uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), = \ __builtin_return_address (0)); = \ } = \ while (0) . . . 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); In the below r4 ends up with the __builtin_dwarf_cfa () value supplied = to uw_init_context_1: Dump of assembler code for function _Unwind_RaiseException: 0x419a8fd8 <+0>: mflr r0 0x419a8fdc <+4>: stw r31,-148(r1) 0x419a8fe0 <+8>: stw r30,-152(r1) 0x419a8fe4 <+12>: stw r0,4(r1) 0x419a8fe8 <+16>: stwu r1,-2992(r1) 0x419a8fec <+20>: mr r31,r1 . . . 0x419a9094 <+188>: mr r4,r31 0x419a9098 <+192>: mflr r30 0x419a909c <+196>: lwz r5,2996(r31) 0x419a90a0 <+200>: mr r3,r28 0x419a90a4 <+204>: bl 0x419a929c <uw_init_context_1> That r4 ends up holding the stack pointer value for after it has been = decremented. r4 is not pointing at the boundary with the caller's frame. The .eh_frame information and unwind code is set up for pointing at the = boundary with the caller's frame. So the cfa relative addressing is = messed up for what it actually extracts. Contrast this with gcc/g++ 5.3's TARGET_ARCH=3Dpowerpc64 code where r4 = is made to be at the boundary with the caller's frame: Dump of assembler code for function _Unwind_RaiseException: 0x00000000501cb810 <+0>: mflr r0 0x00000000501cb814 <+4>: stdu r1,-5648(r1) . . . 0x00000000501cb8d0 <+192>: addi r4,r1,5648 0x00000000501cb8d4 <+196>: stw r12,5656(r1) 0x00000000501cb8d8 <+200>: mr r28,r3 0x00000000501cb8dc <+204>: addi r31,r1,2544 0x00000000501cb8e0 <+208>: mr r3,r27 0x00000000501cb8e4 <+212>: addi r29,r1,112 0x00000000501cb8e8 <+216>: bl 0x501cae60 <uw_init_context_1> NOTE: The powerpc (32-bit) issue may in some way be associated with the = clang 3.8.0 powerpc ABI violation in how it handles the stack pointer = for FreeBSD: TARGET_ARCH=3Dpowerpc is currently using a "red zone", = decrementing the stack pointer late, and incrementing the stack pointer = early compared to the FreeBSD ABI rules. (This is similar to the = official FreeBSD ABI for TARGET_ARCH=3Dpowerpc64.) =3D=3D=3D Mark Millard markmi at dsl-only.net On 2016-Feb-26, at 3:26 PM, Mark Millard <markmi at dsl-only.net> wrote: >=20 > On 2016-Feb-19, at 11:37 AM, Mark Millard <markmi at dsl-only.net> = wrote: >=20 >> The following program does not work for my example = TARGET_ARCH=3Dpowerpc and TARGET_ARCH=3Dpowerpc64 environments for = buildworld based on projects/clang380-import -r205601: >>=20 >> #include <exception> >>=20 >> int main(void) >> { >> try { throw std::exception(); } >> catch (std::exception& e) {} // same result without & >> return 0; >> } >>=20 >> The details vary for what happens and what compiler is in use. >>=20 >> TARGET_ARCH=3Dpowerpc with clang 3.8.0: SEGV >>=20 >> TARGET_ARCH=3Dpowerpc64 with devel/powerpc64-gcc: unbouded loop in = _Unwind_RaiseException >>=20 >> For the powerpc64 context: g++49 can be used to show the problem as = well: >>=20 >> Using g++49's a.out gets the same unbounded loop result for: >>=20 >> # g++49 -I /usr/include/c++/v1/ -L /usr/lib/ -g -Wall -pedantic = exception_test.cpp = =20 >>=20 >> But the a.out works fine for a normal g++49 header/library usage: >>=20 >> # g++49 -g -Wall -pedantic exception_test.cpp >> # ./a.out >> #=20 >>=20 >>=20 >>=20 >> (These were noticed by trying to build and use kyua to run the = /usr/tests material in tehse enviroments.) >>=20 >>=20 >> =3D=3D=3D >> Mark Millard >> markmi at dsl-only.net >=20 > [Note: The _Unwind_RaiseException involved below was compiled by clang = 3.8.0 during buildworld. So clang generated the .eh_frame information = involved.] >=20 > In the TARGET_ARCH=3Dpowerpc operation there are a sequence of 2 = errors, the 2nd of which gets the SEGV: >=20 > A) The catch clause is rejected/ignored so std::terminate is called >=20 > B) During the std::terminate related execution the SEGV happens. >=20 > (A) is the more fundamental issue. >=20 > I have found the following mismatch between some powerpc code = generated and the .eh_frame information generated by clang 3.8.0 for the = TARGET_ARCH=3Dpowerpc context. (Using objdump and dwarfdump notation = below, no relocations.) The specific example need not be directly = involved in (A) or (B) but is inaccurate .eh_frame generation either = way. >=20 >> 00007fd8 <_Unwind_RaiseException> mflr r0 >> 00007fdc <_Unwind_RaiseException+0x4> stw r31,-148(r1) >> 00007fe0 <_Unwind_RaiseException+0x8> stw r30,-152(r1) >> 00007fe4 <_Unwind_RaiseException+0xc> stw r0,4(r1) >> 00007fe8 <_Unwind_RaiseException+0x10> stwu r1,-2992(r1) >> 00007fec <_Unwind_RaiseException+0x14> mr r31,r1 >> 00007ff0 <_Unwind_RaiseException+0x18> mfcr r12 >> . . . >> 0000827c <_Unwind_RaiseException+0x2a4> lwz r14,2776(r31) >> 00008280 <_Unwind_RaiseException+0x2a8> addi r1,r1,2992 >> 00008284 <_Unwind_RaiseException+0x2ac> lwz r0,4(r1) >> 00008288 <_Unwind_RaiseException+0x2b0> lwz r31,-148(r1) >> 0000828c <_Unwind_RaiseException+0x2b4> lwz r30,-152(r1) >> 00008290 <_Unwind_RaiseException+0x2b8> mtlr r0 >> 00008294 <_Unwind_RaiseException+0x2bc> blr >> 00008298 <_Unwind_RaiseException+0x2c0> bl 0001eccc <abort@plt> >=20 > The .eh_frame information shown by dwarfdump (see later below) shows = off cfa=3D2992(r31) over the range starting at 0x00007ff0 but 0x828c to = 0x8298 comes after R31 is returned to its old value. (The range goes up = to 0x0000829c, which is the start of the next block of addresses.) >=20 > <off cfa=3D2992(r31) > is just wrong at 0000828c and later above. >=20 > (I'm not going to make claims here about 0x00007ff0 below listing both = <off cfa=3D2992(r31) > and <off r31=3D-148(cfa) > or how such is = handled. But it would seem that cfa=3D?(r31)'s interpretation would need = to ignore any prior or same line r31=3D?(cfa). Either way it is = generally wrong once cfa itself is inaccurate, as it is at 0000828c.) >=20 > The dwarfdump -v -v -F material for this is: >=20 >> < 0><0x00007fd8:0x0000829c><><fde offset 0x000002b4 length: = 0x00000064><eh aug data len 0x0> >> 0x00007fd8: <off cfa=3D00(r1) >=20 >> 0x00007fec: <off cfa=3D2992(r1) > <off r30=3D-152(cfa) > <off = r31=3D-148(cfa) > <off r65=3D04(cfa) >=20 >> 0x00007ff0: <off cfa=3D2992(r31) > <off r14=3D-216(cfa) > <off = r15=3D-212(cfa) > <off r16=3D-208(cfa) > <off r17=3D-204(cfa) > <off = r18=3D-200(cfa) > <off r19=3D-196(cfa) > <off r20=3D-192(cfa) > <off = r21=3D-188(cfa) > <off r22=3D-184(cfa) > <off r23=3D-180(cfa) > <off = r24=3D-176(cfa) > <off r25=3D-172(cfa) > <off r26=3D-168(cfa) > <off = r27=3D-164(cfa) > <off r28=3D-160(cfa) > <off r29=3D-156(cfa) > <off = r30=3D-152(cfa) > <off r31=3D-148(cfa) > <off r46=3D-144(cfa) > <off = r47=3D-136(cfa) > <off r48=3D-128(cfa) > <off r49=3D-120(cfa) > <off = r50=3D-112(cfa) > <off r51=3D-104(cfa) > <off r52=3D-96(cfa) > <off = r53=3D-88(cfa) > <off r54=3D-80(cfa) > <off r55=3D-72(cfa) > <off = r56=3D-64(cfa) > <off r57=3D-56(cfa) > <off r58=3D-48(cfa) > <off = r59=3D-40(cfa) > <off r60=3D-32(cfa) > <off r61=3D-24(cfa) > <off = r62=3D-16(cfa) > <off r63=3D-8(cfa) > <off r65=3D04(cfa) >=20 >> fde section offset 692 0x000002b4 cie offset for fde: 696 0x000002b8 >> 0 DW_CFA_advance_loc 20 (5 * 4) >> 1 DW_CFA_def_cfa_offset 2992 >> 4 DW_CFA_offset r31 -148 (37 * -4) >> 6 DW_CFA_offset r30 -152 (38 * -4) >> 8 DW_CFA_offset_extended_sf r65 4 (-1 * -4) >> 11 DW_CFA_advance_loc 4 (1 * 4) >> 12 DW_CFA_def_cfa_register r31 >> 14 DW_CFA_offset r14 -216 (54 * -4) >> 16 DW_CFA_offset r15 -212 (53 * -4) >> 18 DW_CFA_offset r16 -208 (52 * -4) >> 20 DW_CFA_offset r17 -204 (51 * -4) >> 22 DW_CFA_offset r18 -200 (50 * -4) >> 24 DW_CFA_offset r19 -196 (49 * -4) >> 26 DW_CFA_offset r20 -192 (48 * -4) >> 28 DW_CFA_offset r21 -188 (47 * -4) >> 30 DW_CFA_offset r22 -184 (46 * -4) >> 32 DW_CFA_offset r23 -180 (45 * -4) >> 34 DW_CFA_offset r24 -176 (44 * -4) >> 36 DW_CFA_offset r25 -172 (43 * -4) >> 38 DW_CFA_offset r26 -168 (42 * -4) >> 40 DW_CFA_offset r27 -164 (41 * -4) >> 42 DW_CFA_offset r28 -160 (40 * -4) >> 44 DW_CFA_offset r29 -156 (39 * -4) >> 46 DW_CFA_offset r30 -152 (38 * -4) >> 48 DW_CFA_offset r31 -148 (37 * -4) >> 50 DW_CFA_offset r46 -144 (36 * -4) >> 52 DW_CFA_offset r47 -136 (34 * -4) >> 54 DW_CFA_offset r48 -128 (32 * -4) >> 56 DW_CFA_offset r49 -120 (30 * -4) >> 58 DW_CFA_offset r50 -112 (28 * -4) >> 60 DW_CFA_offset r51 -104 (26 * -4) >> 62 DW_CFA_offset r52 -96 (24 * -4) >> 64 DW_CFA_offset r53 -88 (22 * -4) >> 66 DW_CFA_offset r54 -80 (20 * -4) >> 68 DW_CFA_offset r55 -72 (18 * -4) >> 70 DW_CFA_offset r56 -64 (16 * -4) >> 72 DW_CFA_offset r57 -56 (14 * -4) >> 74 DW_CFA_offset r58 -48 (12 * -4) >> 76 DW_CFA_offset r59 -40 (10 * -4) >> 78 DW_CFA_offset r60 -32 (8 * -4) >> 80 DW_CFA_offset r61 -24 (6 * -4) >> 82 DW_CFA_offset r62 -16 (4 * -4) >> 84 DW_CFA_offset r63 -8 (2 * -4) >> 86 DW_CFA_nop >=20 > =3D=3D=3D > Mark Millard > markmi at dsl-only.net >=20 >=20
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?F23112FF-C417-4757-96FF-4E93C259DC9D>