Personalities
A personality is the OS ABI a process expects. Every context carries one, and it drives syscall dispatch, argument translation, error encoding, signals, and process startup.
Supported personalities
| Personality | Value | Binary format | Status |
|---|---|---|---|
| Kernel (native) | 0 | ELF (native) | Native ABI, default |
| Linux | 1 | ELF (OS/ABI 0 or 3) | ~80/450 syscalls mapped |
| Windows (NT) | 2 | PE (machine 0x8664 / 0xAA64) | Not started |
| Darwin (macOS) | 3 | Mach-O (x86_64 / arm64) | Not started |
| FreeBSD | 4 | ELF (OS/ABI 9) | Not started |
| NetBSD | 5 | ELF (OS/ABI 2) | Not started |
| OpenBSD | 6 | ELF (OS/ABI 12) | Not started |
The numeric values are the on-wire representation stored in each Context and shared with the Zig layer; they match the C enum in include/personality.h.
Detection
Personality is detected from the binary during exec(), before the first return to userspace. The Zig layer provides the detection helpers:
ELF — fromElfOsAbi(osabi, machine)
Reads e_ident[EI_OSABI]:
| OS/ABI byte | Meaning | Personality |
|---|---|---|
| 0 | ELFOSABI_NONE (System V) | Linux (most common default) |
| 3 | ELFOSABI_LINUX / GNU | Linux |
| 9 | ELFOSABI_FREEBSD | FreeBSD |
| 2 | ELFOSABI_NETBSD | NetBSD |
| 12 | ELFOSABI_OPENBSD | OpenBSD |
| other | — | native kernel |
Modern Linux toolchains emit ELFOSABI_NONE, so 0 is treated as Linux by default; the loader may override based on other signals.
PE — fromPe(machine, subsystem)
Maps the PE machine type (0x8664 AMD64, 0xAA64 ARM64, 0x14C i386, …) to the Windows personality.
Mach-O — fromMachO(cputype, filetype)
Maps the Mach-O cputype (0x01000000 arm64, 0x00000007 x86_64, …) to the Darwin personality.
Wiring status
These helpers are implemented and unit-tested in Zig, but the Rust exec() path does not yet call them — contexts currently default to the native personality. Wiring this is part of the M1 milestone. See ELF & ABI spec.
Per-OS conventions
Different personalities encode results differently. The Zig dispatcher re-encodes the kernel's -errno/value convention into:
- Linux — negative errno in the return register (no carry flag on x86_64).
- Windows — NTSTATUS return convention.
- *Darwin / BSD — error signalled via the carry flag on x86_64 (value in the return register otherwise).
Adding a new personality
- Add a variant to the
Personalityenum (personality/src/personality.zig). - Add a detection clause in
fromElfOsAbi()/fromPe()/fromMachO(). - Create
personality/src/<name>/tables.zigwith the syscall-number table. - Create
personality/src/<name>/shim.zigwith argument/structure translators. - Wire dispatch in
personality/src/main.zig. - Add binary-format loading on the Rust side (
src/elf.rs, futuresrc/pe.rs/src/macho.rs).
See the generated Personality Components for the current Zig surface.