clang 3.8.0 can generate inaccurate .eh_frame information, at least for TARGET_ARCH=powerpc: a bug 207325 update

Mark Millard markmi at dsl-only.net
Fri Feb 26 23:26:44 UTC 2016


On 2016-Feb-19, at 11:37 AM, Mark Millard <markmi at dsl-only.net> wrote:

> The following program does not work for my example TARGET_ARCH=powerpc and TARGET_ARCH=powerpc64 environments for buildworld based on projects/clang380-import -r205601:
> 
> #include <exception>
> 
> int main(void)
> {
>    try { throw std::exception(); }
>    catch (std::exception& e) {} // same result without &
>    return 0;
> }
> 
> The details vary for what happens and what compiler is in use.
> 
> TARGET_ARCH=powerpc with clang 3.8.0: SEGV
> 
> TARGET_ARCH=powerpc64 with devel/powerpc64-gcc: unbouded loop in _Unwind_RaiseException
> 
> For the powerpc64 context: g++49 can be used to show the problem as well:
> 
> Using g++49's a.out gets the same unbounded loop result for:
> 
> # g++49 -I /usr/include/c++/v1/ -L /usr/lib/ -g -Wall -pedantic exception_test.cpp                                                                                                                      
> 
> But the a.out works fine for a normal g++49 header/library usage:
> 
> # g++49 -g -Wall -pedantic exception_test.cpp
> # ./a.out
> # 
> 
> 
> 
> (These were noticed by trying to build and use kyua to run the /usr/tests material in tehse enviroments.)
> 
> 
> ===
> Mark Millard
> markmi at dsl-only.net

[Note: The _Unwind_RaiseException involved below was compiled by clang 3.8.0 during buildworld. So clang generated the .eh_frame information involved.]

In the TARGET_ARCH=powerpc operation there are a sequence of 2 errors, the 2nd of which gets the SEGV:

A) The catch clause is rejected/ignored so std::terminate is called

B) During the std::terminate related execution the SEGV happens.

(A) is the more fundamental issue.

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=powerpc 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.

> 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 at plt>

The .eh_frame information shown by dwarfdump (see later below) shows off cfa=2992(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.)

<off cfa=2992(r31) > is just wrong at 0000828c and later above.

(I'm not going to make claims here about 0x00007ff0 below listing both <off cfa=2992(r31) > and <off r31=-148(cfa) > or how such is handled. But it would seem that cfa=?(r31)'s interpretation would need to ignore any prior or same line r31=?(cfa). Either way it is generally wrong once cfa itself is inaccurate, as it is at 0000828c.)

The dwarfdump -v -v -F material for this is:

> <    0><0x00007fd8:0x0000829c><><fde offset 0x000002b4 length: 0x00000064><eh aug data len 0x0>
>         0x00007fd8: <off cfa=00(r1) > 
>         0x00007fec: <off cfa=2992(r1) > <off r30=-152(cfa) > <off r31=-148(cfa) > <off r65=04(cfa) > 
>         0x00007ff0: <off cfa=2992(r31) > <off r14=-216(cfa) > <off r15=-212(cfa) > <off r16=-208(cfa) > <off r17=-204(cfa) > <off r18=-200(cfa) > <off r19=-196(cfa) > <off r20=-192(cfa) > <off r21=-188(cfa) > <off r22=-184(cfa) > <off r23=-180(cfa) > <off r24=-176(cfa) > <off r25=-172(cfa) > <off r26=-168(cfa) > <off r27=-164(cfa) > <off r28=-160(cfa) > <off r29=-156(cfa) > <off r30=-152(cfa) > <off r31=-148(cfa) > <off r46=-144(cfa) > <off r47=-136(cfa) > <off r48=-128(cfa) > <off r49=-120(cfa) > <off r50=-112(cfa) > <off r51=-104(cfa) > <off r52=-96(cfa) > <off r53=-88(cfa) > <off r54=-80(cfa) > <off r55=-72(cfa) > <off r56=-64(cfa) > <off r57=-56(cfa) > <off r58=-48(cfa) > <off r59=-40(cfa) > <off r60=-32(cfa) > <off r61=-24(cfa) > <off r62=-16(cfa) > <off r63=-8(cfa) > <off r65=04(cfa) > 
>  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

===
Mark Millard
markmi at dsl-only.net



More information about the freebsd-ppc mailing list