Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Mar 2016 01:36:22 -0800
From:      Mark Millard <markmi@dsl-only.net>
To:        FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>, FreeBSD Toolchain <freebsd-toolchain@freebsd.org>
Cc:        Roman Divacky <rdivacky@vlakno.cz>
Subject:   Re: Ulrich Weigand has confirmed 3 of my 4 llvm bug submittals for clang 3.8.0 targeting powerpc/powerpc64. . .
Message-ID:  <2ADD6542-E994-4FF9-B743-F6A03B1DCBCC@dsl-only.net>
In-Reply-To: <C0525A0A-8D4A-4E0B-B024-1A655C281FDC@dsl-only.net>
References:  <EF077AD9-2F3E-493F-802D-D1CCD99461DF@dsl-only.net> <C0525A0A-8D4A-4E0B-B024-1A655C281FDC@dsl-only.net>

next in thread | previous in thread | raw e-mail | index | archive | help
[Some more details confirmed.]

On 2016-Mar-9, at 12:24 PM, Mark Millard <markmi@dsl-only.net> wrote:
>=20
> On 2016-Mar-9, at 11:16 AM, Mark Millard <markmi at dsl-only.net> =
wrote:
>>=20
>> [He also includes a note about ELFV2 ABI for powerpc64le.]
>>=20
>> Quoting llvm 26856 Comment 6 (he put the text in the 26856 submittal =
but the content also covers 26519 and most of 26844):
>>=20
>>> Ulrich Weigand 2016-03-09 11:53:17 CST
>>>=20
>>> Yes, there's indeed a couple of problems here, which affect =
different areas.
>>>=20
>>> 1) On 32-bit ppc, LLVM violates the ABI by storing below the stack =
pointer even though the ABI does not provide a "red zone".  This affects =
every function with a stack frame, and could in theory lead to spurious =
crashes when an asynchronous signal overwrites this area.  This seems to =
be a known issue; the source code contains FIXME lines:
>>>   // FIXME: On PPC32 SVR4, we must not spill before claiming the =
stackframe.
>>>=20
>>> 2) In some scenarios, registers may be spilled/restored twice to the =
stack.  This happens because while most of the spilling happens in =
PPCFrameLowering::spillCalleeSavedRegisters, a few selected registers =
are also spilled in PPCFrameLowering::emitPrologue.  Those registers are =
the frame pointer, base pointer, PIC base pointer, link register, and =
condition code register.  For the latter two, code ensures that they can =
never be spilled in both places (for CR, there is extra code in =
spillCalleeSavedRegisters; for LR, the register is removed from =
SavedRegs in determineCalleeSaves).
>>>=20
>>> However, for FP, BP, and PBP, nothing ensures the registers are not =
spilled twice.  It is probably *rare* for this to happen, because the =
register allocator will not use those registers within the function if =
they're needed for their special purpose, but it can happen in rare =
cases.  This includes the case of a system unwinder routine that uses =
__builtin_unwind_init, but could also include other routines that =
clobber one of those registers, e.g. the following case:
>>>=20
>>> void func (void);
>>>=20
>>> void test (void)
>>> {
>>> func ();
>>> asm ("nop" : : : "31");
>>> }
>>>=20
>>> When it happens that a register is spilled twice, the code as such =
still works correctly, but the DWARF CFI unwind info associated with the =
routine will be broken, which can mess up both C++ exception handling =
and debugging.
>>>=20
>>> 3) For the specific case of system unwinder routines that use =
__builtin_unwind_init and/or __builtin_eh_return, special things need to =
happen in the prolog and epilog that are not required for any other =
routine.  This in particular includes setting up save areas and CFI =
records for the EH data registers (r3 ... r6).  [See bug #26844. ]  For =
the ELFv2 ABI (powerpc64le), it also include using three separate save =
areas for the three caller-saved condition register fields, so that the =
EH logic can overwrite their values independently.
>>>=20
>>> None of this is currently implemented in LLVM, since on Linux =
generally GCC is used to build the system unwind libraries, and no other =
code in the system ever needs those special constructs.
>>=20
>>=20
>> =3D=3D=3D
>> Mark Millard
>> markmi at dsl-only.net
>=20
> One point of his note is wrong: when the 2nd "spill" of a register is =
after it had been changed it makes a bigger difference. I commented =
back:
>=20
>=20
>> However, for FP, BP, and PBP, nothing ensures the registers are not =
spilled
>> twice.. . .
>>=20
>> When it happens that a register is spilled twice, the code as such =
still
>> works correctly, but the DWARF CFI unwind info associated with the =
routine
>> will be broken, which can mess up both C++ exception handling and =
debugging.
>=20
>=20
> I will note that the Frame Pointer Register (r31) being saved again to =
the same location but after it was adjusted to match the adjusted stack =
pointer in the callee does not work correctly in that the restore of the =
Frame Pointer for the return to the caller will restore the wrong =
pointer value.
>=20
> If the caller then uses r31 without separately also restoring r31 =
first then it will be addressing the wrong memory on the stack.
>=20
> The observed/reported code sequence had the 2nd r31 store in the =
callee after r31 had been adjusted to match the adjusted stack pointer =
in the callee.
>=20
> So more than C++ exception handling and debugging is broken for the =
reported code sequence.

The new comments are. . .

> Comment # 9 on bug 26856 from Ulrich Weigand
> (In reply to comment #8)
>=20
> > (In reply to comment #6
> )
> >=20
> > > However, for FP, BP, and PBP, nothing ensures the registers are =
not spilled
> > > twice.. . .
> > >=20
> > > When it happens that a register is spilled twice, the code as such =
still
> > > works correctly, but the DWARF CFI unwind info associated with the =
routine
> > > will be broken, which can mess up both C++ exception handling and =
debugging.
> >=20
> > I will note that the Frame Pointer Register (r31) being saved again =
to the
> > same location but after it was adjusted to match the adjusted stack =
pointer
> > in the callee does not work correctly in that the restore of the =
Frame
> > Pointer for the return to the caller will restore the wrong pointer =
value.
> >=20
> > If the caller then uses r31 without separately also restoring r31 =
first then
> > it will be addressing the wrong memory on the stack.
> >=20
> > The observed/reported code sequence had the 2nd r31 store in the =
callee
> > after r31 had been adjusted to match the adjusted stack pointer in =
the
> > callee.
> >=20
> > So more than C++ exception handling and debugging is broken for the =
reported
> > code sequence.
>=20
>=20
> Ah, right.  I had been under the impression that the back-end would =
use two
> different save areas, but indeed it does use the same area, just =
addressed
> slightly differently.  The resulting code is then just simply =
incorrect.

and. . .

> Comment # 10 on bug 26856 from Ulrich Weigand
> (In reply to comment #7)
>=20
>=20
> > The observed behavior for the powerpc (what should be) SVR4 context =
is that
> > the save/restore logic for CR fields 2, 3, 4 is present but no =
.eh_frame
> > information is written out for the EH logic to use for CR.
>=20
>=20
> Huh, indeed.  This is yet another bug, which also affects functions =
for the
> powerpc (SVR4) ABI in general, not just unwind system routines.
>=20
> This seems to be a logic issue here:
>=20
>       // For SVR4, don't emit a move for the CR spill slot if we =
haven't
>       // spilled CRs.
>       if (isSVR4ABI && (PPC::CR2 <=3D Reg && Reg <=3D PPC::CR4)
>           && !MustSaveCR)
>         continue;
>=20
> MustSaveCR is always false for 32-bit, it is only used on 64-bit.  =
This has the
> effect that on 32-bit, we never get any CFI for the CRs.



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





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2ADD6542-E994-4FF9-B743-F6A03B1DCBCC>