zig/lib/std/c/haiku.zig
mlugg a18fd41064
std: rework/remove ucontext_t
Our usage of `ucontext_t` in the standard library was kind of
problematic. We unnecessarily mimiced libc-specific structures, and our
`getcontext` implementation was overkill for our use case of stack
tracing.

This commit introduces a new namespace, `std.debug.cpu_context`, which
contains "context" types for various architectures (currently x86,
x86_64, ARM, and AARCH64) containing the general-purpose CPU registers;
the ones needed in practice for stack unwinding. Each implementation has
a function `current` which populates the structure using inline
assembly. The structure is user-overrideable, though that should only be
necessary if the standard library does not have an implementation for
the *architecture*: that is to say, none of this is OS-dependent.

Of course, in POSIX signal handlers, we get a `ucontext_t` from the
kernel. The function `std.debug.cpu_context.fromPosixSignalContext`
converts this to a `std.debug.cpu_context.Native` with a big ol' target
switch.

This functionality is not exposed from `std.c` or `std.posix`, and
neither are `ucontext_t`, `mcontext_t`, or `getcontext`. The rationale
is that these types and functions do not conform to a specific ABI, and
in fact tend to get updated over time based on CPU features and
extensions; in addition, different libcs use different structures which
are "partially compatible" with the kernel structure. Overall, it's a
mess, but all we need is the kernel context, so we can just define a
kernel-compatible structure as long as we don't claim C compatibility by
putting it in `std.c` or `std.posix`.

This change resulted in a few nice `std.debug` simplifications, but
nothing too noteworthy. However, the main benefit of this change is that
DWARF unwinding---sometimes necessary for collecting stack traces
reliably---now requires far less target-specific integration.

