mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
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
340 lines
12 KiB
Zig
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;
|
|
};
|