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]>