Commit ec2697b7ea

Jakub Konka <kubkon@jakubkonka.com>
2022-12-14 00:10:14
darwin: add even more wrappers for Mach syscalls
Rename `ThreadId` to `MachThread`.
1 parent f5336a8
Changed files (3)
lib/std/c/darwin.zig
@@ -102,6 +102,8 @@ pub const MACH_EXCEPTION_MASK = MACH_EXCEPTION_CODES |
 
 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;
 
@@ -406,6 +408,7 @@ 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,
@@ -3054,11 +3057,20 @@ pub const _POSIX_SPAWN_RESLIDE = 0x0800;
 pub const POSIX_SPAWN_CLOEXEC_DEFAULT = 0x4000;
 
 pub const PT_TRACE_ME = 0;
+pub const PT_READ_I = 1;
+pub const PT_READ_D = 2;
+pub const PT_READ_U = 3;
+pub const PT_WRITE_I = 4;
+pub const PT_WRITE_D = 5;
+pub const PT_WRITE_U = 6;
 pub const PT_CONTINUE = 7;
 pub const PT_KILL = 8;
 pub const PT_STEP = 9;
 pub const PT_DETACH = 11;
+pub const PT_SIGEXC = 12;
+pub const PT_THUPDATE = 13;
 pub const PT_ATTACHEXC = 14;
+pub const PT_FORCEQUOTA = 30;
 pub const PT_DENY_ATTACH = 31;
 
 pub const caddr_t = ?[*]u8;
lib/std/os/darwin.zig
@@ -24,6 +24,18 @@ const mach_task = if (builtin.target.isDarwin()) struct {
             return self.port != std.c.TASK_NULL;
         }
 
+        pub fn pidForTask(self: MachTask) MachError!std.os.pid_t {
+            var pid: std.os.pid_t = undefined;
+            switch (std.c.getKernError(std.c.pid_for_task(self.port, &pid))) {
+                .SUCCESS => return pid,
+                .FAILURE => return error.PermissionDenied,
+                else => |err| {
+                    log.err("pid_for_task kernel call failed with error code: {s}", .{@tagName(err)});
+                    return error.Unexpected;
+                },
+            }
+        }
+
         pub fn allocatePort(self: MachTask, right: std.c.MACH_PORT_RIGHT) MachError!MachTask {
             var out_port: std.c.mach_port_name_t = undefined;
             switch (std.c.getKernError(std.c.mach_port_allocate(
@@ -440,7 +452,7 @@ const mach_task = if (builtin.target.isDarwin()) struct {
         }
 
         const ThreadList = struct {
-            buf: []ThreadId,
+            buf: []MachThread,
 
             pub fn deinit(list: ThreadList) void {
                 const self_task = machTaskForSelf();
@@ -456,7 +468,7 @@ const mach_task = if (builtin.target.isDarwin()) struct {
             var thread_list: std.c.mach_port_array_t = undefined;
             var thread_count: std.c.mach_msg_type_number_t = undefined;
             switch (std.c.getKernError(std.c.task_threads(task.port, &thread_list, &thread_count))) {
-                .SUCCESS => return ThreadList{ .buf = @ptrCast([*]ThreadId, thread_list)[0..thread_count] },
+                .SUCCESS => return ThreadList{ .buf = @ptrCast([*]MachThread, thread_list)[0..thread_count] },
                 else => |err| {
                     log.err("task_threads kernel call failed with error code: {s}", .{@tagName(err)});
                     return error.Unexpected;
@@ -465,14 +477,18 @@ const mach_task = if (builtin.target.isDarwin()) struct {
         }
     };
 
-    pub const ThreadId = extern struct {
-        id: std.c.thread_act_t,
+    pub const MachThread = extern struct {
+        port: std.c.mach_port_t,
+
+        pub fn isValid(thread: MachThread) bool {
+            return thread.port != std.c.THREAD_NULL;
+        }
 
-        pub fn getBasicInfo(thread_id: ThreadId) MachError!std.c.thread_basic_info {
+        pub fn getBasicInfo(thread: MachThread) MachError!std.c.thread_basic_info {
             var info: std.c.thread_basic_info = undefined;
             var count = std.c.THREAD_BASIC_INFO_COUNT;
             switch (std.c.getKernError(std.c.thread_info(
-                thread_id.id,
+                thread.port,
                 std.c.THREAD_BASIC_INFO,
                 @ptrCast(std.c.thread_info_t, &info),
                 &count,
@@ -485,11 +501,11 @@ const mach_task = if (builtin.target.isDarwin()) struct {
             }
         }
 
-        pub fn getIdentifierInfo(thread_id: ThreadId) MachError!std.c.thread_identifier_info {
+        pub fn getIdentifierInfo(thread: MachThread) MachError!std.c.thread_identifier_info {
             var info: std.c.thread_identifier_info = undefined;
             var count = std.c.THREAD_IDENTIFIER_INFO_COUNT;
             switch (std.c.getKernError(std.c.thread_info(
-                thread_id.id,
+                thread.port,
                 std.c.THREAD_IDENTIFIER_INFO,
                 @ptrCast(std.c.thread_info_t, &info),
                 &count,
lib/std/os/ptrace.zig
@@ -16,8 +16,8 @@ const ptrace = if (builtin.target.isDarwin()) struct {
         PermissionDenied,
     } || UnexpectedError;
 
-    pub fn ptrace(request: i32, pid: pid_t) PtraceError!void {
-        switch (errno(system.ptrace(request, pid, null, 0))) {
+    pub fn ptrace(request: i32, pid: pid_t, addr: ?[*]u8, signal: i32) PtraceError!void {
+        switch (errno(system.ptrace(request, pid, addr, signal))) {
             .SUCCESS => return,
             .SRCH => return error.ProcessNotFound,
             .INVAL => unreachable,