On Tue, Aug 27, 2019 at 01:58:22PM -0400, George Koehler wrote:

> On Tue, 27 Aug 2019 14:30:50 +0200
> Otto Moerbeek <[email protected]> wrote:
> 
> > What I'm seeing is (in jump_ppc32_sysv_elf_gas.S/jump_context)
> > register r3 that is supposed to point to the memory that will receive
> > the transfer_t (the return value of jump_fcontext()) is 0.
> > 
> >     # return transfer_t
> >     stw  %r6, 0(%r3)
> >     stw  %r5, 4(%r3)
> 
> Ouch.  This code is for Linux; there is a secret incompatibility
> between BSD and Linux on 32-bit PowerPC.  These systems have almost
> the same System V ABI, but differ when returning a small struct of up
> to 8 bytes.  transfer_t from <boost/context/detail/fcontext.hpp> is
> such a struct: its 2 pointers measure 8 bytes.  BSD has no return area
> in %r3; the callee should return the transfer_t in %r3 and %r4.  The
> params were in %r4 and %r5 in Linux, but are in %r3 and %r4 in BSD.
> 
> The fixes might be to
> 
>  - delete the lines `stw %r3, 228(%r1)` and `lwz %r3, 228(%r1)`,
>    because the return area no longer exists.
>  - change `mr %r1, %r4` to `mr %r1, %r3`, because first param is %r3.
>  - change `stw %r6, 0(%r3)` to `mr %r3, %r6` (move to %r3 from %r6),
>    because first word of transfer_t is %r3.
>  - delete `stw %r5, 4(%r3)`, because second param is %r4, and second
>    word of transfer_t is %r4, so we would move %r4 to itself.
> 
> One might guard the changes with #ifdef __Linux__ ... #else ... #endif,
> because .S files go through the preprocessor.  The other *ppc32_sysv*.S
> files might also need changes.  I haven't tried these changes, because
> I will need to upgrade my macppc snapshot, then wait a few days for my
> PowerBook G4 to build boost and dependencies.
> 
> The System V ABI of 1995 [1], page 3-22, specified,
> > A structure or union whose size is less than or equal to 8 bytes shall be
> > returned in r3 and r4, as if it were first stored in an 8-byte aligned
> > memory area and then the low-addressed word were loaded into r3 and the
> > high-addressed word into r4.  Bits beyond the last member of the
> > structure or union are not defined.
> 
> For unknown reason, GCC for Linux ignores this and returns a small
> struct like a large struct (through a return area in %r3).  GCC for BSD
> does return a small struct in %r3 and %r4, but extends it to 4 or 8
> bytes by inserting bits before the first member, not "beyond the last
> member", given that the system is big-endian; so struct { char c; }
> puts c in the low byte of %r3, not the first byte.  By BSD, I mean at
> least OpenBSD and NetBSD; I didn't check FreeBSD.
> 
> The Linux ABI of 2011 [2] specified what GCC for Linux does.  LLVM and
> clang follow Linux (so code built with clang for OpenBSD/macppc crashes
> when it calls libraries built with gcc); boost is crashing because we
> use gcc in OpenBSD/macppc.
> 
> [1] https://refspecs.linuxbase.org/elf/elfspec_ppc.pdf
> [2] 
> https://www.polyomino.org.uk/publications/2011/Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf
> 
> -- 
> George Koehler <[email protected]>
> 

Thanks!

I was already thinking it would be something along this line, i386 has
similar issue I fixed a few months ago.

A first shot did not work here, so if you can take a closer look please
do. In the meantime I'll try to do so as well after reading up on the ABI.

        -Otto

Reply via email to