Trona
Trona is the system library that sits between the kernite microkernel and every userspace program in SaltyOS. It is what userspace actually calls when a C function from basalt (libc.so) or a Rust-native program needs to talk to the kernel, to another server, or to a capability object.
Everything in basaltc (the C standard library) is a thin wrapper that converts a POSIX-shaped call into a trona_posix::* call, which in turn builds an IPC message and sends it through a capability to a server or to the kernel.
Understanding trona is therefore the prerequisite for understanding how any userspace code actually reaches the kernel.
The five layers of trona
The tree under lib/trona/ is organized as three built Rust crates + shared UAPI sources + two C dynamic linkers + a standalone C Win32 stub + arch-specific assembly and linker scripts.
| Layer | Produces | Role |
|---|---|---|
substrate ( |
|
Core kernel ABI. Syscall wrappers, IPC, typed capability invocation, slot allocator, futex-based sync primitives, TLS/thread infrastructure, VA and CSpace layout planners, startup capability table, worker pool, serial logging. |
uapi (source tree, not a crate) |
included via |
Shared kernel↔userland contract: syscall numbers, invoke labels, IPC protocol labels, error codes, |
trona_posix crate |
|
POSIX-shaped Rust API. Every function delegates to a substrate IPC call targeting VFS, procmgr, mmsrv, dnssrv, or a kernel invoke. This is what basaltc’s C ABI wrappers call. |
trona_loader crate |
|
ELF64 / PE32+ / CPIO newc binary loading. Scratch-map page loading strategy, ET_EXEC / ET_DYN handling, DT_NEEDED extraction, PE import directory parsing. Used by init and procmgr when spawning children. |
rtld/elf (C, freestanding) |
|
ELF runtime dynamic linker. Parses auxv, self-relocates, walks DT_NEEDED from the initrd CPIO, finalizes static TLS, exports TLS metadata and role-based capability slots into |
rtld/pe (C, freestanding) |
|
PE runtime dynamic linker. Validates the PE image, applies base relocations, resolves imports against a pre-mapped |
win32 (C + Rust source) |
|
Win32 subsystem support. |
posix/arch and arch |
|
Architecture-specific assembly ( |
What is bundled into libtrona.so
libtrona.so is the single shared object loaded by every dynamic SaltyOS process (after ld-trona.so finishes rtld bootstrapping).
It is produced by the top-level lib/trona/meson.build by linking six object files with the architecture-specific linker script arch/<arch>/libtrona.ld:
libtrona.so =
libtrona.o ← trona substrate crate
+ libtrona_posix.o ← trona_posix crate
+ libtrona_loader.o ← trona_loader crate
+ fork.o ← posix/arch/<arch>/fork.S
+ libcore.o ← Rust core library
+ libcompiler_builtins.o ← Rust compiler intrinsics
Everything else is built separately and has its own output:
| Artifact | Source |
|---|---|
|
|
|
|
|
|
This separation matters: ld-trona.so must run before libtrona.so is available (it is the component that loads libtrona.so), so rtld is freestanding — no libc, no libtrona, only inline syscalls and its own self-contained ELF parser.
basalt and trona
basalt (libc) does not talk to the kernel directly.
Every non-trivial C standard library function in basaltc is a thin #[unsafe(no_mangle)] pub extern "C" wrapper that delegates to trona_posix::*.
trona_posix::* in turn uses trona::ipc::* (from substrate) to build a TronaMsg, targets the appropriate well-known capability from trona::caps::*, and makes a call or send syscall.
The layering looks like this:
┌────────────────────────────────┐
│ Application │
├────────────────────────────────┤
│ basaltc (libc.so) │ ← POSIX C ABI surface
│ basalt::stdio::fprintf │
│ basalt::unistd::write │
├────────────────────────────────┤
│ trona_posix │ ← Rust POSIX client
│ posix_write → VFS_WRITE │
├────────────────────────────────┤
│ trona substrate │ ← Kernel ABI + IPC
│ ipc::call_ctx │
│ syscall::syscall(SYS_CALL) │
├────────────────────────────────┤
│ kernite │ ← Microkernel
└────────────────────────────────┘
basalt’s trona-boundary page documents this handoff from the basalt side.
This component (trona) documents the same boundary from the other side: what happens once trona_posix is called, and how the substrate talks to the kernel.
Where to start reading
If you are new to trona, the recommended reading order is:
-
Architecture — crate map, module list, and dependency direction
-
substrate Overview — the 18 modules that make up the core runtime
-
IPC — the message format every server call in SaltyOS uses
-
Capability Invocation — how userspace drives the kernel through capabilities
-
Syscall ABI — the register-level kernel contract
-
ELF Dynamic Linker — what actually runs before
main
From there, Reading the trona Tree shows how to navigate the source tree, and Adding a Syscall or Invoke walks through the full contribution flow for a new kernel operation.
Related pages
-
kernite — the microkernel itself. Everything in trona substrate is a wrapper over something kernite implements.
-
basalt — the C standard library that sits on top of
trona_posix. -
basalt: The trona boundary — the same handoff viewed from libc.