zig/lib/std/c/darwin.zig
Jacob Young d10c52c194 AstGen: disallow alignment on function types
A pointer type already has an alignment, so this information does not
need to be duplicated on the function type.  This already has precedence
with addrspace which is already disallowed on function types for this
reason.  Also fixes `@TypeOf(&func)` to have the correct addrspace and
alignment.
2024-03-17 03:06:17 +01:00

3565 lines
104 KiB
Zig

const std = @import("../std.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
const macho = std.macho;
const native_arch = builtin.target.cpu.arch;
const maxInt = std.math.maxInt;
const iovec_const = std.os.iovec_const;
pub const aarch64 = @import("darwin/aarch64.zig");
pub const x86_64 = @import("darwin/x86_64.zig");
pub const cssm = @import("darwin/cssm.zig");
const arch_bits = switch (native_arch) {
.aarch64 => @import("darwin/aarch64.zig"),
.x86_64 => @import("darwin/x86_64.zig"),
else => struct {},
};
pub const EXC_TYPES_COUNT = arch_bits.EXC_TYPES_COUNT;
pub const THREAD_STATE_NONE = arch_bits.THREAD_STATE_NONE;
pub const EXC = enum(exception_type_t) {
NULL = 0,
/// Could not access memory
BAD_ACCESS = 1,
/// Instruction failed
BAD_INSTRUCTION = 2,
/// Arithmetic exception
ARITHMETIC = 3,
/// Emulation instruction
EMULATION = 4,
/// Software generated exception
SOFTWARE = 5,
/// Trace, breakpoint, etc.
BREAKPOINT = 6,
/// System calls.
SYSCALL = 7,
/// Mach system calls.
MACH_SYSCALL = 8,
/// RPC alert
RPC_ALERT = 9,
/// Abnormal process exit
CRASH = 10,
/// Hit resource consumption limit
RESOURCE = 11,
/// Violated guarded resource protections
GUARD = 12,
/// Abnormal process exited to corpse state
CORPSE_NOTIFY = 13,
};
pub const EXC_SOFT_SIGNAL = 0x10003;
pub const EXC_MASK_BAD_ACCESS = 1 << @intFromEnum(EXC.BAD_ACCESS);
pub const EXC_MASK_BAD_INSTRUCTION = 1 << @intFromEnum(EXC.BAD_INSTRUCTION);
pub const EXC_MASK_ARITHMETIC = 1 << @intFromEnum(EXC.ARITHMETIC);
pub const EXC_MASK_EMULATION = 1 << @intFromEnum(EXC.EMULATION);
pub const EXC_MASK_SOFTWARE = 1 << @intFromEnum(EXC.SOFTWARE);
pub const EXC_MASK_BREAKPOINT = 1 << @intFromEnum(EXC.BREAKPOINT);
pub const EXC_MASK_SYSCALL = 1 << @intFromEnum(EXC.SYSCALL);
pub const EXC_MASK_MACH_SYSCALL = 1 << @intFromEnum(EXC.MACH_SYSCALL);
pub const EXC_MASK_RPC_ALERT = 1 << @intFromEnum(EXC.RPC_ALERT);
pub const EXC_MASK_CRASH = 1 << @intFromEnum(EXC.CRASH);
pub const EXC_MASK_RESOURCE = 1 << @intFromEnum(EXC.RESOURCE);
pub const EXC_MASK_GUARD = 1 << @intFromEnum(EXC.GUARD);
pub const EXC_MASK_CORPSE_NOTIFY = 1 << @intFromEnum(EXC.CORPSE_NOTIFY);
pub const EXC_MASK_MACHINE = arch_bits.EXC_MASK_MACHINE;
pub const EXC_MASK_ALL = EXC_MASK_BAD_ACCESS |
EXC_MASK_BAD_INSTRUCTION |
EXC_MASK_ARITHMETIC |
EXC_MASK_EMULATION |
EXC_MASK_SOFTWARE |
EXC_MASK_BREAKPOINT |
EXC_MASK_SYSCALL |
EXC_MASK_MACH_SYSCALL |
EXC_MASK_RPC_ALERT |
EXC_MASK_RESOURCE |
EXC_MASK_GUARD |
EXC_MASK_MACHINE;
/// Send a catch_exception_raise message including the identity.
pub const EXCEPTION_DEFAULT = 1;
/// Send a catch_exception_raise_state message including the
/// thread state.
pub const EXCEPTION_STATE = 2;
/// Send a catch_exception_raise_state_identity message including
/// the thread identity and state.
pub const EXCEPTION_STATE_IDENTITY = 3;
/// Send a catch_exception_raise_identity_protected message including protected task
/// and thread identity.
pub const EXCEPTION_IDENTITY_PROTECTED = 4;
/// Prefer sending a catch_exception_raice_backtrace message, if applicable.
pub const MACH_EXCEPTION_BACKTRACE_PREFERRED = 0x20000000;
/// include additional exception specific errors, not used yet.
pub const MACH_EXCEPTION_ERRORS = 0x40000000;
/// Send 64-bit code and subcode in the exception header */
pub const MACH_EXCEPTION_CODES = 0x80000000;
pub const MACH_EXCEPTION_MASK = MACH_EXCEPTION_CODES |
MACH_EXCEPTION_ERRORS |
MACH_EXCEPTION_BACKTRACE_PREFERRED;
pub const TASK_NULL: task_t = 0;
pub const THREAD_NULL: thread_t = 0;
pub const MACH_PORT_NULL: mach_port_t = 0;
pub const MACH_MSG_TIMEOUT_NONE: mach_msg_timeout_t = 0;
pub const MACH_MSG_OPTION_NONE = 0x00000000;
pub const MACH_SEND_MSG = 0x00000001;
pub const MACH_RCV_MSG = 0x00000002;
pub const MACH_RCV_LARGE = 0x00000004;
pub const MACH_RCV_LARGE_IDENTITY = 0x00000008;
pub const MACH_SEND_TIMEOUT = 0x00000010;
pub const MACH_SEND_OVERRIDE = 0x00000020;
pub const MACH_SEND_INTERRUPT = 0x00000040;
pub const MACH_SEND_NOTIFY = 0x00000080;
pub const MACH_SEND_ALWAYS = 0x00010000;
pub const MACH_SEND_FILTER_NONFATAL = 0x00010000;
pub const MACH_SEND_TRAILER = 0x00020000;
pub const MACH_SEND_NOIMPORTANCE = 0x00040000;
pub const MACH_SEND_NODENAP = MACH_SEND_NOIMPORTANCE;
pub const MACH_SEND_IMPORTANCE = 0x00080000;
pub const MACH_SEND_SYNC_OVERRIDE = 0x00100000;
pub const MACH_SEND_PROPAGATE_QOS = 0x00200000;
pub const MACH_SEND_SYNC_USE_THRPRI = MACH_SEND_PROPAGATE_QOS;
pub const MACH_SEND_KERNEL = 0x00400000;
pub const MACH_SEND_SYNC_BOOTSTRAP_CHECKIN = 0x00800000;
pub const MACH_RCV_TIMEOUT = 0x00000100;
pub const MACH_RCV_NOTIFY = 0x00000000;
pub const MACH_RCV_INTERRUPT = 0x00000400;
pub const MACH_RCV_VOUCHER = 0x00000800;
pub const MACH_RCV_OVERWRITE = 0x00000000;
pub const MACH_RCV_GUARDED_DESC = 0x00001000;
pub const MACH_RCV_SYNC_WAIT = 0x00004000;
pub const MACH_RCV_SYNC_PEEK = 0x00008000;
pub const MACH_MSG_STRICT_REPLY = 0x00000200;
pub const ucontext_t = extern struct {
onstack: c_int,
sigmask: sigset_t,
stack: stack_t,
link: ?*ucontext_t,
mcsize: u64,
mcontext: *mcontext_t,
__mcontext_data: mcontext_t,
};
pub const mcontext_t = arch_bits.mcontext_t;
extern "c" fn __error() *c_int;
pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
pub extern "c" fn _dyld_image_count() u32;
pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;
pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;
pub extern "c" fn _dyld_get_image_name(image_index: u32) [*:0]const u8;
pub const COPYFILE_ACL = 1 << 0;
pub const COPYFILE_STAT = 1 << 1;
pub const COPYFILE_XATTR = 1 << 2;
pub const COPYFILE_DATA = 1 << 3;
pub const copyfile_state_t = *opaque {};
pub extern "c" fn fcopyfile(from: fd_t, to: fd_t, state: ?copyfile_state_t, flags: u32) c_int;
pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) isize;
pub extern "c" fn mach_absolute_time() u64;
pub extern "c" fn mach_continuous_time() u64;
pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) kern_return_t;
pub extern "c" fn malloc_size(?*const anyopaque) usize;
pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;
pub extern "c" fn kevent64(
kq: c_int,
changelist: [*]const kevent64_s,
nchanges: c_int,
eventlist: [*]kevent64_s,
nevents: c_int,
flags: c_uint,
timeout: ?*const timespec,
) c_int;
const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;
/// The value of the link editor defined symbol _MH_EXECUTE_SYM is the address
/// of the mach header in a Mach-O executable file type. It does not appear in
/// any file type other than a MH_EXECUTE file type. The type of the symbol is
/// absolute as the header is not part of any section.
/// This symbol is populated when linking the system's libc, which is guaranteed
/// on this operating system. However when building object files or libraries,
/// the system libc won't be linked until the final executable. So we
/// export a weak symbol here, to be overridden by the real one.
var dummy_execute_header: mach_hdr = undefined;
pub extern var _mh_execute_header: mach_hdr;
comptime {
if (builtin.target.isDarwin()) {
@export(dummy_execute_header, .{ .name = "_mh_execute_header", .linkage = .weak });
}
}
pub const mach_header_64 = macho.mach_header_64;
pub const mach_header = macho.mach_header;
pub const _errno = __error;
pub extern "c" fn @"close$NOCANCEL"(fd: fd_t) c_int;
pub extern "c" fn mach_host_self() mach_port_t;
pub extern "c" fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t;
pub const exception_type_t = c_int;
pub const exception_data_type_t = integer_t;
pub const exception_data_t = ?*mach_exception_data_type_t;
pub const mach_exception_data_type_t = i64;
pub const mach_exception_data_t = ?*mach_exception_data_type_t;
pub const vm_map_t = mach_port_t;
pub const vm_map_read_t = mach_port_t;
pub const vm_region_flavor_t = c_int;
pub const vm_region_info_t = *c_int;
pub const vm_region_recurse_info_t = *c_int;
pub const mach_vm_address_t = usize;
pub const vm_offset_t = usize;
pub const mach_vm_size_t = u64;
pub const mach_msg_bits_t = c_uint;
pub const mach_msg_id_t = integer_t;
pub const mach_msg_type_number_t = natural_t;
pub const mach_msg_type_name_t = c_uint;
pub const mach_msg_option_t = integer_t;
pub const mach_msg_size_t = natural_t;
pub const mach_msg_timeout_t = natural_t;
pub const mach_port_right_t = natural_t;
pub const task_t = mach_port_t;
pub const thread_port_t = task_t;
pub const thread_t = thread_port_t;
pub const exception_mask_t = c_uint;
pub const exception_mask_array_t = [*]exception_mask_t;
pub const exception_handler_t = mach_port_t;
pub const exception_handler_array_t = [*]exception_handler_t;
pub const exception_port_t = exception_handler_t;
pub const exception_port_array_t = exception_handler_array_t;
pub const exception_flavor_array_t = [*]thread_state_flavor_t;
pub const exception_behavior_t = c_uint;
pub const exception_behavior_array_t = [*]exception_behavior_t;
pub const thread_state_flavor_t = c_int;
pub const ipc_space_t = mach_port_t;
pub const ipc_space_port_t = ipc_space_t;
pub const MACH_PORT_RIGHT = enum(mach_port_right_t) {
SEND = 0,
RECEIVE = 1,
SEND_ONCE = 2,
PORT_SET = 3,
DEAD_NAME = 4,
/// Obsolete right
LABELH = 5,
/// Right not implemented
NUMBER = 6,
};
pub const MACH_MSG_TYPE = enum(mach_msg_type_name_t) {
/// Must hold receive right
MOVE_RECEIVE = 16,
/// Must hold send right(s)
MOVE_SEND = 17,
/// Must hold sendonce right
MOVE_SEND_ONCE = 18,
/// Must hold send right(s)
COPY_SEND = 19,
/// Must hold receive right
MAKE_SEND = 20,
/// Must hold receive right
MAKE_SEND_ONCE = 21,
/// NOT VALID
COPY_RECEIVE = 22,
/// Must hold receive right
DISPOSE_RECEIVE = 24,
/// Must hold send right(s)
DISPOSE_SEND = 25,
/// Must hold sendonce right
DISPOSE_SEND_ONCE = 26,
};
extern "c" var mach_task_self_: mach_port_t;
pub fn mach_task_self() callconv(.C) mach_port_t {
return mach_task_self_;
}
pub extern "c" fn mach_msg(
msg: ?*mach_msg_header_t,
option: mach_msg_option_t,
send_size: mach_msg_size_t,
rcv_size: mach_msg_size_t,
rcv_name: mach_port_name_t,
timeout: mach_msg_timeout_t,
notify: mach_port_name_t,
) kern_return_t;
pub const mach_msg_header_t = extern struct {
msgh_bits: mach_msg_bits_t,
msgh_size: mach_msg_size_t,
msgh_remote_port: mach_port_t,
msgh_local_port: mach_port_t,
msgh_voucher_port: mach_port_name_t,
msgh_id: mach_msg_id_t,
};
pub extern "c" fn task_get_exception_ports(
task: task_t,
exception_mask: exception_mask_t,
masks: exception_mask_array_t,
masks_cnt: *mach_msg_type_number_t,
old_handlers: exception_handler_array_t,
old_behaviors: exception_behavior_array_t,
old_flavors: exception_flavor_array_t,
) kern_return_t;
pub extern "c" fn task_set_exception_ports(
task: task_t,
exception_mask: exception_mask_t,
new_port: mach_port_t,
behavior: exception_behavior_t,
new_flavor: thread_state_flavor_t,
) kern_return_t;
pub const task_read_t = mach_port_t;
pub extern "c" fn task_resume(target_task: task_read_t) kern_return_t;
pub extern "c" fn task_suspend(target_task: task_read_t) kern_return_t;
pub extern "c" fn task_for_pid(target_tport: mach_port_name_t, pid: pid_t, t: *mach_port_name_t) kern_return_t;
pub extern "c" fn pid_for_task(target_tport: mach_port_name_t, pid: *pid_t) kern_return_t;
pub extern "c" fn mach_vm_read(
target_task: vm_map_read_t,
address: mach_vm_address_t,
size: mach_vm_size_t,
data: *vm_offset_t,
data_cnt: *mach_msg_type_number_t,
) kern_return_t;
pub extern "c" fn mach_vm_write(
target_task: vm_map_t,
address: mach_vm_address_t,
data: vm_offset_t,
data_cnt: mach_msg_type_number_t,
) kern_return_t;
pub extern "c" fn mach_vm_region(
target_task: vm_map_t,
address: *mach_vm_address_t,
size: *mach_vm_size_t,
flavor: vm_region_flavor_t,
info: vm_region_info_t,
info_cnt: *mach_msg_type_number_t,
object_name: *mach_port_t,
) kern_return_t;
pub extern "c" fn mach_vm_region_recurse(
target_task: vm_map_t,
address: *mach_vm_address_t,
size: *mach_vm_size_t,
nesting_depth: *natural_t,
info: vm_region_recurse_info_t,
info_cnt: *mach_msg_type_number_t,
) kern_return_t;
pub const vm_inherit_t = u32;
pub const memory_object_offset_t = u64;
pub const vm_behavior_t = i32;
pub const vm32_object_id_t = u32;
pub const vm_object_id_t = u64;
pub const VM_INHERIT_SHARE: vm_inherit_t = 0;
pub const VM_INHERIT_COPY: vm_inherit_t = 1;
pub const VM_INHERIT_NONE: vm_inherit_t = 2;
pub const VM_INHERIT_DONATE_COPY: vm_inherit_t = 3;
pub const VM_INHERIT_DEFAULT = VM_INHERIT_COPY;
pub const VM_BEHAVIOR_DEFAULT: vm_behavior_t = 0;
pub const VM_BEHAVIOR_RANDOM: vm_behavior_t = 1;
pub const VM_BEHAVIOR_SEQUENTIAL: vm_behavior_t = 2;
pub const VM_BEHAVIOR_RSEQNTL: vm_behavior_t = 3;
pub const VM_BEHAVIOR_WILLNEED: vm_behavior_t = 4;
pub const VM_BEHAVIOR_DONTNEED: vm_behavior_t = 5;
pub const VM_BEHAVIOR_FREE: vm_behavior_t = 6;
pub const VM_BEHAVIOR_ZERO_WIRED_PAGES: vm_behavior_t = 7;
pub const VM_BEHAVIOR_REUSABLE: vm_behavior_t = 8;
pub const VM_BEHAVIOR_REUSE: vm_behavior_t = 9;
pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10;
pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11;
pub const VM_REGION_BASIC_INFO_64 = 9;
pub const VM_REGION_EXTENDED_INFO = 13;
pub const VM_REGION_TOP_INFO = 12;
pub const VM_REGION_SUBMAP_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_info_64) / @sizeOf(natural_t);
pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_short_info_64) / @sizeOf(natural_t);
pub const VM_REGION_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_basic_info_64) / @sizeOf(c_int);
pub const VM_REGION_EXTENDED_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_extended_info) / @sizeOf(natural_t);
pub const VM_REGION_TOP_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_top_info) / @sizeOf(natural_t);
pub fn VM_MAKE_TAG(tag: u8) u32 {
return @as(u32, tag) << 24;
}
pub const vm_region_basic_info_64 = extern struct {
protection: vm_prot_t,
max_protection: vm_prot_t,
inheritance: vm_inherit_t,
shared: boolean_t,
reserved: boolean_t,
offset: memory_object_offset_t,
behavior: vm_behavior_t,
user_wired_count: u16,
};
pub const vm_region_extended_info = extern struct {
protection: vm_prot_t,
user_tag: u32,
pages_resident: u32,
pages_shared_now_private: u32,
pages_swapped_out: u32,
pages_dirtied: u32,
ref_count: u32,
shadow_depth: u16,
external_pager: u8,
share_mode: u8,
pages_reusable: u32,
};
pub const vm_region_top_info = extern struct {
obj_id: u32,
ref_count: u32,
private_pages_resident: u32,
shared_pages_resident: u32,
share_mode: u8,
};
pub const vm_region_submap_info_64 = extern struct {
// present across protection
protection: vm_prot_t,
// max avail through vm_prot
max_protection: vm_prot_t,
// behavior of map/obj on fork
inheritance: vm_inherit_t,
// offset into object/map
offset: memory_object_offset_t,
// user tag on map entry
user_tag: u32,
// only valid for objects
pages_resident: u32,
// only for objects
pages_shared_now_private: u32,
// only for objects
pages_swapped_out: u32,
// only for objects
pages_dirtied: u32,
// obj/map mappers, etc.
ref_count: u32,
// only for obj
shadow_depth: u16,
// only for obj
external_pager: u8,
// see enumeration
share_mode: u8,
// submap vs obj
is_submap: boolean_t,
// access behavior hint
behavior: vm_behavior_t,
// obj/map name, not a handle
object_id: vm32_object_id_t,
user_wired_count: u16,
pages_reusable: u32,
object_id_full: vm_object_id_t,
};
pub const vm_region_submap_short_info_64 = extern struct {
// present access protection
protection: vm_prot_t,
// max avail through vm_prot
max_protection: vm_prot_t,
// behavior of map/obj on fork
inheritance: vm_inherit_t,
// offset into object/map
offset: memory_object_offset_t,
// user tag on map entry
user_tag: u32,
// obj/map mappers, etc
ref_count: u32,
// only for obj
shadow_depth: u16,
// only for obj
external_pager: u8,
// see enumeration
share_mode: u8,
// submap vs obj
is_submap: boolean_t,
// access behavior hint
behavior: vm_behavior_t,
// obj/map name, not a handle
object_id: vm32_object_id_t,
user_wired_count: u16,
};
pub const thread_act_t = mach_port_t;
pub const thread_state_t = *natural_t;
pub const mach_port_array_t = [*]mach_port_t;
pub extern "c" fn task_threads(
target_task: mach_port_t,
init_port_set: *mach_port_array_t,
init_port_count: *mach_msg_type_number_t,
) kern_return_t;
pub extern "c" fn thread_get_state(
thread: thread_act_t,
flavor: thread_flavor_t,
state: thread_state_t,
count: *mach_msg_type_number_t,
) kern_return_t;
pub extern "c" fn thread_set_state(
thread: thread_act_t,
flavor: thread_flavor_t,
new_state: thread_state_t,
count: mach_msg_type_number_t,
) kern_return_t;
pub extern "c" fn thread_info(
thread: thread_act_t,
flavor: thread_flavor_t,
info: thread_info_t,
count: *mach_msg_type_number_t,
) kern_return_t;
pub extern "c" fn thread_resume(thread: thread_act_t) kern_return_t;
pub const THREAD_BASIC_INFO = 3;
pub const THREAD_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(thread_basic_info) / @sizeOf(natural_t);
pub const THREAD_IDENTIFIER_INFO = 4;
pub const THREAD_IDENTIFIER_INFO_COUNT: mach_msg_type_number_t = @sizeOf(thread_identifier_info) / @sizeOf(natural_t);
pub const thread_flavor_t = natural_t;
pub const thread_info_t = *integer_t;
pub const time_value_t = time_value;
pub const task_policy_flavor_t = natural_t;
pub const task_policy_t = *integer_t;
pub const policy_t = c_int;
pub const time_value = extern struct {
seconds: integer_t,
microseconds: integer_t,
};
pub const thread_basic_info = extern struct {
// user run time
user_time: time_value_t,
// system run time
system_time: time_value_t,
// scaled cpu usage percentage
cpu_usage: integer_t,
// scheduling policy in effect
policy: policy_t,
// run state
run_state: integer_t,
// various flags
flags: integer_t,
// suspend count for thread
suspend_count: integer_t,
// number of seconds that thread has been sleeping
sleep_time: integer_t,
};
pub const thread_identifier_info = extern struct {
/// System-wide unique 64-bit thread id
thread_id: u64,
/// Handle to be used by libproc
thread_handle: u64,
/// libdispatch queue address
dispatch_qaddr: u64,
};
/// Cachability
pub const MATTR_CACHE = 1;
/// Migrability
pub const MATTR_MIGRATE = 2;
/// Replicability
pub const MATTR_REPLICATE = 4;
/// (Generic) turn attribute off
pub const MATTR_VAL_OFF = 0;
/// (Generic) turn attribute on
pub const MATTR_VAL_ON = 1;
/// (Generic) return current value
pub const MATTR_VAL_GET = 2;
/// Flush from all caches
pub const MATTR_VAL_CACHE_FLUSH = 6;
/// Flush from data caches
pub const MATTR_VAL_DCACHE_FLUSH = 7;
/// Flush from instruction caches
pub const MATTR_VAL_ICACHE_FLUSH = 8;
/// Sync I+D caches
pub const MATTR_VAL_CACHE_SYNC = 9;
/// Get page info (stats)
pub const MATTR_VAL_GET_INFO = 10;
pub const TASK_VM_INFO = 22;
pub const TASK_VM_INFO_COUNT: mach_msg_type_number_t = @sizeOf(task_vm_info_data_t) / @sizeOf(natural_t);
pub const task_vm_info = extern struct {
// virtual memory size (bytes)
virtual_size: mach_vm_size_t,
// number of memory regions
region_count: integer_t,
page_size: integer_t,
// resident memory size (bytes)
resident_size: mach_vm_size_t,
// peak resident size (bytes)
resident_size_peak: mach_vm_size_t,
device: mach_vm_size_t,
device_peak: mach_vm_size_t,
internal: mach_vm_size_t,
internal_peak: mach_vm_size_t,
external: mach_vm_size_t,
external_peak: mach_vm_size_t,
reusable: mach_vm_size_t,
reusable_peak: mach_vm_size_t,
purgeable_volatile_pmap: mach_vm_size_t,
purgeable_volatile_resident: mach_vm_size_t,
purgeable_volatile_virtual: mach_vm_size_t,
compressed: mach_vm_size_t,
compressed_peak: mach_vm_size_t,
compressed_lifetime: mach_vm_size_t,
// added for rev1
phys_footprint: mach_vm_size_t,
// added for rev2
min_address: mach_vm_address_t,
max_address: mach_vm_address_t,
// added for rev3
ledger_phys_footprint_peak: i64,
ledger_purgeable_nonvolatile: i64,
ledger_purgeable_novolatile_compressed: i64,
ledger_purgeable_volatile: i64,
ledger_purgeable_volatile_compressed: i64,
ledger_tag_network_nonvolatile: i64,
ledger_tag_network_nonvolatile_compressed: i64,
ledger_tag_network_volatile: i64,
ledger_tag_network_volatile_compressed: i64,
ledger_tag_media_footprint: i64,
ledger_tag_media_footprint_compressed: i64,
ledger_tag_media_nofootprint: i64,
ledger_tag_media_nofootprint_compressed: i64,
ledger_tag_graphics_footprint: i64,
ledger_tag_graphics_footprint_compressed: i64,
ledger_tag_graphics_nofootprint: i64,
ledger_tag_graphics_nofootprint_compressed: i64,
ledger_tag_neural_footprint: i64,
ledger_tag_neural_footprint_compressed: i64,
ledger_tag_neural_nofootprint: i64,
ledger_tag_neural_nofootprint_compressed: i64,
// added for rev4
limit_bytes_remaining: u64,
// added for rev5
decompressions: integer_t,
};
pub const task_vm_info_data_t = task_vm_info;
pub const vm_prot_t = c_int;
pub const boolean_t = c_int;
pub extern "c" fn mach_vm_protect(
target_task: vm_map_t,
address: mach_vm_address_t,
size: mach_vm_size_t,
set_maximum: boolean_t,
new_protection: vm_prot_t,
) kern_return_t;
pub extern "c" fn mach_port_allocate(
task: ipc_space_t,
right: mach_port_right_t,
name: *mach_port_name_t,
) kern_return_t;
pub extern "c" fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t;
pub extern "c" fn mach_port_insert_right(
task: ipc_space_t,
name: mach_port_name_t,
poly: mach_port_t,
poly_poly: mach_msg_type_name_t,
) kern_return_t;
pub extern "c" fn task_info(
target_task: task_name_t,
flavor: task_flavor_t,
task_info_out: task_info_t,
task_info_outCnt: *mach_msg_type_number_t,
) kern_return_t;
pub const mach_task_basic_info = extern struct {
/// Virtual memory size (bytes)
virtual_size: mach_vm_size_t,
/// Resident memory size (bytes)
resident_size: mach_vm_size_t,
/// Total user run time for terminated threads
user_time: time_value_t,
/// Total system run time for terminated threads
system_time: time_value_t,
/// Default policy for new threads
policy: policy_t,
/// Suspend count for task
suspend_count: mach_vm_size_t,
};
pub const MACH_TASK_BASIC_INFO = 20;
pub const MACH_TASK_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(mach_task_basic_info) / @sizeOf(natural_t);
pub extern "c" fn _host_page_size(task: mach_port_t, size: *vm_size_t) kern_return_t;
pub extern "c" fn vm_deallocate(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) kern_return_t;
pub extern "c" fn vm_machine_attribute(
target_task: vm_map_t,
address: vm_address_t,
size: vm_size_t,
attribute: vm_machine_attribute_t,
value: *vm_machine_attribute_val_t,
) kern_return_t;
pub const sf_hdtr = extern struct {
headers: [*]const iovec_const,
hdr_cnt: c_int,
trailers: [*]const iovec_const,
trl_cnt: c_int,
};
pub extern "c" fn sendfile(
in_fd: fd_t,
out_fd: fd_t,
offset: off_t,
len: *off_t,
sf_hdtr: ?*sf_hdtr,
flags: u32,
) c_int;
pub fn sigaddset(set: *sigset_t, signo: u5) void {
set.* |= @as(u32, 1) << (signo - 1);
}
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
pub const IFNAMESIZE = 16;
pub const AI = struct {
/// get address to use bind()
pub const PASSIVE = 0x00000001;
/// fill ai_canonname
pub const CANONNAME = 0x00000002;
/// prevent host name resolution
pub const NUMERICHOST = 0x00000004;
/// prevent service name resolution
pub const NUMERICSERV = 0x00001000;
};
pub const EAI = enum(c_int) {
/// address family for hostname not supported
ADDRFAMILY = 1,
/// temporary failure in name resolution
AGAIN = 2,
/// invalid value for ai_flags
BADFLAGS = 3,
/// non-recoverable failure in name resolution
FAIL = 4,
/// ai_family not supported
FAMILY = 5,
/// memory allocation failure
MEMORY = 6,
/// no address associated with hostname
NODATA = 7,
/// hostname nor servname provided, or not known
NONAME = 8,
/// servname not supported for ai_socktype
SERVICE = 9,
/// ai_socktype not supported
SOCKTYPE = 10,
/// system error returned in errno
SYSTEM = 11,
/// invalid value for hints
BADHINTS = 12,
/// resolved protocol is unknown
PROTOCOL = 13,
/// argument buffer overflow
OVERFLOW = 14,
_,
};
pub const EAI_MAX = 15;
pub const qos_class_t = enum(c_uint) {
/// highest priority QOS class for critical tasks
QOS_CLASS_USER_INTERACTIVE = 0x21,
/// slightly more moderate priority QOS class
QOS_CLASS_USER_INITIATED = 0x19,
/// default QOS class when none is set
QOS_CLASS_DEFAULT = 0x15,
/// more energy efficient QOS class than default
QOS_CLASS_UTILITY = 0x11,
/// QOS class more appropriate for background tasks
QOS_CLASS_BACKGROUND = 0x09,
/// QOS class as a return value
QOS_CLASS_UNSPECIFIED = 0x00,
};
pub const sem_t = c_int;
pub const pthread_attr_t = extern struct {
__sig: c_long,
__opaque: [56]u8,
};
pub extern "c" fn pthread_threadid_np(thread: ?std.c.pthread_t, thread_id: *u64) c_int;
pub extern "c" fn pthread_setname_np(name: [*:0]const u8) E;
pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) E;
pub extern "c" fn pthread_attr_set_qos_class_np(attr: *pthread_attr_t, qos_class: qos_class_t, relative_priority: c_int) c_int;
pub extern "c" fn pthread_attr_get_qos_class_np(attr: *pthread_attr_t, qos_class: *qos_class_t, relative_priority: *c_int) c_int;
pub extern "c" fn pthread_set_qos_class_self_np(qos_class: qos_class_t, relative_priority: c_int) c_int;
pub extern "c" fn pthread_get_qos_class_np(pthread: std.c.pthread_t, qos_class: *qos_class_t, relative_priority: *c_int) c_int;
pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void;
// Grand Central Dispatch is exposed by libSystem.
pub extern "c" fn dispatch_release(object: *anyopaque) void;
pub const dispatch_semaphore_t = *opaque {};
pub extern "c" fn dispatch_semaphore_create(value: isize) ?dispatch_semaphore_t;
pub extern "c" fn dispatch_semaphore_wait(dsema: dispatch_semaphore_t, timeout: dispatch_time_t) isize;
pub extern "c" fn dispatch_semaphore_signal(dsema: dispatch_semaphore_t) isize;
pub const dispatch_time_t = u64;
pub const DISPATCH_TIME_NOW = @as(dispatch_time_t, 0);
pub const DISPATCH_TIME_FOREVER = ~@as(dispatch_time_t, 0);
pub extern "c" fn dispatch_time(when: dispatch_time_t, delta: i64) dispatch_time_t;
const dispatch_once_t = usize;
const dispatch_function_t = fn (?*anyopaque) callconv(.C) void;
pub extern fn dispatch_once_f(
predicate: *dispatch_once_t,
context: ?*anyopaque,
function: dispatch_function_t,
) void;
// Undocumented futex-like API available on darwin 16+
// (macOS 10.12+, iOS 10.0+, tvOS 10.0+, watchOS 3.0+, catalyst 13.0+).
//
// [ulock.h]: https://github.com/apple/darwin-xnu/blob/master/bsd/sys/ulock.h
// [sys_ulock.c]: https://github.com/apple/darwin-xnu/blob/master/bsd/kern/sys_ulock.c
pub const UL_COMPARE_AND_WAIT = 1;
pub const UL_UNFAIR_LOCK = 2;
// Obsolete/deprecated
pub const UL_OSSPINLOCK = UL_COMPARE_AND_WAIT;
pub const UL_HANDOFFLOCK = UL_UNFAIR_LOCK;
pub const ULF_WAKE_ALL = 0x100;
pub const ULF_WAKE_THREAD = 0x200;
pub const ULF_WAIT_WORKQ_DATA_CONTENTION = 0x10000;
pub const ULF_WAIT_CANCEL_POINT = 0x20000;
pub const ULF_NO_ERRNO = 0x1000000;
// The following are only supported on darwin 19+
// (macOS 10.15+, iOS 13.0+)
pub const UL_COMPARE_AND_WAIT_SHARED = 3;
pub const UL_UNFAIR_LOCK64_SHARED = 4;
pub const UL_COMPARE_AND_WAIT64 = 5;
pub const UL_COMPARE_AND_WAIT64_SHARED = 6;
pub const ULF_WAIT_ADAPTIVE_SPIN = 0x40000;
pub extern "c" fn __ulock_wait2(op: u32, addr: ?*const anyopaque, val: u64, timeout_ns: u64, val2: u64) c_int;
pub extern "c" fn __ulock_wait(op: u32, addr: ?*const anyopaque, val: u64, timeout_us: u32) c_int;
pub extern "c" fn __ulock_wake(op: u32, addr: ?*const anyopaque, val: u64) c_int;
pub const OS_UNFAIR_LOCK_INIT = os_unfair_lock{};
pub const os_unfair_lock_t = *os_unfair_lock;
pub const os_unfair_lock = extern struct {
_os_unfair_lock_opaque: u32 = 0,
};
pub extern "c" fn os_unfair_lock_lock(o: os_unfair_lock_t) void;
pub extern "c" fn os_unfair_lock_unlock(o: os_unfair_lock_t) void;
pub extern "c" fn os_unfair_lock_trylock(o: os_unfair_lock_t) bool;
pub extern "c" fn os_unfair_lock_assert_owner(o: os_unfair_lock_t) void;
pub extern "c" fn os_unfair_lock_assert_not_owner(o: os_unfair_lock_t) void;
// See: https://opensource.apple.com/source/xnu/xnu-6153.141.1/bsd/sys/_types.h.auto.html
// TODO: audit mode_t/pid_t, should likely be u16/i32
pub const blkcnt_t = i64;
pub const blksize_t = i32;
pub const dev_t = i32;
pub const fd_t = c_int;
pub const pid_t = c_int;
pub const mode_t = c_uint;
pub const uid_t = u32;
pub const gid_t = u32;
// machine/_types.h
pub const clock_t = c_ulong;
pub const time_t = c_long;
pub const in_port_t = u16;
pub const sa_family_t = u8;
pub const socklen_t = u32;
pub const sockaddr = extern struct {
len: u8,
family: sa_family_t,
data: [14]u8,
pub const SS_MAXSIZE = 128;
pub const storage = extern struct {
len: u8 align(8),
family: sa_family_t,
padding: [126]u8 = undefined,
comptime {
assert(@sizeOf(storage) == SS_MAXSIZE);
assert(@alignOf(storage) == 8);
}
};
pub const in = extern struct {
len: u8 = @sizeOf(in),
family: sa_family_t = AF.INET,
port: in_port_t,
addr: u32,
zero: [8]u8 = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 },
};
pub const in6 = extern struct {
len: u8 = @sizeOf(in6),
family: sa_family_t = AF.INET6,
port: in_port_t,
flowinfo: u32,
addr: [16]u8,
scope_id: u32,
};
/// UNIX domain socket
pub const un = extern struct {
len: u8 = @sizeOf(un),
family: sa_family_t = AF.UNIX,
path: [104]u8,
};
};
pub const timeval = extern struct {
tv_sec: c_long,
tv_usec: i32,
};
pub const timezone = extern struct {
tz_minuteswest: i32,
tz_dsttime: i32,
};
pub const mach_timebase_info_data = extern struct {
numer: u32,
denom: u32,
};
pub const off_t = i64;
pub const ino_t = u64;
pub const Flock = extern struct {
start: off_t,
len: off_t,
pid: pid_t,
type: i16,
whence: i16,
};
pub const Stat = extern struct {
dev: i32,
mode: u16,
nlink: u16,
ino: ino_t,
uid: uid_t,
gid: gid_t,
rdev: i32,
atimespec: timespec,
mtimespec: timespec,
ctimespec: timespec,
birthtimespec: timespec,
size: off_t,
blocks: i64,
blksize: i32,
flags: u32,
gen: u32,
lspare: i32,
qspare: [2]i64,
pub fn atime(self: @This()) timespec {
return self.atimespec;
}
pub fn mtime(self: @This()) timespec {
return self.mtimespec;
}
pub fn ctime(self: @This()) timespec {
return self.ctimespec;
}
pub fn birthtime(self: @This()) timespec {
return self.birthtimespec;
}
};
pub const timespec = extern struct {
tv_sec: isize,
tv_nsec: isize,
};
pub const sigset_t = u32;
pub const empty_sigset: sigset_t = 0;
pub const SIG = struct {
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(5);
/// block specified signal set
pub const BLOCK = 1;
/// unblock specified signal set
pub const UNBLOCK = 2;
/// set specified signal set
pub const SETMASK = 3;
/// hangup
pub const HUP = 1;
/// interrupt
pub const INT = 2;
/// quit
pub const QUIT = 3;
/// illegal instruction (not reset when caught)
pub const ILL = 4;
/// trace trap (not reset when caught)
pub const TRAP = 5;
/// abort()
pub const ABRT = 6;
/// pollable event ([XSR] generated, not supported)
pub const POLL = 7;
/// compatibility
pub const IOT = ABRT;
/// EMT instruction
pub const EMT = 7;
/// floating point exception
pub const FPE = 8;
/// kill (cannot be caught or ignored)
pub const KILL = 9;
/// bus error
pub const BUS = 10;
/// segmentation violation
pub const SEGV = 11;
/// bad argument to system call
pub const SYS = 12;
/// write on a pipe with no one to read it
pub const PIPE = 13;
/// alarm clock
pub const ALRM = 14;
/// software termination signal from kill
pub const TERM = 15;
/// urgent condition on IO channel
pub const URG = 16;
/// sendable stop signal not from tty
pub const STOP = 17;
/// stop signal from tty
pub const TSTP = 18;
/// continue a stopped process
pub const CONT = 19;
/// to parent on child stop or exit
pub const CHLD = 20;
/// to readers pgrp upon background tty read
pub const TTIN = 21;
/// like TTIN for output if (tp->t_local&LTOSTOP)
pub const TTOU = 22;
/// input/output possible signal
pub const IO = 23;
/// exceeded CPU time limit
pub const XCPU = 24;
/// exceeded file size limit
pub const XFSZ = 25;
/// virtual time alarm
pub const VTALRM = 26;
/// profiling time alarm
pub const PROF = 27;
/// window size changes
pub const WINCH = 28;
/// information request
pub const INFO = 29;
/// user defined signal 1
pub const USR1 = 30;
/// user defined signal 2
pub const USR2 = 31;
};
pub const siginfo_t = extern struct {
signo: c_int,
errno: c_int,
code: c_int,
pid: pid_t,
uid: uid_t,
status: c_int,
addr: *anyopaque,
value: extern union {
int: c_int,
ptr: *anyopaque,
},
si_band: c_long,
_pad: [7]c_ulong,
};
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
pub const Sigaction = extern struct {
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
handler: extern union {
handler: ?handler_fn,
sigaction: ?sigaction_fn,
},
mask: sigset_t,
flags: c_uint,
};
pub const dirent = extern struct {
ino: u64,
seekoff: u64,
reclen: u16,
namlen: u16,
type: u8,
name: [1024]u8,
};
/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
pub const Kevent = extern struct {
ident: usize,
filter: i16,
flags: u16,
fflags: u32,
data: isize,
udata: usize,
};
// sys/types.h on macos uses #pragma pack(4) so these checks are
// to make sure the struct is laid out the same. These values were
// produced from C code using the offsetof macro.
comptime {
if (builtin.target.isDarwin()) {
assert(@offsetOf(Kevent, "ident") == 0);
assert(@offsetOf(Kevent, "filter") == 8);
assert(@offsetOf(Kevent, "flags") == 10);
assert(@offsetOf(Kevent, "fflags") == 12);
assert(@offsetOf(Kevent, "data") == 16);
assert(@offsetOf(Kevent, "udata") == 24);
}
}
pub const kevent64_s = extern struct {
ident: u64,
filter: i16,
flags: u16,
fflags: u32,
data: i64,
udata: u64,
ext: [2]u64,
};
// sys/types.h on macos uses #pragma pack() so these checks are
// to make sure the struct is laid out the same. These values were
// produced from C code using the offsetof macro.
comptime {
if (builtin.target.isDarwin()) {
assert(@offsetOf(kevent64_s, "ident") == 0);
assert(@offsetOf(kevent64_s, "filter") == 8);
assert(@offsetOf(kevent64_s, "flags") == 10);
assert(@offsetOf(kevent64_s, "fflags") == 12);
assert(@offsetOf(kevent64_s, "data") == 16);
assert(@offsetOf(kevent64_s, "udata") == 24);
assert(@offsetOf(kevent64_s, "ext") == 32);
}
}
pub const mach_port_t = c_uint;
pub const clock_serv_t = mach_port_t;
pub const clock_res_t = c_int;
pub const mach_port_name_t = natural_t;
pub const natural_t = c_uint;
pub const mach_timespec_t = extern struct {
tv_sec: c_uint,
tv_nsec: clock_res_t,
};
pub const kern_return_t = c_int;
pub const host_t = mach_port_t;
pub const integer_t = c_int;
pub const task_flavor_t = natural_t;
pub const task_info_t = *integer_t;
pub const task_name_t = mach_port_name_t;
pub const vm_address_t = vm_offset_t;
pub const vm_size_t = mach_vm_size_t;
pub const vm_machine_attribute_t = usize;
pub const vm_machine_attribute_val_t = isize;
pub const CALENDAR_CLOCK = 1;
pub const PATH_MAX = 1024;
pub const NAME_MAX = 255;
pub const IOV_MAX = 16;
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;
pub const STDERR_FILENO = 2;
pub const PROT = struct {
/// [MC2] no permissions
pub const NONE: vm_prot_t = 0x00;
/// [MC2] pages can be read
pub const READ: vm_prot_t = 0x01;
/// [MC2] pages can be written
pub const WRITE: vm_prot_t = 0x02;
/// [MC2] pages can be executed
pub const EXEC: vm_prot_t = 0x04;
/// When a caller finds that they cannot obtain write permission on a
/// mapped entry, the following flag can be used. The entry will be
/// made "needs copy" effectively copying the object (using COW),
/// and write permission will be added to the maximum protections for
/// the associated entry.
pub const COPY: vm_prot_t = 0x10;
};
pub const MSF = struct {
pub const ASYNC = 0x1;
pub const INVALIDATE = 0x2;
// invalidate, leave mapped
pub const KILLPAGES = 0x4;
// deactivate, leave mapped
pub const DEACTIVATE = 0x8;
pub const SYNC = 0x10;
};
pub const SA = struct {
/// take signal on signal stack
pub const ONSTACK = 0x0001;
/// restart system on signal return
pub const RESTART = 0x0002;
/// reset to SIG.DFL when taking signal
pub const RESETHAND = 0x0004;
/// do not generate SIG.CHLD on child stop
pub const NOCLDSTOP = 0x0008;
/// don't mask the signal we're delivering
pub const NODEFER = 0x0010;
/// don't keep zombies around
pub const NOCLDWAIT = 0x0020;
/// signal handler with SIGINFO args
pub const SIGINFO = 0x0040;
/// do not bounce off kernel's sigtramp
pub const USERTRAMP = 0x0100;
/// signal handler with SIGINFO args with 64bit regs information
pub const @"64REGSET" = 0x0200;
};
pub const F_OK = 0;
pub const X_OK = 1;
pub const W_OK = 2;
pub const R_OK = 4;
pub const SEEK = struct {
pub const SET = 0x0;
pub const CUR = 0x1;
pub const END = 0x2;
};
pub const DT = struct {
pub const UNKNOWN = 0;
pub const FIFO = 1;
pub const CHR = 2;
pub const DIR = 4;
pub const BLK = 6;
pub const REG = 8;
pub const LNK = 10;
pub const SOCK = 12;
pub const WHT = 14;
};
/// no flag value
pub const KEVENT_FLAG_NONE = 0x000;
/// immediate timeout
pub const KEVENT_FLAG_IMMEDIATE = 0x001;
/// output events only include change
pub const KEVENT_FLAG_ERROR_EVENTS = 0x002;
/// add event to kq (implies enable)
pub const EV_ADD = 0x0001;
/// delete event from kq
pub const EV_DELETE = 0x0002;
/// enable event
pub const EV_ENABLE = 0x0004;
/// disable event (not reported)
pub const EV_DISABLE = 0x0008;
/// only report one occurrence
pub const EV_ONESHOT = 0x0010;
/// clear event state after reporting
pub const EV_CLEAR = 0x0020;
/// force immediate event output
/// ... with or without EV_ERROR
/// ... use KEVENT_FLAG_ERROR_EVENTS
/// on syscalls supporting flags
pub const EV_RECEIPT = 0x0040;
/// disable event after reporting
pub const EV_DISPATCH = 0x0080;
/// unique kevent per udata value
pub const EV_UDATA_SPECIFIC = 0x0100;
/// ... in combination with EV_DELETE
/// will defer delete until udata-specific
/// event enabled. EINPROGRESS will be
/// returned to indicate the deferral
pub const EV_DISPATCH2 = EV_DISPATCH | EV_UDATA_SPECIFIC;
/// report that source has vanished
/// ... only valid with EV_DISPATCH2
pub const EV_VANISHED = 0x0200;
/// reserved by system
pub const EV_SYSFLAGS = 0xF000;
/// filter-specific flag
pub const EV_FLAG0 = 0x1000;
/// filter-specific flag
pub const EV_FLAG1 = 0x2000;
/// EOF detected
pub const EV_EOF = 0x8000;
/// error, data contains errno
pub const EV_ERROR = 0x4000;
pub const EV_POLL = EV_FLAG0;
pub const EV_OOBAND = EV_FLAG1;
pub const EVFILT_READ = -1;
pub const EVFILT_WRITE = -2;
/// attached to aio requests
pub const EVFILT_AIO = -3;
/// attached to vnodes
pub const EVFILT_VNODE = -4;
/// attached to struct proc
pub const EVFILT_PROC = -5;
/// attached to struct proc
pub const EVFILT_SIGNAL = -6;
/// timers
pub const EVFILT_TIMER = -7;
/// Mach portsets
pub const EVFILT_MACHPORT = -8;
/// Filesystem events
pub const EVFILT_FS = -9;
/// User events
pub const EVFILT_USER = -10;
/// Virtual memory events
pub const EVFILT_VM = -12;
/// Exception events
pub const EVFILT_EXCEPT = -15;
pub const EVFILT_SYSCOUNT = 17;
/// On input, NOTE_TRIGGER causes the event to be triggered for output.
pub const NOTE_TRIGGER = 0x01000000;
/// ignore input fflags
pub const NOTE_FFNOP = 0x00000000;
/// and fflags
pub const NOTE_FFAND = 0x40000000;
/// or fflags
pub const NOTE_FFOR = 0x80000000;
/// copy fflags
pub const NOTE_FFCOPY = 0xc0000000;
/// mask for operations
pub const NOTE_FFCTRLMASK = 0xc0000000;
pub const NOTE_FFLAGSMASK = 0x00ffffff;
/// low water mark
pub const NOTE_LOWAT = 0x00000001;
/// OOB data
pub const NOTE_OOB = 0x00000002;
/// vnode was removed
pub const NOTE_DELETE = 0x00000001;
/// data contents changed
pub const NOTE_WRITE = 0x00000002;
/// size increased
pub const NOTE_EXTEND = 0x00000004;
/// attributes changed
pub const NOTE_ATTRIB = 0x00000008;
/// link count changed
pub const NOTE_LINK = 0x00000010;
/// vnode was renamed
pub const NOTE_RENAME = 0x00000020;
/// vnode access was revoked
pub const NOTE_REVOKE = 0x00000040;
/// No specific vnode event: to test for EVFILT_READ activation
pub const NOTE_NONE = 0x00000080;
/// vnode was unlocked by flock(2)
pub const NOTE_FUNLOCK = 0x00000100;
/// process exited
pub const NOTE_EXIT = 0x80000000;
/// process forked
pub const NOTE_FORK = 0x40000000;
/// process exec'd
pub const NOTE_EXEC = 0x20000000;
/// shared with EVFILT_SIGNAL
pub const NOTE_SIGNAL = 0x08000000;
/// exit status to be returned, valid for child process only
pub const NOTE_EXITSTATUS = 0x04000000;
/// provide details on reasons for exit
pub const NOTE_EXIT_DETAIL = 0x02000000;
/// mask for signal & exit status
pub const NOTE_PDATAMASK = 0x000fffff;
pub const NOTE_PCTRLMASK = (~NOTE_PDATAMASK);
pub const NOTE_EXIT_DETAIL_MASK = 0x00070000;
pub const NOTE_EXIT_DECRYPTFAIL = 0x00010000;
pub const NOTE_EXIT_MEMORY = 0x00020000;
pub const NOTE_EXIT_CSERROR = 0x00040000;
/// will react on memory pressure
pub const NOTE_VM_PRESSURE = 0x80000000;
/// will quit on memory pressure, possibly after cleaning up dirty state
pub const NOTE_VM_PRESSURE_TERMINATE = 0x40000000;
/// will quit immediately on memory pressure
pub const NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000;
/// there was an error
pub const NOTE_VM_ERROR = 0x10000000;
/// data is seconds
pub const NOTE_SECONDS = 0x00000001;
/// data is microseconds
pub const NOTE_USECONDS = 0x00000002;
/// data is nanoseconds
pub const NOTE_NSECONDS = 0x00000004;
/// absolute timeout
pub const NOTE_ABSOLUTE = 0x00000008;
/// ext[1] holds leeway for power aware timers
pub const NOTE_LEEWAY = 0x00000010;
/// system does minimal timer coalescing
pub const NOTE_CRITICAL = 0x00000020;
/// system does maximum timer coalescing
pub const NOTE_BACKGROUND = 0x00000040;
pub const NOTE_MACH_CONTINUOUS_TIME = 0x00000080;
/// data is mach absolute time units
pub const NOTE_MACHTIME = 0x00000100;
pub const AF = struct {
pub const UNSPEC = 0;
pub const LOCAL = 1;
pub const UNIX = LOCAL;
pub const INET = 2;
pub const SYS_CONTROL = 2;
pub const IMPLINK = 3;
pub const PUP = 4;
pub const CHAOS = 5;
pub const NS = 6;
pub const ISO = 7;
pub const OSI = ISO;
pub const ECMA = 8;
pub const DATAKIT = 9;
pub const CCITT = 10;
pub const SNA = 11;
pub const DECnet = 12;
pub const DLI = 13;
pub const LAT = 14;
pub const HYLINK = 15;
pub const APPLETALK = 16;
pub const ROUTE = 17;
pub const LINK = 18;
pub const XTP = 19;
pub const COIP = 20;
pub const CNT = 21;
pub const RTIP = 22;
pub const IPX = 23;
pub const SIP = 24;
pub const PIP = 25;
pub const ISDN = 28;
pub const E164 = ISDN;
pub const KEY = 29;
pub const INET6 = 30;
pub const NATM = 31;
pub const SYSTEM = 32;
pub const NETBIOS = 33;
pub const PPP = 34;
pub const MAX = 40;
};
pub const PF = struct {
pub const UNSPEC = AF.UNSPEC;
pub const LOCAL = AF.LOCAL;
pub const UNIX = PF.LOCAL;
pub const INET = AF.INET;
pub const IMPLINK = AF.IMPLINK;
pub const PUP = AF.PUP;
pub const CHAOS = AF.CHAOS;
pub const NS = AF.NS;
pub const ISO = AF.ISO;
pub const OSI = AF.ISO;
pub const ECMA = AF.ECMA;
pub const DATAKIT = AF.DATAKIT;
pub const CCITT = AF.CCITT;
pub const SNA = AF.SNA;
pub const DECnet = AF.DECnet;
pub const DLI = AF.DLI;
pub const LAT = AF.LAT;
pub const HYLINK = AF.HYLINK;
pub const APPLETALK = AF.APPLETALK;
pub const ROUTE = AF.ROUTE;
pub const LINK = AF.LINK;
pub const XTP = AF.XTP;
pub const COIP = AF.COIP;
pub const CNT = AF.CNT;
pub const SIP = AF.SIP;
pub const IPX = AF.IPX;
pub const RTIP = AF.RTIP;
pub const PIP = AF.PIP;
pub const ISDN = AF.ISDN;
pub const KEY = AF.KEY;
pub const INET6 = AF.INET6;
pub const NATM = AF.NATM;
pub const SYSTEM = AF.SYSTEM;
pub const NETBIOS = AF.NETBIOS;
pub const PPP = AF.PPP;
pub const MAX = AF.MAX;
};
pub const SYSPROTO_EVENT = 1;
pub const SYSPROTO_CONTROL = 2;
pub const SOCK = struct {
pub const STREAM = 1;
pub const DGRAM = 2;
pub const RAW = 3;
pub const RDM = 4;
pub const SEQPACKET = 5;
pub const MAXADDRLEN = 255;
/// Not actually supported by Darwin, but Zig supplies a shim.
/// This numerical value is not ABI-stable. It need only not conflict
/// with any other `SOCK` bits.
pub const CLOEXEC = 1 << 15;
/// Not actually supported by Darwin, but Zig supplies a shim.
/// This numerical value is not ABI-stable. It need only not conflict
/// with any other `SOCK` bits.
pub const NONBLOCK = 1 << 16;
};
pub const IPPROTO = struct {
pub const ICMP = 1;
pub const ICMPV6 = 58;
pub const TCP = 6;
pub const UDP = 17;
pub const IP = 0;
pub const IPV6 = 41;
};
pub const SOL = struct {
pub const SOCKET = 0xffff;
};
pub const SO = struct {
pub const DEBUG = 0x0001;
pub const ACCEPTCONN = 0x0002;
pub const REUSEADDR = 0x0004;
pub const KEEPALIVE = 0x0008;
pub const DONTROUTE = 0x0010;
pub const BROADCAST = 0x0020;
pub const USELOOPBACK = 0x0040;
pub const LINGER = 0x1080;
pub const OOBINLINE = 0x0100;
pub const REUSEPORT = 0x0200;
pub const ACCEPTFILTER = 0x1000;
pub const SNDBUF = 0x1001;
pub const RCVBUF = 0x1002;
pub const SNDLOWAT = 0x1003;
pub const RCVLOWAT = 0x1004;
pub const SNDTIMEO = 0x1005;
pub const RCVTIMEO = 0x1006;
pub const ERROR = 0x1007;
pub const TYPE = 0x1008;
pub const NREAD = 0x1020;
pub const NKE = 0x1021;
pub const NOSIGPIPE = 0x1022;
pub const NOADDRERR = 0x1023;
pub const NWRITE = 0x1024;
pub const REUSESHAREUID = 0x1025;
};
pub const W = struct {
/// [XSI] no hang in wait/no child to reap
pub const NOHANG = 0x00000001;
/// [XSI] notify on stop, untraced child
pub const UNTRACED = 0x00000002;
pub fn EXITSTATUS(x: u32) u8 {
return @as(u8, @intCast(x >> 8));
}
pub fn TERMSIG(x: u32) u32 {
return status(x);
}
pub fn STOPSIG(x: u32) u32 {
return x >> 8;
}
pub fn IFEXITED(x: u32) bool {
return status(x) == 0;
}
pub fn IFSTOPPED(x: u32) bool {
return status(x) == stopped and STOPSIG(x) != 0x13;
}
pub fn IFSIGNALED(x: u32) bool {
return status(x) != stopped and status(x) != 0;
}
fn status(x: u32) u32 {
return x & 0o177;
}
const stopped = 0o177;
};
pub const E = enum(u16) {
/// No error occurred.
SUCCESS = 0,
/// Operation not permitted
PERM = 1,
/// No such file or directory
NOENT = 2,
/// No such process
SRCH = 3,
/// Interrupted system call
INTR = 4,
/// Input/output error
IO = 5,
/// Device not configured
NXIO = 6,
/// Argument list too long
@"2BIG" = 7,
/// Exec format error
NOEXEC = 8,
/// Bad file descriptor
BADF = 9,
/// No child processes
CHILD = 10,
/// Resource deadlock avoided
DEADLK = 11,
/// Cannot allocate memory
NOMEM = 12,
/// Permission denied
ACCES = 13,
/// Bad address
FAULT = 14,
/// Block device required
NOTBLK = 15,
/// Device / Resource busy
BUSY = 16,
/// File exists
EXIST = 17,
/// Cross-device link
XDEV = 18,
/// Operation not supported by device
NODEV = 19,
/// Not a directory
NOTDIR = 20,
/// Is a directory
ISDIR = 21,
/// Invalid argument
INVAL = 22,
/// Too many open files in system
NFILE = 23,
/// Too many open files
MFILE = 24,
/// Inappropriate ioctl for device
NOTTY = 25,
/// Text file busy
TXTBSY = 26,
/// File too large
FBIG = 27,
/// No space left on device
NOSPC = 28,
/// Illegal seek
SPIPE = 29,
/// Read-only file system
ROFS = 30,
/// Too many links
MLINK = 31,
/// Broken pipe
PIPE = 32,
// math software
/// Numerical argument out of domain
DOM = 33,
/// Result too large
RANGE = 34,
// non-blocking and interrupt i/o
/// Resource temporarily unavailable
/// This is the same code used for `WOULDBLOCK`.
AGAIN = 35,
/// Operation now in progress
INPROGRESS = 36,
/// Operation already in progress
ALREADY = 37,
// ipc/network software -- argument errors
/// Socket operation on non-socket
NOTSOCK = 38,
/// Destination address required
DESTADDRREQ = 39,
/// Message too long
MSGSIZE = 40,
/// Protocol wrong type for socket
PROTOTYPE = 41,
/// Protocol not available
NOPROTOOPT = 42,
/// Protocol not supported
PROTONOSUPPORT = 43,
/// Socket type not supported
SOCKTNOSUPPORT = 44,
/// Operation not supported
/// The same code is used for `NOTSUP`.
OPNOTSUPP = 45,
/// Protocol family not supported
PFNOSUPPORT = 46,
/// Address family not supported by protocol family
AFNOSUPPORT = 47,
/// Address already in use
ADDRINUSE = 48,
/// Can't assign requested address
// ipc/network software -- operational errors
ADDRNOTAVAIL = 49,
/// Network is down
NETDOWN = 50,
/// Network is unreachable
NETUNREACH = 51,
/// Network dropped connection on reset
NETRESET = 52,
/// Software caused connection abort
CONNABORTED = 53,
/// Connection reset by peer
CONNRESET = 54,
/// No buffer space available
NOBUFS = 55,
/// Socket is already connected
ISCONN = 56,
/// Socket is not connected
NOTCONN = 57,
/// Can't send after socket shutdown
SHUTDOWN = 58,
/// Too many references: can't splice
TOOMANYREFS = 59,
/// Operation timed out
TIMEDOUT = 60,
/// Connection refused
CONNREFUSED = 61,
/// Too many levels of symbolic links
LOOP = 62,
/// File name too long
NAMETOOLONG = 63,
/// Host is down
HOSTDOWN = 64,
/// No route to host
HOSTUNREACH = 65,
/// Directory not empty
// quotas & mush
NOTEMPTY = 66,
/// Too many processes
PROCLIM = 67,
/// Too many users
USERS = 68,
/// Disc quota exceeded
// Network File System
DQUOT = 69,
/// Stale NFS file handle
STALE = 70,
/// Too many levels of remote in path
REMOTE = 71,
/// RPC struct is bad
BADRPC = 72,
/// RPC version wrong
RPCMISMATCH = 73,
/// RPC prog. not avail
PROGUNAVAIL = 74,
/// Program version wrong
PROGMISMATCH = 75,
/// Bad procedure for program
PROCUNAVAIL = 76,
/// No locks available
NOLCK = 77,
/// Function not implemented
NOSYS = 78,
/// Inappropriate file type or format
FTYPE = 79,
/// Authentication error
AUTH = 80,
/// Need authenticator
NEEDAUTH = 81,
// Intelligent device errors
/// Device power is off
PWROFF = 82,
/// Device error, e.g. paper out
DEVERR = 83,
/// Value too large to be stored in data type
OVERFLOW = 84,
// Program loading errors
/// Bad executable
BADEXEC = 85,
/// Bad CPU type in executable
BADARCH = 86,
/// Shared library version mismatch
SHLIBVERS = 87,
/// Malformed Macho file
BADMACHO = 88,
/// Operation canceled
CANCELED = 89,
/// Identifier removed
IDRM = 90,
/// No message of desired type
NOMSG = 91,
/// Illegal byte sequence
ILSEQ = 92,
/// Attribute not found
NOATTR = 93,
/// Bad message
BADMSG = 94,
/// Reserved
MULTIHOP = 95,
/// No message available on STREAM
NODATA = 96,
/// Reserved
NOLINK = 97,
/// No STREAM resources
NOSR = 98,
/// Not a STREAM
NOSTR = 99,
/// Protocol error
PROTO = 100,
/// STREAM ioctl timeout
TIME = 101,
/// No such policy registered
NOPOLICY = 103,
/// State not recoverable
NOTRECOVERABLE = 104,
/// Previous owner died
OWNERDEAD = 105,
/// Interface output queue is full
QFULL = 106,
_,
};
/// Kernel return values
pub const KernE = enum(u32) {
SUCCESS = 0,
/// Specified address is not currently valid
INVALID_ADDRESS = 1,
/// Specified memory is valid, but does not permit the
/// required forms of access.
PROTECTION_FAILURE = 2,
/// The address range specified is already in use, or
/// no address range of the size specified could be
/// found.
NO_SPACE = 3,
/// The function requested was not applicable to this
/// type of argument, or an argument is invalid
INVALID_ARGUMENT = 4,
/// The function could not be performed. A catch-all.
FAILURE = 5,
/// A system resource could not be allocated to fulfill
/// this request. This failure may not be permanent.
RESOURCE_SHORTAGE = 6,
/// The task in question does not hold receive rights
/// for the port argument.
NOT_RECEIVER = 7,
/// Bogus access restriction.
NO_ACCESS = 8,
/// During a page fault, the target address refers to a
/// memory object that has been destroyed. This
/// failure is permanent.
MEMORY_FAILURE = 9,
/// During a page fault, the memory object indicated
/// that the data could not be returned. This failure
/// may be temporary; future attempts to access this
/// same data may succeed, as defined by the memory
/// object.
MEMORY_ERROR = 10,
/// The receive right is already a member of the portset.
ALREADY_IN_SET = 11,
/// The receive right is not a member of a port set.
NOT_IN_SET = 12,
/// The name already denotes a right in the task.
NAME_EXISTS = 13,
/// The operation was aborted. Ipc code will
/// catch this and reflect it as a message error.
ABORTED = 14,
/// The name doesn't denote a right in the task.
INVALID_NAME = 15,
/// Target task isn't an active task.
INVALID_TASK = 16,
/// The name denotes a right, but not an appropriate right.
INVALID_RIGHT = 17,
/// A blatant range error.
INVALID_VALUE = 18,
/// Operation would overflow limit on user-references.
UREFS_OVERFLOW = 19,
/// The supplied (port) capability is improper.
INVALID_CAPABILITY = 20,
/// The task already has send or receive rights
/// for the port under another name.
RIGHT_EXISTS = 21,
/// Target host isn't actually a host.
INVALID_HOST = 22,
/// An attempt was made to supply "precious" data
/// for memory that is already present in a
/// memory object.
MEMORY_PRESENT = 23,
/// A page was requested of a memory manager via
/// memory_object_data_request for an object using
/// a MEMORY_OBJECT_COPY_CALL strategy, with the
/// VM_PROT_WANTS_COPY flag being used to specify
/// that the page desired is for a copy of the
/// object, and the memory manager has detected
/// the page was pushed into a copy of the object
/// while the kernel was walking the shadow chain
/// from the copy to the object. This error code
/// is delivered via memory_object_data_error
/// and is handled by the kernel (it forces the
/// kernel to restart the fault). It will not be
/// seen by users.
MEMORY_DATA_MOVED = 24,
/// A strategic copy was attempted of an object
/// upon which a quicker copy is now possible.
/// The caller should retry the copy using
/// vm_object_copy_quickly. This error code
/// is seen only by the kernel.
MEMORY_RESTART_COPY = 25,
/// An argument applied to assert processor set privilege
/// was not a processor set control port.
INVALID_PROCESSOR_SET = 26,
/// The specified scheduling attributes exceed the thread's
/// limits.
POLICY_LIMIT = 27,
/// The specified scheduling policy is not currently
/// enabled for the processor set.
INVALID_POLICY = 28,
/// The external memory manager failed to initialize the
/// memory object.
INVALID_OBJECT = 29,
/// A thread is attempting to wait for an event for which
/// there is already a waiting thread.
ALREADY_WAITING = 30,
/// An attempt was made to destroy the default processor
/// set.
DEFAULT_SET = 31,
/// An attempt was made to fetch an exception port that is
/// protected, or to abort a thread while processing a
/// protected exception.
EXCEPTION_PROTECTED = 32,
/// A ledger was required but not supplied.
INVALID_LEDGER = 33,
/// The port was not a memory cache control port.
INVALID_MEMORY_CONTROL = 34,
/// An argument supplied to assert security privilege
/// was not a host security port.
INVALID_SECURITY = 35,
/// thread_depress_abort was called on a thread which
/// was not currently depressed.
NOT_DEPRESSED = 36,
/// Object has been terminated and is no longer available
TERMINATED = 37,
/// Lock set has been destroyed and is no longer available.
LOCK_SET_DESTROYED = 38,
/// The thread holding the lock terminated before releasing
/// the lock
LOCK_UNSTABLE = 39,
/// The lock is already owned by another thread
LOCK_OWNED = 40,
/// The lock is already owned by the calling thread
LOCK_OWNED_SELF = 41,
/// Semaphore has been destroyed and is no longer available.
SEMAPHORE_DESTROYED = 42,
/// Return from RPC indicating the target server was
/// terminated before it successfully replied
RPC_SERVER_TERMINATED = 43,
/// Terminate an orphaned activation.
RPC_TERMINATE_ORPHAN = 44,
/// Allow an orphaned activation to continue executing.
RPC_CONTINUE_ORPHAN = 45,
/// Empty thread activation (No thread linked to it)
NOT_SUPPORTED = 46,
/// Remote node down or inaccessible.
NODE_DOWN = 47,
/// A signalled thread was not actually waiting.
NOT_WAITING = 48,
/// Some thread-oriented operation (semaphore_wait) timed out
OPERATION_TIMED_OUT = 49,
/// During a page fault, indicates that the page was rejected
/// as a result of a signature check.
CODESIGN_ERROR = 50,
/// The requested property cannot be changed at this time.
POLICY_STATIC = 51,
/// The provided buffer is of insufficient size for the requested data.
INSUFFICIENT_BUFFER_SIZE = 52,
/// Denied by security policy
DENIED = 53,
/// The KC on which the function is operating is missing
MISSING_KC = 54,
/// The KC on which the function is operating is invalid
INVALID_KC = 55,
/// A search or query operation did not return a result
NOT_FOUND = 56,
_,
};
pub const mach_msg_return_t = kern_return_t;
pub fn getMachMsgError(err: mach_msg_return_t) MachMsgE {
return @as(MachMsgE, @enumFromInt(@as(u32, @truncate(@as(usize, @intCast(err))))));
}
/// All special error code bits defined below.
pub const MACH_MSG_MASK: u32 = 0x3e00;
/// No room in IPC name space for another capability name.
pub const MACH_MSG_IPC_SPACE: u32 = 0x2000;
/// No room in VM address space for out-of-line memory.
pub const MACH_MSG_VM_SPACE: u32 = 0x1000;
/// Kernel resource shortage handling out-of-line memory.
pub const MACH_MSG_IPC_KERNEL: u32 = 0x800;
/// Kernel resource shortage handling an IPC capability.
pub const MACH_MSG_VM_KERNEL: u32 = 0x400;
/// Mach msg return values
pub const MachMsgE = enum(u32) {
SUCCESS = 0x00000000,
/// Thread is waiting to send. (Internal use only.)
SEND_IN_PROGRESS = 0x10000001,
/// Bogus in-line data.
SEND_INVALID_DATA = 0x10000002,
/// Bogus destination port.
SEND_INVALID_DEST = 0x10000003,
/// Message not sent before timeout expired.
SEND_TIMED_OUT = 0x10000004,
/// Bogus voucher port.
SEND_INVALID_VOUCHER = 0x10000005,
/// Software interrupt.
SEND_INTERRUPTED = 0x10000007,
/// Data doesn't contain a complete message.
SEND_MSG_TOO_SMALL = 0x10000008,
/// Bogus reply port.
SEND_INVALID_REPLY = 0x10000009,
/// Bogus port rights in the message body.
SEND_INVALID_RIGHT = 0x1000000a,
/// Bogus notify port argument.
SEND_INVALID_NOTIFY = 0x1000000b,
/// Invalid out-of-line memory pointer.
SEND_INVALID_MEMORY = 0x1000000c,
/// No message buffer is available.
SEND_NO_BUFFER = 0x1000000d,
/// Send is too large for port
SEND_TOO_LARGE = 0x1000000e,
/// Invalid msg-type specification.
SEND_INVALID_TYPE = 0x1000000f,
/// A field in the header had a bad value.
SEND_INVALID_HEADER = 0x10000010,
/// The trailer to be sent does not match kernel format.
SEND_INVALID_TRAILER = 0x10000011,
/// The sending thread context did not match the context on the dest port
SEND_INVALID_CONTEXT = 0x10000012,
/// compatibility: no longer a returned error
SEND_INVALID_RT_OOL_SIZE = 0x10000015,
/// The destination port doesn't accept ports in body
SEND_NO_GRANT_DEST = 0x10000016,
/// Message send was rejected by message filter
SEND_MSG_FILTERED = 0x10000017,
/// Thread is waiting for receive. (Internal use only.)
RCV_IN_PROGRESS = 0x10004001,
/// Bogus name for receive port/port-set.
RCV_INVALID_NAME = 0x10004002,
/// Didn't get a message within the timeout value.
RCV_TIMED_OUT = 0x10004003,
/// Message buffer is not large enough for inline data.
RCV_TOO_LARGE = 0x10004004,
/// Software interrupt.
RCV_INTERRUPTED = 0x10004005,
/// compatibility: no longer a returned error
RCV_PORT_CHANGED = 0x10004006,
/// Bogus notify port argument.
RCV_INVALID_NOTIFY = 0x10004007,
/// Bogus message buffer for inline data.
RCV_INVALID_DATA = 0x10004008,
/// Port/set was sent away/died during receive.
RCV_PORT_DIED = 0x10004009,
/// compatibility: no longer a returned error
RCV_IN_SET = 0x1000400a,
/// Error receiving message header. See special bits.
RCV_HEADER_ERROR = 0x1000400b,
/// Error receiving message body. See special bits.
RCV_BODY_ERROR = 0x1000400c,
/// Invalid msg-type specification in scatter list.
RCV_INVALID_TYPE = 0x1000400d,
/// Out-of-line overwrite region is not large enough
RCV_SCATTER_SMALL = 0x1000400e,
/// trailer type or number of trailer elements not supported
RCV_INVALID_TRAILER = 0x1000400f,
/// Waiting for receive with timeout. (Internal use only.)
RCV_IN_PROGRESS_TIMED = 0x10004011,
/// invalid reply port used in a STRICT_REPLY message
RCV_INVALID_REPLY = 0x10004012,
};
pub const SIGSTKSZ = 131072;
pub const MINSIGSTKSZ = 32768;
pub const SS_ONSTACK = 1;
pub const SS_DISABLE = 4;
pub const stack_t = extern struct {
sp: [*]u8,
size: isize,
flags: i32,
};
pub const S = struct {
pub const IFMT = 0o170000;
pub const IFIFO = 0o010000;
pub const IFCHR = 0o020000;
pub const IFDIR = 0o040000;
pub const IFBLK = 0o060000;
pub const IFREG = 0o100000;
pub const IFLNK = 0o120000;
pub const IFSOCK = 0o140000;
pub const IFWHT = 0o160000;
pub const ISUID = 0o4000;
pub const ISGID = 0o2000;
pub const ISVTX = 0o1000;
pub const IRWXU = 0o700;
pub const IRUSR = 0o400;
pub const IWUSR = 0o200;
pub const IXUSR = 0o100;
pub const IRWXG = 0o070;
pub const IRGRP = 0o040;
pub const IWGRP = 0o020;
pub const IXGRP = 0o010;
pub const IRWXO = 0o007;
pub const IROTH = 0o004;
pub const IWOTH = 0o002;
pub const IXOTH = 0o001;
pub fn ISFIFO(m: u32) bool {
return m & IFMT == IFIFO;
}
pub fn ISCHR(m: u32) bool {
return m & IFMT == IFCHR;
}
pub fn ISDIR(m: u32) bool {
return m & IFMT == IFDIR;
}
pub fn ISBLK(m: u32) bool {
return m & IFMT == IFBLK;
}
pub fn ISREG(m: u32) bool {
return m & IFMT == IFREG;
}
pub fn ISLNK(m: u32) bool {
return m & IFMT == IFLNK;
}
pub fn ISSOCK(m: u32) bool {
return m & IFMT == IFSOCK;
}
pub fn IWHT(m: u32) bool {
return m & IFMT == IFWHT;
}
};
pub const HOST_NAME_MAX = 72;
pub const addrinfo = extern struct {
flags: i32,
family: i32,
socktype: i32,
protocol: i32,
addrlen: socklen_t,
canonname: ?[*:0]u8,
addr: ?*sockaddr,
next: ?*addrinfo,
};
pub const RTLD = struct {
pub const LAZY = 0x1;
pub const NOW = 0x2;
pub const LOCAL = 0x4;
pub const GLOBAL = 0x8;
pub const NOLOAD = 0x10;
pub const NODELETE = 0x80;
pub const FIRST = 0x100;
pub const NEXT = @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1)))));
pub const DEFAULT = @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -2)))));
pub const SELF = @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -3)))));
pub const MAIN_ONLY = @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -5)))));
};
pub const F = struct {
/// duplicate file descriptor
pub const DUPFD = 0;
/// get file descriptor flags
pub const GETFD = 1;
/// set file descriptor flags
pub const SETFD = 2;
/// get file status flags
pub const GETFL = 3;
/// set file status flags
pub const SETFL = 4;
/// get SIGIO/SIGURG proc/pgrp
pub const GETOWN = 5;
/// set SIGIO/SIGURG proc/pgrp
pub const SETOWN = 6;
/// get record locking information
pub const GETLK = 7;
/// set record locking information
pub const SETLK = 8;
/// F.SETLK; wait if blocked
pub const SETLKW = 9;
/// F.SETLK; wait if blocked, return on timeout
pub const SETLKWTIMEOUT = 10;
pub const FLUSH_DATA = 40;
/// Used for regression test
pub const CHKCLEAN = 41;
/// Preallocate storage
pub const PREALLOCATE = 42;
/// Truncate a file without zeroing space
pub const SETSIZE = 43;
/// Issue an advisory read async with no copy to user
pub const RDADVISE = 44;
/// turn read ahead off/on for this fd
pub const RDAHEAD = 45;
/// turn data caching off/on for this fd
pub const NOCACHE = 48;
/// file offset to device offset
pub const LOG2PHYS = 49;
/// return the full path of the fd
pub const GETPATH = 50;
/// fsync + ask the drive to flush to the media
pub const FULLFSYNC = 51;
/// find which component (if any) is a package
pub const PATHPKG_CHECK = 52;
/// "freeze" all fs operations
pub const FREEZE_FS = 53;
/// "thaw" all fs operations
pub const THAW_FS = 54;
/// turn data caching off/on (globally) for this file
pub const GLOBAL_NOCACHE = 55;
/// add detached signatures
pub const ADDSIGS = 59;
/// add signature from same file (used by dyld for shared libs)
pub const ADDFILESIGS = 61;
/// used in conjunction with F.NOCACHE to indicate that DIRECT, synchronous writes
/// should not be used (i.e. its ok to temporaily create cached pages)
pub const NODIRECT = 62;
///Get the protection class of a file from the EA, returns int
pub const GETPROTECTIONCLASS = 63;
///Set the protection class of a file for the EA, requires int
pub const SETPROTECTIONCLASS = 64;
///file offset to device offset, extended
pub const LOG2PHYS_EXT = 65;
///get record locking information, per-process
pub const GETLKPID = 66;
///Mark the file as being the backing store for another filesystem
pub const SETBACKINGSTORE = 70;
///return the full path of the FD, but error in specific mtmd circumstances
pub const GETPATH_MTMINFO = 71;
///Returns the code directory, with associated hashes, to the caller
pub const GETCODEDIR = 72;
///No SIGPIPE generated on EPIPE
pub const SETNOSIGPIPE = 73;
///Status of SIGPIPE for this fd
pub const GETNOSIGPIPE = 74;
///For some cases, we need to rewrap the key for AKS/MKB
pub const TRANSCODEKEY = 75;
///file being written to a by single writer... if throttling enabled, writes
///may be broken into smaller chunks with throttling in between
pub const SINGLE_WRITER = 76;
///Get the protection version number for this filesystem
pub const GETPROTECTIONLEVEL = 77;
///Add detached code signatures (used by dyld for shared libs)
pub const FINDSIGS = 78;
///Add signature from same file, only if it is signed by Apple (used by dyld for simulator)
pub const ADDFILESIGS_FOR_DYLD_SIM = 83;
///fsync + issue barrier to drive
pub const BARRIERFSYNC = 85;
///Add signature from same file, return end offset in structure on success
pub const ADDFILESIGS_RETURN = 97;
///Check if Library Validation allows this Mach-O file to be mapped into the calling process
pub const CHECK_LV = 98;
///Deallocate a range of the file
pub const PUNCHHOLE = 99;
///Trim an active file
pub const TRIM_ACTIVE_FILE = 100;
///mark the dup with FD_CLOEXEC
pub const DUPFD_CLOEXEC = 67;
/// shared or read lock
pub const RDLCK = 1;
/// unlock
pub const UNLCK = 2;
/// exclusive or write lock
pub const WRLCK = 3;
};
pub const FCNTL_FS_SPECIFIC_BASE = 0x00010000;
///close-on-exec flag
pub const FD_CLOEXEC = 1;
pub const LOCK = struct {
pub const SH = 1;
pub const EX = 2;
pub const UN = 8;
pub const NB = 4;
};
pub const nfds_t = u32;
pub const pollfd = extern struct {
fd: fd_t,
events: i16,
revents: i16,
};
pub const POLL = struct {
pub const IN = 0x001;
pub const PRI = 0x002;
pub const OUT = 0x004;
pub const RDNORM = 0x040;
pub const WRNORM = OUT;
pub const RDBAND = 0x080;
pub const WRBAND = 0x100;
pub const EXTEND = 0x0200;
pub const ATTRIB = 0x0400;
pub const NLINK = 0x0800;
pub const WRITE = 0x1000;
pub const ERR = 0x008;
pub const HUP = 0x010;
pub const NVAL = 0x020;
pub const STANDARD = IN | PRI | OUT | RDNORM | RDBAND | WRBAND | ERR | HUP | NVAL;
};
pub const CLOCK = struct {
pub const REALTIME = 0;
pub const MONOTONIC = 6;
pub const MONOTONIC_RAW = 4;
pub const MONOTONIC_RAW_APPROX = 5;
pub const UPTIME_RAW = 8;
pub const UPTIME_RAW_APPROX = 9;
pub const PROCESS_CPUTIME_ID = 12;
pub const THREAD_CPUTIME_ID = 16;
};
/// Max open files per process
/// https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/sys/syslimits.h.auto.html
pub const OPEN_MAX = 10240;
pub const rusage = extern struct {
utime: timeval,
stime: timeval,
maxrss: isize,
ixrss: isize,
idrss: isize,
isrss: isize,
minflt: isize,
majflt: isize,
nswap: isize,
inblock: isize,
oublock: isize,
msgsnd: isize,
msgrcv: isize,
nsignals: isize,
nvcsw: isize,
nivcsw: isize,
pub const SELF = 0;
pub const CHILDREN = -1;
};
pub const rlimit_resource = enum(c_int) {
CPU = 0,
FSIZE = 1,
DATA = 2,
STACK = 3,
CORE = 4,
RSS = 5,
MEMLOCK = 6,
NPROC = 7,
NOFILE = 8,
_,
pub const AS: rlimit_resource = .RSS;
};
pub const rlim_t = u64;
pub const RLIM = struct {
/// No limit
pub const INFINITY: rlim_t = (1 << 63) - 1;
pub const SAVED_MAX = INFINITY;
pub const SAVED_CUR = INFINITY;
};
pub const rlimit = extern struct {
/// Soft limit
cur: rlim_t,
/// Hard limit
max: rlim_t,
};
pub const SHUT = struct {
pub const RD = 0;
pub const WR = 1;
pub const RDWR = 2;
};
pub const TCSA = enum(c_uint) {
NOW,
DRAIN,
FLUSH,
_,
};
pub const winsize = extern struct {
ws_row: u16,
ws_col: u16,
ws_xpixel: u16,
ws_ypixel: u16,
};
pub const T = struct {
pub const IOCGWINSZ = ior(0x40000000, 't', 104, @sizeOf(winsize));
};
pub const IOCPARM_MASK = 0x1fff;
fn ior(inout: u32, group: usize, num: usize, len: usize) usize {
return (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num));
}
// CPU families mapping
pub const CPUFAMILY = enum(u32) {
UNKNOWN = 0,
POWERPC_G3 = 0xcee41549,
POWERPC_G4 = 0x77c184ae,
POWERPC_G5 = 0xed76d8aa,
INTEL_6_13 = 0xaa33392b,
INTEL_PENRYN = 0x78ea4fbc,
INTEL_NEHALEM = 0x6b5a4cd2,
INTEL_WESTMERE = 0x573b5eec,
INTEL_SANDYBRIDGE = 0x5490b78c,
INTEL_IVYBRIDGE = 0x1f65e835,
INTEL_HASWELL = 0x10b282dc,
INTEL_BROADWELL = 0x582ed09c,
INTEL_SKYLAKE = 0x37fc219f,
INTEL_KABYLAKE = 0x0f817246,
ARM_9 = 0xe73283ae,
ARM_11 = 0x8ff620d8,
ARM_XSCALE = 0x53b005f5,
ARM_12 = 0xbd1b0ae9,
ARM_13 = 0x0cc90e64,
ARM_14 = 0x96077ef1,
ARM_15 = 0xa8511bca,
ARM_SWIFT = 0x1e2d6381,
ARM_CYCLONE = 0x37a09642,
ARM_TYPHOON = 0x2c91a47e,
ARM_TWISTER = 0x92fb37c8,
ARM_HURRICANE = 0x67ceee93,
ARM_MONSOON_MISTRAL = 0xe81e7ef6,
ARM_VORTEX_TEMPEST = 0x07d34b9f,
ARM_LIGHTNING_THUNDER = 0x462504d2,
ARM_FIRESTORM_ICESTORM = 0x1b588bb3,
ARM_BLIZZARD_AVALANCHE = 0xda33d83d,
ARM_EVEREST_SAWTOOTH = 0x8765edea,
_,
};
pub const PT = struct {
pub const TRACE_ME = 0;
pub const READ_I = 1;
pub const READ_D = 2;
pub const READ_U = 3;
pub const WRITE_I = 4;
pub const WRITE_D = 5;
pub const WRITE_U = 6;
pub const CONTINUE = 7;
pub const KILL = 8;
pub const STEP = 9;
pub const DETACH = 11;
pub const SIGEXC = 12;
pub const THUPDATE = 13;
pub const ATTACHEXC = 14;
pub const FORCEQUOTA = 30;
pub const DENY_ATTACH = 31;
};
pub const caddr_t = ?[*]u8;
pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
pub const POSIX_SPAWN = struct {
pub const RESETIDS = 0x0001;
pub const SETPGROUP = 0x0002;
pub const SETSIGDEF = 0x0004;
pub const SETSIGMASK = 0x0008;
pub const SETEXEC = 0x0040;
pub const START_SUSPENDED = 0x0080;
pub const DISABLE_ASLR = 0x0100;
pub const SETSID = 0x0400;
pub const RESLIDE = 0x0800;
pub const CLOEXEC_DEFAULT = 0x4000;
};
pub const posix_spawnattr_t = *opaque {};
pub const posix_spawn_file_actions_t = *opaque {};
pub extern "c" fn posix_spawnattr_init(attr: *posix_spawnattr_t) c_int;
pub extern "c" fn posix_spawnattr_destroy(attr: *posix_spawnattr_t) c_int;
pub extern "c" fn posix_spawnattr_setflags(attr: *posix_spawnattr_t, flags: c_short) c_int;
pub extern "c" fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *c_short) c_int;
pub extern "c" fn posix_spawn_file_actions_init(actions: *posix_spawn_file_actions_t) c_int;
pub extern "c" fn posix_spawn_file_actions_destroy(actions: *posix_spawn_file_actions_t) c_int;
pub extern "c" fn posix_spawn_file_actions_addclose(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
pub extern "c" fn posix_spawn_file_actions_addopen(
actions: *posix_spawn_file_actions_t,
filedes: fd_t,
path: [*:0]const u8,
oflag: c_int,
mode: mode_t,
) c_int;
pub extern "c" fn posix_spawn_file_actions_adddup2(
actions: *posix_spawn_file_actions_t,
filedes: fd_t,
newfiledes: fd_t,
) c_int;
pub extern "c" fn posix_spawn_file_actions_addinherit_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
pub extern "c" fn posix_spawn_file_actions_addchdir_np(actions: *posix_spawn_file_actions_t, path: [*:0]const u8) c_int;
pub extern "c" fn posix_spawn_file_actions_addfchdir_np(actions: *posix_spawn_file_actions_t, filedes: fd_t) c_int;
pub extern "c" fn posix_spawn(
pid: *pid_t,
path: [*:0]const u8,
actions: ?*const posix_spawn_file_actions_t,
attr: ?*const posix_spawnattr_t,
argv: [*:null]?[*:0]const u8,
env: [*:null]?[*:0]const u8,
) c_int;
pub extern "c" fn posix_spawnp(
pid: *pid_t,
path: [*:0]const u8,
actions: ?*const posix_spawn_file_actions_t,
attr: ?*const posix_spawnattr_t,
argv: [*:null]?[*:0]const u8,
env: [*:null]?[*:0]const u8,
) c_int;
pub const PosixSpawn = struct {
const errno = std.os.errno;
const unexpectedErrno = std.os.unexpectedErrno;
pub const Error = error{
SystemResources,
InvalidFileDescriptor,
NameTooLong,
TooBig,
PermissionDenied,
InputOutput,
FileSystem,
FileNotFound,
InvalidExe,
NotDir,
FileBusy,
/// Returned when the child fails to execute either in the pre-exec() initialization step, or
/// when exec(3) is invoked.
ChildExecFailed,
} || std.os.UnexpectedError;
pub const Attr = struct {
attr: posix_spawnattr_t,
pub fn init() Error!Attr {
var attr: posix_spawnattr_t = undefined;
switch (errno(posix_spawnattr_init(&attr))) {
.SUCCESS => return Attr{ .attr = attr },
.NOMEM => return error.SystemResources,
.INVAL => unreachable,
else => |err| return unexpectedErrno(err),
}
}
pub fn deinit(self: *Attr) void {
defer self.* = undefined;
switch (errno(posix_spawnattr_destroy(&self.attr))) {
.SUCCESS => return,
.INVAL => unreachable, // Invalid parameters.
else => unreachable,
}
}
pub fn get(self: Attr) Error!u16 {
var flags: c_short = undefined;
switch (errno(posix_spawnattr_getflags(&self.attr, &flags))) {
.SUCCESS => return @as(u16, @bitCast(flags)),
.INVAL => unreachable,
else => |err| return unexpectedErrno(err),
}
}
pub fn set(self: *Attr, flags: u16) Error!void {
switch (errno(posix_spawnattr_setflags(&self.attr, @as(c_short, @bitCast(flags))))) {
.SUCCESS => return,
.INVAL => unreachable,
else => |err| return unexpectedErrno(err),
}
}
};
pub const Actions = struct {
actions: posix_spawn_file_actions_t,
pub fn init() Error!Actions {
var actions: posix_spawn_file_actions_t = undefined;
switch (errno(posix_spawn_file_actions_init(&actions))) {
.SUCCESS => return Actions{ .actions = actions },
.NOMEM => return error.SystemResources,
.INVAL => unreachable,
else => |err| return unexpectedErrno(err),
}
}
pub fn deinit(self: *Actions) void {
defer self.* = undefined;
switch (errno(posix_spawn_file_actions_destroy(&self.actions))) {
.SUCCESS => return,
.INVAL => unreachable, // Invalid parameters.
else => unreachable,
}
}
pub fn open(self: *Actions, fd: fd_t, path: []const u8, flags: u32, mode: mode_t) Error!void {
const posix_path = try std.os.toPosixPath(path);
return self.openZ(fd, &posix_path, flags, mode);
}
pub fn openZ(self: *Actions, fd: fd_t, path: [*:0]const u8, flags: u32, mode: mode_t) Error!void {
switch (errno(posix_spawn_file_actions_addopen(&self.actions, fd, path, @as(c_int, @bitCast(flags)), mode))) {
.SUCCESS => return,
.BADF => return error.InvalidFileDescriptor,
.NOMEM => return error.SystemResources,
.NAMETOOLONG => return error.NameTooLong,
.INVAL => unreachable, // the value of file actions is invalid
else => |err| return unexpectedErrno(err),
}
}
pub fn close(self: *Actions, fd: fd_t) Error!void {
switch (errno(posix_spawn_file_actions_addclose(&self.actions, fd))) {
.SUCCESS => return,
.BADF => return error.InvalidFileDescriptor,
.NOMEM => return error.SystemResources,
.INVAL => unreachable, // the value of file actions is invalid
.NAMETOOLONG => unreachable,
else => |err| return unexpectedErrno(err),
}
}
pub fn dup2(self: *Actions, fd: fd_t, newfd: fd_t) Error!void {
switch (errno(posix_spawn_file_actions_adddup2(&self.actions, fd, newfd))) {
.SUCCESS => return,
.BADF => return error.InvalidFileDescriptor,
.NOMEM => return error.SystemResources,
.INVAL => unreachable, // the value of file actions is invalid
.NAMETOOLONG => unreachable,
else => |err| return unexpectedErrno(err),
}
}
pub fn inherit(self: *Actions, fd: fd_t) Error!void {
switch (errno(posix_spawn_file_actions_addinherit_np(&self.actions, fd))) {
.SUCCESS => return,
.BADF => return error.InvalidFileDescriptor,
.NOMEM => return error.SystemResources,
.INVAL => unreachable, // the value of file actions is invalid
.NAMETOOLONG => unreachable,
else => |err| return unexpectedErrno(err),
}
}
pub fn chdir(self: *Actions, path: []const u8) Error!void {
const posix_path = try std.os.toPosixPath(path);
return self.chdirZ(&posix_path);
}
pub fn chdirZ(self: *Actions, path: [*:0]const u8) Error!void {
switch (errno(posix_spawn_file_actions_addchdir_np(&self.actions, path))) {
.SUCCESS => return,
.NOMEM => return error.SystemResources,
.NAMETOOLONG => return error.NameTooLong,
.BADF => unreachable,
.INVAL => unreachable, // the value of file actions is invalid
else => |err| return unexpectedErrno(err),
}
}
pub fn fchdir(self: *Actions, fd: fd_t) Error!void {
switch (errno(posix_spawn_file_actions_addfchdir_np(&self.actions, fd))) {
.SUCCESS => return,
.BADF => return error.InvalidFileDescriptor,
.NOMEM => return error.SystemResources,
.INVAL => unreachable, // the value of file actions is invalid
.NAMETOOLONG => unreachable,
else => |err| return unexpectedErrno(err),
}
}
};
pub fn spawn(
path: []const u8,
actions: ?Actions,
attr: ?Attr,
argv: [*:null]?[*:0]const u8,
envp: [*:null]?[*:0]const u8,
) Error!pid_t {
const posix_path = try std.os.toPosixPath(path);
return spawnZ(&posix_path, actions, attr, argv, envp);
}
pub fn spawnZ(
path: [*:0]const u8,
actions: ?Actions,
attr: ?Attr,
argv: [*:null]?[*:0]const u8,
envp: [*:null]?[*:0]const u8,
) Error!pid_t {
var pid: pid_t = undefined;
switch (errno(posix_spawn(
&pid,
path,
if (actions) |a| &a.actions else null,
if (attr) |a| &a.attr else null,
argv,
envp,
))) {
.SUCCESS => return pid,
.@"2BIG" => return error.TooBig,
.NOMEM => return error.SystemResources,
.BADF => return error.InvalidFileDescriptor,
.ACCES => return error.PermissionDenied,
.IO => return error.InputOutput,
.LOOP => return error.FileSystem,
.NAMETOOLONG => return error.NameTooLong,
.NOENT => return error.FileNotFound,
.NOEXEC => return error.InvalidExe,
.NOTDIR => return error.NotDir,
.TXTBSY => return error.FileBusy,
.BADARCH => return error.InvalidExe,
.BADEXEC => return error.InvalidExe,
.FAULT => unreachable,
.INVAL => unreachable,
else => |err| return unexpectedErrno(err),
}
}
pub fn waitpid(pid: pid_t, flags: u32) Error!std.os.WaitPidResult {
var status: c_int = undefined;
while (true) {
const rc = waitpid(pid, &status, @as(c_int, @intCast(flags)));
switch (errno(rc)) {
.SUCCESS => return std.os.WaitPidResult{
.pid = @as(pid_t, @intCast(rc)),
.status = @as(u32, @bitCast(status)),
},
.INTR => continue,
.CHILD => return error.ChildExecFailed,
.INVAL => unreachable, // Invalid flags.
else => unreachable,
}
}
}
};
pub fn getKernError(err: kern_return_t) KernE {
return @as(KernE, @enumFromInt(@as(u32, @truncate(@as(usize, @intCast(err))))));
}
pub fn unexpectedKernError(err: KernE) std.os.UnexpectedError {
if (std.os.unexpected_error_tracing) {
std.debug.print("unexpected error: {d}\n", .{@intFromEnum(err)});
std.debug.dumpCurrentStackTrace(null);
}
return error.Unexpected;
}
pub const MachError = error{
/// Not enough permissions held to perform the requested kernel
/// call.
PermissionDenied,
} || std.os.UnexpectedError;
pub const MachTask = extern struct {
port: mach_port_name_t,
pub fn isValid(self: MachTask) bool {
return self.port != TASK_NULL;
}
pub fn pidForTask(self: MachTask) MachError!std.os.pid_t {
var pid: std.os.pid_t = undefined;
switch (getKernError(pid_for_task(self.port, &pid))) {
.SUCCESS => return pid,
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
pub fn allocatePort(self: MachTask, right: MACH_PORT_RIGHT) MachError!MachTask {
var out_port: mach_port_name_t = undefined;
switch (getKernError(mach_port_allocate(
self.port,
@intFromEnum(right),
&out_port,
))) {
.SUCCESS => return .{ .port = out_port },
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
pub fn deallocatePort(self: MachTask, port: MachTask) void {
_ = getKernError(mach_port_deallocate(self.port, port.port));
}
pub fn insertRight(self: MachTask, port: MachTask, msg: MACH_MSG_TYPE) !void {
switch (getKernError(mach_port_insert_right(
self.port,
port.port,
port.port,
@intFromEnum(msg),
))) {
.SUCCESS => return,
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
pub const PortInfo = struct {
mask: exception_mask_t,
masks: [EXC_TYPES_COUNT]exception_mask_t,
ports: [EXC_TYPES_COUNT]mach_port_t,
behaviors: [EXC_TYPES_COUNT]exception_behavior_t,
flavors: [EXC_TYPES_COUNT]thread_state_flavor_t,
count: mach_msg_type_number_t,
};
pub fn getExceptionPorts(self: MachTask, mask: exception_mask_t) !PortInfo {
var info = PortInfo{
.mask = mask,
.masks = undefined,
.ports = undefined,
.behaviors = undefined,
.flavors = undefined,
.count = 0,
};
info.count = info.ports.len / @sizeOf(mach_port_t);
switch (getKernError(task_get_exception_ports(
self.port,
info.mask,
&info.masks,
&info.count,
&info.ports,
&info.behaviors,
&info.flavors,
))) {
.SUCCESS => return info,
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
pub fn setExceptionPorts(
self: MachTask,
mask: exception_mask_t,
new_port: MachTask,
behavior: exception_behavior_t,
new_flavor: thread_state_flavor_t,
) !void {
switch (getKernError(task_set_exception_ports(
self.port,
mask,
new_port.port,
behavior,
new_flavor,
))) {
.SUCCESS => return,
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
pub const RegionInfo = struct {
pub const Tag = enum {
basic,
extended,
top,
};
base_addr: u64,
tag: Tag,
info: union {
basic: vm_region_basic_info_64,
extended: vm_region_extended_info,
top: vm_region_top_info,
},
};
pub fn getRegionInfo(
task: MachTask,
address: u64,
len: usize,
tag: RegionInfo.Tag,
) MachError!RegionInfo {
var info: RegionInfo = .{
.base_addr = address,
.tag = tag,
.info = undefined,
};
switch (tag) {
.basic => info.info = .{ .basic = undefined },
.extended => info.info = .{ .extended = undefined },
.top => info.info = .{ .top = undefined },
}
var base_len: mach_vm_size_t = if (len == 1) 2 else len;
var objname: mach_port_t = undefined;
var count: mach_msg_type_number_t = switch (tag) {
.basic => VM_REGION_BASIC_INFO_COUNT,
.extended => VM_REGION_EXTENDED_INFO_COUNT,
.top => VM_REGION_TOP_INFO_COUNT,
};
switch (getKernError(mach_vm_region(
task.port,
&info.base_addr,
&base_len,
switch (tag) {
.basic => VM_REGION_BASIC_INFO_64,
.extended => VM_REGION_EXTENDED_INFO,
.top => VM_REGION_TOP_INFO,
},
switch (tag) {
.basic => @as(vm_region_info_t, @ptrCast(&info.info.basic)),
.extended => @as(vm_region_info_t, @ptrCast(&info.info.extended)),
.top => @as(vm_region_info_t, @ptrCast(&info.info.top)),
},
&count,
&objname,
))) {
.SUCCESS => return info,
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
pub const RegionSubmapInfo = struct {
pub const Tag = enum {
short,
full,
};
tag: Tag,
base_addr: u64,
info: union {
short: vm_region_submap_short_info_64,
full: vm_region_submap_info_64,
},
};
pub fn getRegionSubmapInfo(
task: MachTask,
address: u64,
len: usize,
nesting_depth: u32,
tag: RegionSubmapInfo.Tag,
) MachError!RegionSubmapInfo {
var info: RegionSubmapInfo = .{
.base_addr = address,
.tag = tag,
.info = undefined,
};
switch (tag) {
.short => info.info = .{ .short = undefined },
.full => info.info = .{ .full = undefined },
}
var nesting = nesting_depth;
var base_len: mach_vm_size_t = if (len == 1) 2 else len;
var count: mach_msg_type_number_t = switch (tag) {
.short => VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
.full => VM_REGION_SUBMAP_INFO_COUNT_64,
};
switch (getKernError(mach_vm_region_recurse(
task.port,
&info.base_addr,
&base_len,
&nesting,
switch (tag) {
.short => @as(vm_region_recurse_info_t, @ptrCast(&info.info.short)),
.full => @as(vm_region_recurse_info_t, @ptrCast(&info.info.full)),
},
&count,
))) {
.SUCCESS => return info,
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!vm_prot_t {
const info = try task.getRegionSubmapInfo(address, len, 0, .short);
return info.info.short.protection;
}
pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: vm_prot_t) MachError!void {
return task.setProtectionImpl(address, len, true, prot);
}
pub fn setCurrProtection(task: MachTask, address: u64, len: usize, prot: vm_prot_t) MachError!void {
return task.setProtectionImpl(address, len, false, prot);
}
fn setProtectionImpl(task: MachTask, address: u64, len: usize, set_max: bool, prot: vm_prot_t) MachError!void {
switch (getKernError(mach_vm_protect(task.port, address, len, @intFromBool(set_max), prot))) {
.SUCCESS => return,
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
}
/// Will write to VM even if current protection attributes specifically prohibit
/// us from doing so, by temporarily setting protection level to a level with VM_PROT_COPY
/// variant, and resetting after a successful or unsuccessful write.
pub fn writeMemProtected(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize {
const curr_prot = try task.getCurrProtection(address, buf.len);
try task.setCurrProtection(
address,
buf.len,
PROT.READ | PROT.WRITE | PROT.COPY,
);
defer {
task.setCurrProtection(address, buf.len, curr_prot) catch {};
}
return task.writeMem(address, buf, arch);
}
pub fn writeMem(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize {
const count = buf.len;
var total_written: usize = 0;
var curr_addr = address;
const page_size = try getPageSize(task); // TODO we probably can assume value here
var out_buf = buf[0..];
while (total_written < count) {
const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_written);
switch (getKernError(mach_vm_write(
task.port,
curr_addr,
@intFromPtr(out_buf.ptr),
@as(mach_msg_type_number_t, @intCast(curr_size)),
))) {
.SUCCESS => {},
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
switch (arch) {
.aarch64 => {
var mattr_value: vm_machine_attribute_val_t = MATTR_VAL_CACHE_FLUSH;
switch (getKernError(vm_machine_attribute(
task.port,
curr_addr,
curr_size,
MATTR_CACHE,
&mattr_value,
))) {
.SUCCESS => {},
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
},
.x86_64 => {},
else => unreachable,
}
out_buf = out_buf[curr_size..];
total_written += curr_size;
curr_addr += curr_size;
}
return total_written;
}
pub fn readMem(task: MachTask, address: u64, buf: []u8) MachError!usize {
const count = buf.len;
var total_read: usize = 0;
var curr_addr = address;
const page_size = try getPageSize(task); // TODO we probably can assume value here
var out_buf = buf[0..];
while (total_read < count) {
const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_read);
var curr_bytes_read: mach_msg_type_number_t = 0;
var vm_memory: vm_offset_t = undefined;
switch (getKernError(mach_vm_read(task.port, curr_addr, curr_size, &vm_memory, &curr_bytes_read))) {
.SUCCESS => {},
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
@memcpy(out_buf[0..curr_bytes_read], @as([*]const u8, @ptrFromInt(vm_memory)));
_ = vm_deallocate(mach_task_self(), vm_memory, curr_bytes_read);
out_buf = out_buf[curr_bytes_read..];
curr_addr += curr_bytes_read;
total_read += curr_bytes_read;
}
return total_read;
}
fn maxBytesLeftInPage(page_size: usize, address: u64, count: usize) usize {
var left = count;
if (page_size > 0) {
const page_offset = address % page_size;
const bytes_left_in_page = page_size - page_offset;
if (count > bytes_left_in_page) {
left = bytes_left_in_page;
}
}
return left;
}
fn getPageSize(task: MachTask) MachError!usize {
if (task.isValid()) {
var info_count = TASK_VM_INFO_COUNT;
var vm_info: task_vm_info_data_t = undefined;
switch (getKernError(task_info(
task.port,
TASK_VM_INFO,
@as(task_info_t, @ptrCast(&vm_info)),
&info_count,
))) {
.SUCCESS => return @as(usize, @intCast(vm_info.page_size)),
else => {},
}
}
var page_size: vm_size_t = undefined;
switch (getKernError(_host_page_size(mach_host_self(), &page_size))) {
.SUCCESS => return page_size,
else => |err| return unexpectedKernError(err),
}
}
pub fn basicTaskInfo(task: MachTask) MachError!mach_task_basic_info {
var info: mach_task_basic_info = undefined;
var count = MACH_TASK_BASIC_INFO_COUNT;
switch (getKernError(task_info(
task.port,
MACH_TASK_BASIC_INFO,
@as(task_info_t, @ptrCast(&info)),
&count,
))) {
.SUCCESS => return info,
else => |err| return unexpectedKernError(err),
}
}
pub fn @"resume"(task: MachTask) MachError!void {
switch (getKernError(task_resume(task.port))) {
.SUCCESS => {},
else => |err| return unexpectedKernError(err),
}
}
pub fn @"suspend"(task: MachTask) MachError!void {
switch (getKernError(task_suspend(task.port))) {
.SUCCESS => {},
else => |err| return unexpectedKernError(err),
}
}
const ThreadList = struct {
buf: []MachThread,
pub fn deinit(list: ThreadList) void {
const self_task = machTaskForSelf();
_ = vm_deallocate(
self_task.port,
@intFromPtr(list.buf.ptr),
@as(vm_size_t, @intCast(list.buf.len * @sizeOf(mach_port_t))),
);
}
};
pub fn getThreads(task: MachTask) MachError!ThreadList {
var thread_list: mach_port_array_t = undefined;
var thread_count: mach_msg_type_number_t = undefined;
switch (getKernError(task_threads(task.port, &thread_list, &thread_count))) {
.SUCCESS => return ThreadList{ .buf = @as([*]MachThread, @ptrCast(thread_list))[0..thread_count] },
else => |err| return unexpectedKernError(err),
}
}
};
pub const MachThread = extern struct {
port: mach_port_t,
pub fn isValid(thread: MachThread) bool {
return thread.port != THREAD_NULL;
}
pub fn getBasicInfo(thread: MachThread) MachError!thread_basic_info {
var info: thread_basic_info = undefined;
var count = THREAD_BASIC_INFO_COUNT;
switch (getKernError(thread_info(
thread.port,
THREAD_BASIC_INFO,
@as(thread_info_t, @ptrCast(&info)),
&count,
))) {
.SUCCESS => return info,
else => |err| return unexpectedKernError(err),
}
}
pub fn getIdentifierInfo(thread: MachThread) MachError!thread_identifier_info {
var info: thread_identifier_info = undefined;
var count = THREAD_IDENTIFIER_INFO_COUNT;
switch (getKernError(thread_info(
thread.port,
THREAD_IDENTIFIER_INFO,
@as(thread_info_t, @ptrCast(&info)),
&count,
))) {
.SUCCESS => return info,
else => |err| return unexpectedKernError(err),
}
}
};
pub fn machTaskForPid(pid: std.os.pid_t) MachError!MachTask {
var port: mach_port_name_t = undefined;
switch (getKernError(task_for_pid(mach_task_self(), pid, &port))) {
.SUCCESS => {},
.FAILURE => return error.PermissionDenied,
else => |err| return unexpectedKernError(err),
}
return MachTask{ .port = port };
}
pub fn machTaskForSelf() MachTask {
return .{ .port = mach_task_self() };
}
pub const os_signpost_id_t = u64;
pub const OS_SIGNPOST_ID_NULL: os_signpost_id_t = 0;
pub const OS_SIGNPOST_ID_INVALID: os_signpost_id_t = !0;
pub const OS_SIGNPOST_ID_EXCLUSIVE: os_signpost_id_t = 0xeeeeb0b5b2b2eeee;
pub const os_log_t = opaque {};
pub const os_log_type_t = enum(u8) {
/// default messages always captures
OS_LOG_TYPE_DEFAULT = 0x00,
/// messages with additional infos
OS_LOG_TYPE_INFO = 0x01,
/// debug messages
OS_LOG_TYPE_DEBUG = 0x02,
/// error messages
OS_LOG_TYPE_ERROR = 0x10,
/// unexpected conditions messages
OS_LOG_TYPE_FAULT = 0x11,
};
pub const OS_LOG_CATEGORY_POINTS_OF_INTEREST: *const u8 = "PointsOfInterest";
pub const OS_LOG_CATEGORY_DYNAMIC_TRACING: *const u8 = "DynamicTracing";
pub const OS_LOG_CATEGORY_DYNAMIC_STACK_TRACING: *const u8 = "DynamicStackTracing";
pub extern "c" fn os_log_create(subsystem: [*]const u8, category: [*]const u8) os_log_t;
pub extern "c" fn os_log_type_enabled(log: os_log_t, tpe: os_log_type_t) bool;
pub extern "c" fn os_signpost_id_generate(log: os_log_t) os_signpost_id_t;
pub extern "c" fn os_signpost_interval_begin(log: os_log_t, signpos: os_signpost_id_t, func: [*]const u8, ...) void;
pub extern "c" fn os_signpost_interval_end(log: os_log_t, signpos: os_signpost_id_t, func: [*]const u8, ...) void;
pub extern "c" fn os_signpost_id_make_with_pointer(log: os_log_t, ptr: ?*anyopaque) os_signpost_id_t;
pub extern "c" fn os_signpost_enabled(log: os_log_t) bool;