Skip site navigation (1)Skip section navigation (2)
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>