Also fix a bug I noticed in `PageAllocator` (I found this due to a bug
in my distro's QEMU distribution; thanks, broken QEMU patch!) and I
think a couple of minor bugs in `std.debug`.

Resolves: #23801
Resolves: #23802
2025-09-30 13:44:54 +01:00

340 lines
12 KiB
Zig

const std = @import("../std.zig");
const assert = std.debug.assert;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
const iovec = std.posix.iovec;
const iovec_const = std.posix.iovec_const;
const socklen_t = std.c.socklen_t;
const fd_t = std.c.fd_t;
const PATH_MAX = std.c.PATH_MAX;
const uid_t = std.c.uid_t;
const gid_t = std.c.gid_t;
const dev_t = std.c.dev_t;
const ino_t = std.c.ino_t;
comptime {
assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS.
}
pub extern "root" fn _errnop() *i32;
pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64;
pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32;
pub extern "root" fn get_system_info(system_info: *system_info) usize;
pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32;
pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32;
pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32;
pub extern "root" fn _kern_get_current_team() team_id;
pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t;
pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize;
pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t;
pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t;
pub const area_info = extern struct {
area: u32,
name: [32]u8,
size: usize,
lock: u32,
protection: u32,
team_id: i32,
ram_size: u32,
copy_count: u32,
in_count: u32,
out_count: u32,
address: *anyopaque,
};
pub const image_info = extern struct {
id: u32,
image_type: u32,
sequence: i32,
init_order: i32,
init_routine: *anyopaque,
term_routine: *anyopaque,
device: i32,
node: i64,
name: [PATH_MAX]u8,
text: *anyopaque,
data: *anyopaque,
text_size: i32,
data_size: i32,
api_version: i32,
abi: i32,
};
pub const system_info = extern struct {
boot_time: i64,
cpu_count: u32,
max_pages: u64,
used_pages: u64,
cached_pages: u64,
block_cache_pages: u64,
ignored_pages: u64,
needed_memory: u64,
free_memory: u64,
max_swap_pages: u64,
free_swap_pages: u64,
page_faults: u32,
max_sems: u32,
used_sems: u32,
max_ports: u32,
used_ports: u32,
max_threads: u32,
used_threads: u32,
max_teams: u32,
used_teams: u32,
kernel_name: [256]u8,
kernel_build_date: [32]u8,
kernel_build_time: [32]u8,
kernel_version: i64,
abi: u32,
};
pub const team_info = extern struct {
team_id: i32,
thread_count: i32,
image_count: i32,
area_count: i32,
debugger_nub_thread: i32,
debugger_nub_port: i32,
argc: i32,
args: [64]u8,
uid: uid_t,
gid: gid_t,
};
pub const directory_which = enum(i32) {
B_USER_SETTINGS_DIRECTORY = 0xbbe,
_,
};
pub const area_id = i32;
pub const port_id = i32;
pub const sem_id = i32;
pub const team_id = i32;
pub const thread_id = i32;
pub const E = enum(i32) {
pub const B_GENERAL_ERROR_BASE: i32 = std.math.minInt(i32);
pub const B_OS_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x1000;
pub const B_APP_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x2000;
pub const B_INTERFACE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x3000;
pub const B_MEDIA_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x4000;
pub const B_TRANSLATION_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x4800;
pub const B_MIDI_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x5000;
pub const B_STORAGE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x6000;
pub const B_POSIX_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x7000;
pub const B_MAIL_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x8000;
pub const B_PRINT_ERROR_BASE = B_GENERAL_ERROR_BASE + 0x9000;
pub const B_DEVICE_ERROR_BASE = B_GENERAL_ERROR_BASE + 0xa000;
pub const B_ERRORS_END = B_GENERAL_ERROR_BASE + 0xffff;
pub const B_NO_MEMORY = B_GENERAL_ERROR_BASE + 0;
pub const B_IO_ERROR = B_GENERAL_ERROR_BASE + 1;
pub const B_PERMISSION_DENIED = B_GENERAL_ERROR_BASE + 2;
pub const B_BAD_INDEX = B_GENERAL_ERROR_BASE + 3;
pub const B_BAD_TYPE = B_GENERAL_ERROR_BASE + 4;
pub const B_BAD_VALUE = B_GENERAL_ERROR_BASE + 5;
pub const B_MISMATCHED_VALUES = B_GENERAL_ERROR_BASE + 6;
pub const B_NAME_NOT_FOUND = B_GENERAL_ERROR_BASE + 7;
pub const B_NAME_IN_USE = B_GENERAL_ERROR_BASE + 8;
pub const B_TIMED_OUT = B_GENERAL_ERROR_BASE + 9;
pub const B_INTERRUPTED = B_GENERAL_ERROR_BASE + 10;
pub const B_WOULD_BLOCK = B_GENERAL_ERROR_BASE + 11;
pub const B_CANCELED = B_GENERAL_ERROR_BASE + 12;
pub const B_NO_INIT = B_GENERAL_ERROR_BASE + 13;
pub const B_NOT_INITIALIZED = B_GENERAL_ERROR_BASE + 13;
pub const B_BUSY = B_GENERAL_ERROR_BASE + 14;
pub const B_NOT_ALLOWED = B_GENERAL_ERROR_BASE + 15;
pub const B_BAD_DATA = B_GENERAL_ERROR_BASE + 16;
pub const B_DONT_DO_THAT = B_GENERAL_ERROR_BASE + 17;
pub const B_BAD_IMAGE_ID = B_OS_ERROR_BASE + 0x300;
pub const B_BAD_ADDRESS = B_OS_ERROR_BASE + 0x301;
pub const B_NOT_AN_EXECUTABLE = B_OS_ERROR_BASE + 0x302;
pub const B_MISSING_LIBRARY = B_OS_ERROR_BASE + 0x303;
pub const B_MISSING_SYMBOL = B_OS_ERROR_BASE + 0x304;
pub const B_UNKNOWN_EXECUTABLE = B_OS_ERROR_BASE + 0x305;
pub const B_LEGACY_EXECUTABLE = B_OS_ERROR_BASE + 0x306;
pub const B_FILE_ERROR = B_STORAGE_ERROR_BASE + 0;
pub const B_FILE_EXISTS = B_STORAGE_ERROR_BASE + 2;
pub const B_ENTRY_NOT_FOUND = B_STORAGE_ERROR_BASE + 3;
pub const B_NAME_TOO_LONG = B_STORAGE_ERROR_BASE + 4;
pub const B_NOT_A_DIRECTORY = B_STORAGE_ERROR_BASE + 5;
pub const B_DIRECTORY_NOT_EMPTY = B_STORAGE_ERROR_BASE + 6;
pub const B_DEVICE_FULL = B_STORAGE_ERROR_BASE + 7;
pub const B_READ_ONLY_DEVICE = B_STORAGE_ERROR_BASE + 8;
pub const B_IS_A_DIRECTORY = B_STORAGE_ERROR_BASE + 9;
pub const B_NO_MORE_FDS = B_STORAGE_ERROR_BASE + 10;
pub const B_CROSS_DEVICE_LINK = B_STORAGE_ERROR_BASE + 11;
pub const B_LINK_LIMIT = B_STORAGE_ERROR_BASE + 12;
pub const B_BUSTED_PIPE = B_STORAGE_ERROR_BASE + 13;
pub const B_UNSUPPORTED = B_STORAGE_ERROR_BASE + 14;
pub const B_PARTITION_TOO_SMALL = B_STORAGE_ERROR_BASE + 15;
pub const B_PARTIAL_READ = B_STORAGE_ERROR_BASE + 16;
pub const B_PARTIAL_WRITE = B_STORAGE_ERROR_BASE + 17;
SUCCESS = 0,
@"2BIG" = B_POSIX_ERROR_BASE + 1,
CHILD = B_POSIX_ERROR_BASE + 2,
DEADLK = B_POSIX_ERROR_BASE + 3,
FBIG = B_POSIX_ERROR_BASE + 4,
MLINK = B_POSIX_ERROR_BASE + 5,
NFILE = B_POSIX_ERROR_BASE + 6,
NODEV = B_POSIX_ERROR_BASE + 7,
NOLCK = B_POSIX_ERROR_BASE + 8,
NOSYS = B_POSIX_ERROR_BASE + 9,
NOTTY = B_POSIX_ERROR_BASE + 10,
NXIO = B_POSIX_ERROR_BASE + 11,
SPIPE = B_POSIX_ERROR_BASE + 12,
SRCH = B_POSIX_ERROR_BASE + 13,
FPOS = B_POSIX_ERROR_BASE + 14,
SIGPARM = B_POSIX_ERROR_BASE + 15,
DOM = B_POSIX_ERROR_BASE + 16,
RANGE = B_POSIX_ERROR_BASE + 17,
PROTOTYPE = B_POSIX_ERROR_BASE + 18,
PROTONOSUPPORT = B_POSIX_ERROR_BASE + 19,
PFNOSUPPORT = B_POSIX_ERROR_BASE + 20,
AFNOSUPPORT = B_POSIX_ERROR_BASE + 21,
ADDRINUSE = B_POSIX_ERROR_BASE + 22,
ADDRNOTAVAIL = B_POSIX_ERROR_BASE + 23,
NETDOWN = B_POSIX_ERROR_BASE + 24,
NETUNREACH = B_POSIX_ERROR_BASE + 25,
NETRESET = B_POSIX_ERROR_BASE + 26,
CONNABORTED = B_POSIX_ERROR_BASE + 27,
CONNRESET = B_POSIX_ERROR_BASE + 28,
ISCONN = B_POSIX_ERROR_BASE + 29,
NOTCONN = B_POSIX_ERROR_BASE + 30,
SHUTDOWN = B_POSIX_ERROR_BASE + 31,
CONNREFUSED = B_POSIX_ERROR_BASE + 32,
HOSTUNREACH = B_POSIX_ERROR_BASE + 33,
NOPROTOOPT = B_POSIX_ERROR_BASE + 34,
NOBUFS = B_POSIX_ERROR_BASE + 35,
INPROGRESS = B_POSIX_ERROR_BASE + 36,
ALREADY = B_POSIX_ERROR_BASE + 37,
ILSEQ = B_POSIX_ERROR_BASE + 38,
NOMSG = B_POSIX_ERROR_BASE + 39,
STALE = B_POSIX_ERROR_BASE + 40,
OVERFLOW = B_POSIX_ERROR_BASE + 41,
MSGSIZE = B_POSIX_ERROR_BASE + 42,
OPNOTSUPP = B_POSIX_ERROR_BASE + 43,
NOTSOCK = B_POSIX_ERROR_BASE + 44,
HOSTDOWN = B_POSIX_ERROR_BASE + 45,
BADMSG = B_POSIX_ERROR_BASE + 46,
CANCELED = B_POSIX_ERROR_BASE + 47,
DESTADDRREQ = B_POSIX_ERROR_BASE + 48,
DQUOT = B_POSIX_ERROR_BASE + 49,
IDRM = B_POSIX_ERROR_BASE + 50,
MULTIHOP = B_POSIX_ERROR_BASE + 51,
NODATA = B_POSIX_ERROR_BASE + 52,
NOLINK = B_POSIX_ERROR_BASE + 53,
NOSR = B_POSIX_ERROR_BASE + 54,
NOSTR = B_POSIX_ERROR_BASE + 55,
NOTSUP = B_POSIX_ERROR_BASE + 56,
PROTO = B_POSIX_ERROR_BASE + 57,
TIME = B_POSIX_ERROR_BASE + 58,
TXTBSY = B_POSIX_ERROR_BASE + 59,
NOATTR = B_POSIX_ERROR_BASE + 60,
NOTRECOVERABLE = B_POSIX_ERROR_BASE + 61,
OWNERDEAD = B_POSIX_ERROR_BASE + 62,
NOMEM = B_NO_MEMORY,
ACCES = B_PERMISSION_DENIED,
INTR = B_INTERRUPTED,
IO = B_IO_ERROR,
BUSY = B_BUSY,
FAULT = B_BAD_ADDRESS,
TIMEDOUT = B_TIMED_OUT,
/// Also used for WOULDBLOCK
AGAIN = B_WOULD_BLOCK,
BADF = B_FILE_ERROR,
EXIST = B_FILE_EXISTS,
INVAL = B_BAD_VALUE,
NAMETOOLONG = B_NAME_TOO_LONG,
NOENT = B_ENTRY_NOT_FOUND,
PERM = B_NOT_ALLOWED,
NOTDIR = B_NOT_A_DIRECTORY,
ISDIR = B_IS_A_DIRECTORY,
NOTEMPTY = B_DIRECTORY_NOT_EMPTY,
NOSPC = B_DEVICE_FULL,
ROFS = B_READ_ONLY_DEVICE,
MFILE = B_NO_MORE_FDS,
XDEV = B_CROSS_DEVICE_LINK,
LOOP = B_LINK_LIMIT,
NOEXEC = B_NOT_AN_EXECUTABLE,
PIPE = B_BUSTED_PIPE,
_,
};
pub const status_t = i32;
pub const DirEnt = extern struct {
/// device
dev: dev_t,
/// parent device (only for queries)
pdev: dev_t,
/// inode number
ino: ino_t,
/// parent inode (only for queries)
pino: ino_t,
/// length of this record, not the name
reclen: u16,
/// name of the entry (null byte terminated)
name: [0]u8,
pub fn getName(dirent: *const DirEnt) [*:0]const u8 {
return @ptrCast(&dirent.name);
}
};
// https://github.com/haiku/haiku/blob/2aab5f5f14aeb3f34c3a3d9a9064cc3c0d914bea/headers/posix/netinet/in.h#L122
pub const IP = struct {
pub const OPTIONS = 1;
pub const HDRINCL = 2;
pub const TOS = 3;
pub const TTL = 4;
pub const RECVOPTS = 5;
pub const RECVRETOPTS = 6;
pub const RECVDSTADDR = 7;
pub const RETOPTS = 8;
pub const MULTICAST_IF = 9;
pub const MULTICAST_TTL = 10;
pub const MULTICAST_LOOP = 11;
pub const ADD_MEMBERSHIP = 12;
pub const DROP_MEMBERSHIP = 13;
pub const BLOCK_SOURCE = 14;
pub const UNBLOCK_SOURCE = 15;
pub const ADD_SOURCE_MEMBERSHIP = 16;
pub const DROP_SOURCE_MEMBERSHIP = 17;
pub const DONTFRAG = 38;
};
// https://github.com/haiku/haiku/blob/2aab5f5f14aeb3f34c3a3d9a9064cc3c0d914bea/headers/posix/netinet/in.h#L150
pub const IPV6 = struct {
pub const MULTICAST_IF = 24;
pub const MULTICAST_HOPS = 25;
pub const MULTICAST_LOOP = 26;
pub const UNICAST_HOPS = 27;
pub const JOIN_GROUP = 28;
pub const LEAVE_GROUP = 29;
pub const V6ONLY = 30;
pub const PKTINFO = 31;
pub const RECVPKTINFO = 32;
pub const HOPLIMIT = 33;
pub const RECVHOPLIMIT = 34;
pub const HOPOPTS = 35;
pub const DSTOPTS = 36;
pub const RTHDR = 37;
};
// https://github.com/haiku/haiku/blob/2aab5f5f14aeb3f34c3a3d9a9064cc3c0d914bea/headers/posix/netinet/ip.h#L36
pub const IPTOS = struct {
pub const RELIABILITY = 0x04;
pub const THROUGHPUT = 0x08;
pub const LOWDELAY = 0x10;
};