On Mon, Jun 29, 2026 at 9:47 AM Damien Zammit <[email protected]> wrote:
> It seems complex_alignof = 4 is causing the structures to recompute
> their member sizes.  Now while the total number of bytes still matches,
> on (__LP64__ && USER32) kernel with 32 bit userspace, mig_usize is
> computed differently in the user32 case, thus we get a MIG_TYPE_ERROR on
> some RPCs that use 64 bit types embedded in structs.

To add some more context from my side (as discussed on IRC):

In versions of Mach that use "typed IPC" (such as in our case GNU
Mach), an IPC message body logically consists of elements (items,
fields — I don't remember if there's an established term for this)
that have types like MACH_MSG_TYPE_INTEGER_32 (a 32-bit integer) and
MACH_MSG_TYPE_COPY_SEND (Mach port right with copy-send semantics) and
arrays of those (plus out-of-line types). On each particular CPU
architecture / ABI, such a sequence of elements has an in-memory
layout, with endianness, alignment/padding, and such. But logically
those are not a part of the message, that's just how a message is
represented in-memory for a particular ABI.

Consider also that Mach IPC was supposed to be network-transparent
(see netname / netmsg and NORMA). The two peers might be running with
different ABIs, perhaps one is big-endian 32-bit PPC and the other is
little-endian 64-bit AArch64, or something like that. The way a
message would be laid out in memory would be quite different between
these two peers, but the logical contents of a message (e.g. a 32-bit
integer with the value of 1234, followed by a C string saying "test",
followed by an array of 4 booleans with the values {true, false,
false, true}) would be identical. The way the message would be
represented over the network is probably some yet different
ABI/format, what's important is that it preserves this logical
structure of the message.

Even without actual network transparency, there's an issue of doing
local messaging between tasks/peers using a different ABI. Apple had
PPC and x86 processes coexisting, and now x86_64 and AArch64 ones
(though they use untyped MIG); we decided against supporting multiple
userland ABIs on the same kernel, but we still have the different ABIs
between the kernel and the userland when running in user32 mode.

I'm saying all this to emphasize that 'struct [4] of
(MACH_MSG_TYPE_INTEGER_32, 32)' and 'struct [2] of
(MACH_MSG_TYPE_INTEGER_64, 64)' are not the same thing at all, even
though they have a similar/identical in-memory layout on some ABIs.
There is no 'struct' at Mach IPC level, that's a MIG concept, but one
produces an array of 4 MACH_MSG_TYPE_INTEGER_32's, and the other an
array of 2 MACH_MSG_TYPE_INTEGER_64's, and those are different types.

So with the new-style structs, MIG takes the same type definition, such as

type new_style_struct_t = struct { int64_t field; };

and maps it to different Mach IPC level field types, depending on the
local ABI. That's not great.

Sergey

Reply via email to