authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-14 17:42:02+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-14 17:42:02+01:00
logb27b17e2533505955622ea9950aaacb87f87c4fb
treed0c06156cf9272dbce9c5f156197dd16c105de34
parent0b4461d97b5d315e71302f96076c54bbdffb7717
parentec2697b7ea355281330df0bab91c4a09f6466950
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13935 from ziglang/mach-tasks

darwin: expose more Mach primitives, expose wrapped ptrace, and allow starting suspended for posix_spawn

7 files changed, 690 insertions(+), 6 deletions(-)

lib/std/c/darwin.zig+393-4
...@@ -15,6 +15,131 @@ const arch_bits = switch (native_arch) {...@@ -15,6 +15,131 @@ const arch_bits = switch (native_arch) {
15 else => struct {},15 else => struct {},
16};16};
1717
18pub const EXC_TYPES_COUNT = arch_bits.EXC_TYPES_COUNT;
19pub const THREAD_STATE_NONE = arch_bits.THREAD_STATE_NONE;
20
21pub const EXC = enum(exception_type_t) {
22 NULL = 0,
23 /// Could not access memory
24 BAD_ACCESS = 1,
25 /// Instruction failed
26 BAD_INSTRUCTION = 2,
27 /// Arithmetic exception
28 ARITHMETIC = 3,
29 /// Emulation instruction
30 EMULATION = 4,
31 /// Software generated exception
32 SOFTWARE = 5,
33 /// Trace, breakpoint, etc.
34 BREAKPOINT = 6,
35 /// System calls.
36 SYSCALL = 7,
37 /// Mach system calls.
38 MACH_SYSCALL = 8,
39 /// RPC alert
40 RPC_ALERT = 9,
41 /// Abnormal process exit
42 CRASH = 10,
43 /// Hit resource consumption limit
44 RESOURCE = 11,
45 /// Violated guarded resource protections
46 GUARD = 12,
47 /// Abnormal process exited to corpse state
48 CORPSE_NOTIFY = 13,
49};
50
51pub const EXC_SOFT_SIGNAL = 0x10003;
52
53pub const EXC_MASK_BAD_ACCESS = 1 << @enumToInt(EXC.BAD_ACCESS);
54pub const EXC_MASK_BAD_INSTRUCTION = 1 << @enumToInt(EXC.BAD_INSTRUCTION);
55pub const EXC_MASK_ARITHMETIC = 1 << @enumToInt(EXC.ARITHMETIC);
56pub const EXC_MASK_EMULATION = 1 << @enumToInt(EXC.EMULATION);
57pub const EXC_MASK_SOFTWARE = 1 << @enumToInt(EXC.SOFTWARE);
58pub const EXC_MASK_BREAKPOINT = 1 << @enumToInt(EXC.BREAKPOINT);
59pub const EXC_MASK_SYSCALL = 1 << @enumToInt(EXC.SYSCALL);
60pub const EXC_MASK_MACH_SYSCALL = 1 << @enumToInt(EXC.MACH_SYSCALL);
61pub const EXC_MASK_RPC_ALERT = 1 << @enumToInt(EXC.RPC_ALERT);
62pub const EXC_MASK_CRASH = 1 << @enumToInt(EXC.CRASH);
63pub const EXC_MASK_RESOURCE = 1 << @enumToInt(EXC.RESOURCE);
64pub const EXC_MASK_GUARD = 1 << @enumToInt(EXC.GUARD);
65pub const EXC_MASK_CORPSE_NOTIFY = 1 << @enumToInt(EXC.CORPSE_NOTIFY);
66pub const EXC_MASK_MACHINE = arch_bits.EXC_MASK_MACHINE;
67
68pub const EXC_MASK_ALL = EXC_MASK_BAD_ACCESS |
69 EXC_MASK_BAD_INSTRUCTION |
70 EXC_MASK_ARITHMETIC |
71 EXC_MASK_EMULATION |
72 EXC_MASK_SOFTWARE |
73 EXC_MASK_BREAKPOINT |
74 EXC_MASK_SYSCALL |
75 EXC_MASK_MACH_SYSCALL |
76 EXC_MASK_RPC_ALERT |
77 EXC_MASK_RESOURCE |
78 EXC_MASK_GUARD |
79 EXC_MASK_MACHINE;
80
81/// Send a catch_exception_raise message including the identity.
82pub const EXCEPTION_DEFAULT = 1;
83/// Send a catch_exception_raise_state message including the
84/// thread state.
85pub const EXCEPTION_STATE = 2;
86/// Send a catch_exception_raise_state_identity message including
87/// the thread identity and state.
88pub const EXCEPTION_STATE_IDENTITY = 3;
89/// Send a catch_exception_raise_identity_protected message including protected task
90/// and thread identity.
91pub const EXCEPTION_IDENTITY_PROTECTED = 4;
92/// Prefer sending a catch_exception_raice_backtrace message, if applicable.
93pub const MACH_EXCEPTION_BACKTRACE_PREFERRED = 0x20000000;
94/// include additional exception specific errors, not used yet.
95pub const MACH_EXCEPTION_ERRORS = 0x40000000;
96/// Send 64-bit code and subcode in the exception header */
97pub const MACH_EXCEPTION_CODES = 0x80000000;
98
99pub const MACH_EXCEPTION_MASK = MACH_EXCEPTION_CODES |
100 MACH_EXCEPTION_ERRORS |
101 MACH_EXCEPTION_BACKTRACE_PREFERRED;
102
103pub const TASK_NULL: task_t = 0;
104pub const THREAD_NULL: thread_t = 0;
105pub const MACH_PORT_NULL: mach_port_t = 0;
106pub const MACH_MSG_TIMEOUT_NONE: mach_msg_timeout_t = 0;
107
108pub const MACH_MSG_OPTION_NONE = 0x00000000;
109
110pub const MACH_SEND_MSG = 0x00000001;
111pub const MACH_RCV_MSG = 0x00000002;
112
113pub const MACH_RCV_LARGE = 0x00000004;
114pub const MACH_RCV_LARGE_IDENTITY = 0x00000008;
115
116pub const MACH_SEND_TIMEOUT = 0x00000010;
117pub const MACH_SEND_OVERRIDE = 0x00000020;
118pub const MACH_SEND_INTERRUPT = 0x00000040;
119pub const MACH_SEND_NOTIFY = 0x00000080;
120pub const MACH_SEND_ALWAYS = 0x00010000;
121pub const MACH_SEND_FILTER_NONFATAL = 0x00010000;
122pub const MACH_SEND_TRAILER = 0x00020000;
123pub const MACH_SEND_NOIMPORTANCE = 0x00040000;
124pub const MACH_SEND_NODENAP = MACH_SEND_NOIMPORTANCE;
125pub const MACH_SEND_IMPORTANCE = 0x00080000;
126pub const MACH_SEND_SYNC_OVERRIDE = 0x00100000;
127pub const MACH_SEND_PROPAGATE_QOS = 0x00200000;
128pub const MACH_SEND_SYNC_USE_THRPRI = MACH_SEND_PROPAGATE_QOS;
129pub const MACH_SEND_KERNEL = 0x00400000;
130pub const MACH_SEND_SYNC_BOOTSTRAP_CHECKIN = 0x00800000;
131
132pub const MACH_RCV_TIMEOUT = 0x00000100;
133pub const MACH_RCV_NOTIFY = 0x00000000;
134pub const MACH_RCV_INTERRUPT = 0x00000400;
135pub const MACH_RCV_VOUCHER = 0x00000800;
136pub const MACH_RCV_OVERWRITE = 0x00000000;
137pub const MACH_RCV_GUARDED_DESC = 0x00001000;
138pub const MACH_RCV_SYNC_WAIT = 0x00004000;
139pub const MACH_RCV_SYNC_PEEK = 0x00008000;
140
141pub const MACH_MSG_STRICT_REPLY = 0x00000200;
142
18pub const ucontext_t = extern struct {143pub const ucontext_t = extern struct {
19 onstack: c_int,144 onstack: c_int,
20 sigmask: sigset_t,145 sigmask: sigset_t,
...@@ -155,6 +280,11 @@ pub extern "c" fn @"close$NOCANCEL"(fd: fd_t) c_int;...@@ -155,6 +280,11 @@ pub extern "c" fn @"close$NOCANCEL"(fd: fd_t) c_int;
155pub extern "c" fn mach_host_self() mach_port_t;280pub extern "c" fn mach_host_self() mach_port_t;
156pub extern "c" fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t;281pub extern "c" fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t;
157282
283pub const exception_type_t = c_int;
284pub const exception_data_type_t = integer_t;
285pub const exception_data_t = ?*mach_exception_data_type_t;
286pub const mach_exception_data_type_t = i64;
287pub const mach_exception_data_t = ?*mach_exception_data_type_t;
158pub const vm_map_t = mach_port_t;288pub const vm_map_t = mach_port_t;
159pub const vm_map_read_t = mach_port_t;289pub const vm_map_read_t = mach_port_t;
160pub const vm_region_flavor_t = c_int;290pub const vm_region_flavor_t = c_int;
...@@ -163,19 +293,122 @@ pub const vm_region_recurse_info_t = *c_int;...@@ -163,19 +293,122 @@ pub const vm_region_recurse_info_t = *c_int;
163pub const mach_vm_address_t = usize;293pub const mach_vm_address_t = usize;
164pub const vm_offset_t = usize;294pub const vm_offset_t = usize;
165pub const mach_vm_size_t = u64;295pub const mach_vm_size_t = u64;
296pub const mach_msg_bits_t = c_uint;
297pub const mach_msg_id_t = integer_t;
166pub const mach_msg_type_number_t = natural_t;298pub const mach_msg_type_number_t = natural_t;
299pub const mach_msg_type_name_t = c_uint;
300pub const mach_msg_option_t = integer_t;
301pub const mach_msg_size_t = natural_t;
302pub const mach_msg_timeout_t = natural_t;
303pub const mach_port_right_t = natural_t;
304pub const task_t = mach_port_t;
305pub const thread_port_t = task_t;
306pub const thread_t = thread_port_t;
307pub const exception_mask_t = c_uint;
308pub const exception_mask_array_t = [*]exception_mask_t;
309pub const exception_handler_t = mach_port_t;
310pub const exception_handler_array_t = [*]exception_handler_t;
311pub const exception_port_t = exception_handler_t;
312pub const exception_port_array_t = exception_handler_array_t;
313pub const exception_flavor_array_t = [*]thread_state_flavor_t;
314pub const exception_behavior_t = c_uint;
315pub const exception_behavior_array_t = [*]exception_behavior_t;
316pub const thread_state_flavor_t = c_int;
317pub const ipc_space_t = mach_port_t;
318pub const ipc_space_port_t = ipc_space_t;
319
320pub const MACH_PORT_RIGHT = enum(mach_port_right_t) {
321 SEND = 0,
322 RECEIVE = 1,
323 SEND_ONCE = 2,
324 PORT_SET = 3,
325 DEAD_NAME = 4,
326 /// Obsolete right
327 LABELH = 5,
328 /// Right not implemented
329 NUMBER = 6,
330};
331
332pub const MACH_MSG_TYPE = enum(mach_msg_type_name_t) {
333 /// Must hold receive right
334 MOVE_RECEIVE = 16,
335
336 /// Must hold send right(s)
337 MOVE_SEND = 17,
338
339 /// Must hold sendonce right
340 MOVE_SEND_ONCE = 18,
341
342 /// Must hold send right(s)
343 COPY_SEND = 19,
344
345 /// Must hold receive right
346 MAKE_SEND = 20,
347
348 /// Must hold receive right
349 MAKE_SEND_ONCE = 21,
350
351 /// NOT VALID
352 COPY_RECEIVE = 22,
353
354 /// Must hold receive right
355 DISPOSE_RECEIVE = 24,
356
357 /// Must hold send right(s)
358 DISPOSE_SEND = 25,
359
360 /// Must hold sendonce right
361 DISPOSE_SEND_ONCE = 26,
362};
167363
168extern "c" var mach_task_self_: mach_port_t;364extern "c" var mach_task_self_: mach_port_t;
169pub fn mach_task_self() callconv(.C) mach_port_t {365pub fn mach_task_self() callconv(.C) mach_port_t {
170 return mach_task_self_;366 return mach_task_self_;
171}367}
172368
369pub extern "c" fn mach_msg(
370 msg: ?*mach_msg_header_t,
371 option: mach_msg_option_t,
372 send_size: mach_msg_size_t,
373 rcv_size: mach_msg_size_t,
374 rcv_name: mach_port_name_t,
375 timeout: mach_msg_timeout_t,
376 notify: mach_port_name_t,
377) kern_return_t;
378
379pub const mach_msg_header_t = extern struct {
380 msgh_bits: mach_msg_bits_t,
381 msgh_size: mach_msg_size_t,
382 msgh_remote_port: mach_port_t,
383 msgh_local_port: mach_port_t,
384 msgh_voucher_port: mach_port_name_t,
385 msgh_id: mach_msg_id_t,
386};
387
388pub extern "c" fn task_get_exception_ports(
389 task: task_t,
390 exception_mask: exception_mask_t,
391 masks: exception_mask_array_t,
392 masks_cnt: *mach_msg_type_number_t,
393 old_handlers: exception_handler_array_t,
394 old_behaviors: exception_behavior_array_t,
395 old_flavors: exception_flavor_array_t,
396) kern_return_t;
397pub extern "c" fn task_set_exception_ports(
398 task: task_t,
399 exception_mask: exception_mask_t,
400 new_port: mach_port_t,
401 behavior: exception_behavior_t,
402 new_flavor: thread_state_flavor_t,
403) kern_return_t;
404
173pub const task_read_t = mach_port_t;405pub const task_read_t = mach_port_t;
174406
175pub extern "c" fn task_resume(target_task: task_read_t) kern_return_t;407pub extern "c" fn task_resume(target_task: task_read_t) kern_return_t;
176pub extern "c" fn task_suspend(target_task: task_read_t) kern_return_t;408pub extern "c" fn task_suspend(target_task: task_read_t) kern_return_t;
177409
178pub extern "c" fn task_for_pid(target_tport: mach_port_name_t, pid: pid_t, t: *mach_port_name_t) kern_return_t;410pub extern "c" fn task_for_pid(target_tport: mach_port_name_t, pid: pid_t, t: *mach_port_name_t) kern_return_t;
411pub extern "c" fn pid_for_task(target_tport: mach_port_name_t, pid: *pid_t) kern_return_t;
179pub extern "c" fn mach_vm_read(412pub extern "c" fn mach_vm_read(
180 target_task: vm_map_read_t,413 target_task: vm_map_read_t,
181 address: mach_vm_address_t,414 address: mach_vm_address_t,
...@@ -343,7 +576,7 @@ pub const vm_region_submap_short_info_64 = extern struct {...@@ -343,7 +576,7 @@ pub const vm_region_submap_short_info_64 = extern struct {
343576
344pub const thread_act_t = mach_port_t;577pub const thread_act_t = mach_port_t;
345pub const thread_state_t = *natural_t;578pub const thread_state_t = *natural_t;
346pub const mach_port_array_t = *mach_port_t;579pub const mach_port_array_t = [*]mach_port_t;
347580
348pub extern "c" fn task_threads(581pub extern "c" fn task_threads(
349 target_task: mach_port_t,582 target_task: mach_port_t,
...@@ -373,6 +606,9 @@ pub extern "c" fn thread_resume(thread: thread_act_t) kern_return_t;...@@ -373,6 +606,9 @@ pub extern "c" fn thread_resume(thread: thread_act_t) kern_return_t;
373pub const THREAD_BASIC_INFO = 3;606pub const THREAD_BASIC_INFO = 3;
374pub const THREAD_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(thread_basic_info) / @sizeOf(natural_t);607pub const THREAD_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(thread_basic_info) / @sizeOf(natural_t);
375608
609pub const THREAD_IDENTIFIER_INFO = 4;
610pub const THREAD_IDENTIFIER_INFO_COUNT: mach_msg_type_number_t = @sizeOf(thread_identifier_info) / @sizeOf(natural_t);
611
376pub const thread_flavor_t = natural_t;612pub const thread_flavor_t = natural_t;
377pub const thread_info_t = *integer_t;613pub const thread_info_t = *integer_t;
378pub const time_value_t = time_value;614pub const time_value_t = time_value;
...@@ -404,6 +640,17 @@ pub const thread_basic_info = extern struct {...@@ -404,6 +640,17 @@ pub const thread_basic_info = extern struct {
404 sleep_time: integer_t,640 sleep_time: integer_t,
405};641};
406642
643pub const thread_identifier_info = extern struct {
644 /// System-wide unique 64-bit thread id
645 thread_id: u64,
646
647 /// Handle to be used by libproc
648 thread_handle: u64,
649
650 /// libdispatch queue address
651 dispatch_qaddr: u64,
652};
653
407/// Cachability654/// Cachability
408pub const MATTR_CACHE = 1;655pub const MATTR_CACHE = 1;
409/// Migrability656/// Migrability
...@@ -506,7 +753,18 @@ pub extern "c" fn mach_vm_protect(...@@ -506,7 +753,18 @@ pub extern "c" fn mach_vm_protect(
506 new_protection: vm_prot_t,753 new_protection: vm_prot_t,
507) kern_return_t;754) kern_return_t;
508755
509pub extern "c" fn mach_port_deallocate(target_tport: mach_port_name_t, task: mach_port_name_t) kern_return_t;756pub extern "c" fn mach_port_allocate(
757 task: ipc_space_t,
758 right: mach_port_right_t,
759 name: *mach_port_name_t,
760) kern_return_t;
761pub extern "c" fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t;
762pub extern "c" fn mach_port_insert_right(
763 task: ipc_space_t,
764 name: mach_port_name_t,
765 poly: mach_port_t,
766 poly_poly: mach_msg_type_name_t,
767) kern_return_t;
510768
511pub extern "c" fn task_info(769pub extern "c" fn task_info(
512 target_task: task_name_t,770 target_task: task_name_t,
...@@ -514,6 +772,30 @@ pub extern "c" fn task_info(...@@ -514,6 +772,30 @@ pub extern "c" fn task_info(
514 task_info_out: task_info_t,772 task_info_out: task_info_t,
515 task_info_outCnt: *mach_msg_type_number_t,773 task_info_outCnt: *mach_msg_type_number_t,
516) kern_return_t;774) kern_return_t;
775
776pub const mach_task_basic_info = extern struct {
777 /// Virtual memory size (bytes)
778 virtual_size: mach_vm_size_t,
779
780 /// Resident memory size (bytes)
781 resident_size: mach_vm_size_t,
782
783 /// Total user run time for terminated threads
784 user_time: time_value_t,
785
786 /// Total system run time for terminated threads
787 system_time: time_value_t,
788
789 /// Default policy for new threads
790 policy: policy_t,
791
792 /// Suspend count for task
793 suspend_count: mach_vm_size_t,
794};
795
796pub const MACH_TASK_BASIC_INFO = 20;
797pub const MACH_TASK_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(mach_task_basic_info) / @sizeOf(natural_t);
798
517pub extern "c" fn _host_page_size(task: mach_port_t, size: *vm_size_t) kern_return_t;799pub extern "c" fn _host_page_size(task: mach_port_t, size: *vm_size_t) kern_return_t;
518pub extern "c" fn vm_deallocate(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) kern_return_t;800pub extern "c" fn vm_deallocate(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) kern_return_t;
519pub extern "c" fn vm_machine_attribute(801pub extern "c" fn vm_machine_attribute(
...@@ -1885,11 +2167,11 @@ pub const E = enum(u16) {...@@ -1885,11 +2167,11 @@ pub const E = enum(u16) {
1885};2167};
18862168
1887pub fn getKernError(err: kern_return_t) KernE {2169pub fn getKernError(err: kern_return_t) KernE {
1888 return @intToEnum(KernE, @truncate(u8, @intCast(usize, err)));2170 return @intToEnum(KernE, @truncate(u32, @intCast(usize, err)));
1889}2171}
18902172
1891/// Kernel return values2173/// Kernel return values
1892pub const KernE = enum(u8) {2174pub const KernE = enum(u32) {
1893 SUCCESS = 0,2175 SUCCESS = 0,
18942176
1895 /// Specified address is not currently valid2177 /// Specified address is not currently valid
...@@ -2108,6 +2390,104 @@ pub const KernE = enum(u8) {...@@ -2108,6 +2390,104 @@ pub const KernE = enum(u8) {
2108 _,2390 _,
2109};2391};
21102392
2393pub const mach_msg_return_t = kern_return_t;
2394
2395pub fn getMachMsgError(err: mach_msg_return_t) MachMsgE {
2396 return @intToEnum(MachMsgE, @truncate(u32, @intCast(usize, err)));
2397}
2398
2399/// All special error code bits defined below.
2400pub const MACH_MSG_MASK: u32 = 0x3e00;
2401/// No room in IPC name space for another capability name.
2402pub const MACH_MSG_IPC_SPACE: u32 = 0x2000;
2403/// No room in VM address space for out-of-line memory.
2404pub const MACH_MSG_VM_SPACE: u32 = 0x1000;
2405/// Kernel resource shortage handling out-of-line memory.
2406pub const MACH_MSG_IPC_KERNEL: u32 = 0x800;
2407/// Kernel resource shortage handling an IPC capability.
2408pub const MACH_MSG_VM_KERNEL: u32 = 0x400;
2409
2410/// Mach msg return values
2411pub const MachMsgE = enum(u32) {
2412 SUCCESS = 0x00000000,
2413
2414 /// Thread is waiting to send. (Internal use only.)
2415 SEND_IN_PROGRESS = 0x10000001,
2416 /// Bogus in-line data.
2417 SEND_INVALID_DATA = 0x10000002,
2418 /// Bogus destination port.
2419 SEND_INVALID_DEST = 0x10000003,
2420 /// Message not sent before timeout expired.
2421 SEND_TIMED_OUT = 0x10000004,
2422 /// Bogus voucher port.
2423 SEND_INVALID_VOUCHER = 0x10000005,
2424 /// Software interrupt.
2425 SEND_INTERRUPTED = 0x10000007,
2426 /// Data doesn't contain a complete message.
2427 SEND_MSG_TOO_SMALL = 0x10000008,
2428 /// Bogus reply port.
2429 SEND_INVALID_REPLY = 0x10000009,
2430 /// Bogus port rights in the message body.
2431 SEND_INVALID_RIGHT = 0x1000000a,
2432 /// Bogus notify port argument.
2433 SEND_INVALID_NOTIFY = 0x1000000b,
2434 /// Invalid out-of-line memory pointer.
2435 SEND_INVALID_MEMORY = 0x1000000c,
2436 /// No message buffer is available.
2437 SEND_NO_BUFFER = 0x1000000d,
2438 /// Send is too large for port
2439 SEND_TOO_LARGE = 0x1000000e,
2440 /// Invalid msg-type specification.
2441 SEND_INVALID_TYPE = 0x1000000f,
2442 /// A field in the header had a bad value.
2443 SEND_INVALID_HEADER = 0x10000010,
2444 /// The trailer to be sent does not match kernel format.
2445 SEND_INVALID_TRAILER = 0x10000011,
2446 /// The sending thread context did not match the context on the dest port
2447 SEND_INVALID_CONTEXT = 0x10000012,
2448 /// compatibility: no longer a returned error
2449 SEND_INVALID_RT_OOL_SIZE = 0x10000015,
2450 /// The destination port doesn't accept ports in body
2451 SEND_NO_GRANT_DEST = 0x10000016,
2452 /// Message send was rejected by message filter
2453 SEND_MSG_FILTERED = 0x10000017,
2454
2455 /// Thread is waiting for receive. (Internal use only.)
2456 RCV_IN_PROGRESS = 0x10004001,
2457 /// Bogus name for receive port/port-set.
2458 RCV_INVALID_NAME = 0x10004002,
2459 /// Didn't get a message within the timeout value.
2460 RCV_TIMED_OUT = 0x10004003,
2461 /// Message buffer is not large enough for inline data.
2462 RCV_TOO_LARGE = 0x10004004,
2463 /// Software interrupt.
2464 RCV_INTERRUPTED = 0x10004005,
2465 /// compatibility: no longer a returned error
2466 RCV_PORT_CHANGED = 0x10004006,
2467 /// Bogus notify port argument.
2468 RCV_INVALID_NOTIFY = 0x10004007,
2469 /// Bogus message buffer for inline data.
2470 RCV_INVALID_DATA = 0x10004008,
2471 /// Port/set was sent away/died during receive.
2472 RCV_PORT_DIED = 0x10004009,
2473 /// compatibility: no longer a returned error
2474 RCV_IN_SET = 0x1000400a,
2475 /// Error receiving message header. See special bits.
2476 RCV_HEADER_ERROR = 0x1000400b,
2477 /// Error receiving message body. See special bits.
2478 RCV_BODY_ERROR = 0x1000400c,
2479 /// Invalid msg-type specification in scatter list.
2480 RCV_INVALID_TYPE = 0x1000400d,
2481 /// Out-of-line overwrite region is not large enough
2482 RCV_SCATTER_SMALL = 0x1000400e,
2483 /// trailer type or number of trailer elements not supported
2484 RCV_INVALID_TRAILER = 0x1000400f,
2485 /// Waiting for receive with timeout. (Internal use only.)
2486 RCV_IN_PROGRESS_TIMED = 0x10004011,
2487 /// invalid reply port used in a STRICT_REPLY message
2488 RCV_INVALID_REPLY = 0x10004012,
2489};
2490
2111pub const SIGSTKSZ = 131072;2491pub const SIGSTKSZ = 131072;
2112pub const MINSIGSTKSZ = 32768;2492pub const MINSIGSTKSZ = 32768;
21132493
...@@ -2677,11 +3057,20 @@ pub const _POSIX_SPAWN_RESLIDE = 0x0800;...@@ -2677,11 +3057,20 @@ pub const _POSIX_SPAWN_RESLIDE = 0x0800;
2677pub const POSIX_SPAWN_CLOEXEC_DEFAULT = 0x4000;3057pub const POSIX_SPAWN_CLOEXEC_DEFAULT = 0x4000;
26783058
2679pub const PT_TRACE_ME = 0;3059pub const PT_TRACE_ME = 0;
3060pub const PT_READ_I = 1;
3061pub const PT_READ_D = 2;
3062pub const PT_READ_U = 3;
3063pub const PT_WRITE_I = 4;
3064pub const PT_WRITE_D = 5;
3065pub const PT_WRITE_U = 6;
2680pub const PT_CONTINUE = 7;3066pub const PT_CONTINUE = 7;
2681pub const PT_KILL = 8;3067pub const PT_KILL = 8;
2682pub const PT_STEP = 9;3068pub const PT_STEP = 9;
2683pub const PT_DETACH = 11;3069pub const PT_DETACH = 11;
3070pub const PT_SIGEXC = 12;
3071pub const PT_THUPDATE = 13;
2684pub const PT_ATTACHEXC = 14;3072pub const PT_ATTACHEXC = 14;
3073pub const PT_FORCEQUOTA = 30;
2685pub const PT_DENY_ATTACH = 31;3074pub const PT_DENY_ATTACH = 31;
26863075
2687pub const caddr_t = ?[*]u8;3076pub const caddr_t = ?[*]u8;
lib/std/c/darwin/aarch64.zig+20
...@@ -16,3 +16,23 @@ pub const thread_state = extern struct {...@@ -16,3 +16,23 @@ pub const thread_state = extern struct {
16 cpsr: u32, // Current program status register16 cpsr: u32, // Current program status register
17 __pad: u32,17 __pad: u32,
18};18};
19
20pub const EXC_TYPES_COUNT = 14;
21pub const EXC_MASK_MACHINE = 0;
22
23pub const ARM_THREAD_STATE = 1;
24pub const ARM_UNIFIED_THREAD_STATE = ARM_THREAD_STATE;
25pub const ARM_VFP_STATE = 2;
26pub const ARM_EXCEPTION_STATE = 3;
27pub const ARM_DEBUG_STATE = 4;
28pub const THREAD_STATE_NONE = 5;
29pub const ARM_THREAD_STATE64 = 6;
30pub const ARM_EXCEPTION_STATE64 = 7;
31pub const ARM_THREAD_STATE_LAST = 8;
32pub const ARM_THREAD_STATE32 = 9;
33pub const ARM_DEBUG_STATE32 = 14;
34pub const ARM_DEBUG_STATE64 = 15;
35pub const ARM_NEON_STATE = 16;
36pub const ARM_NEON_STATE64 = 17;
37pub const ARM_CPMU_STATE64 = 18;
38pub const ARM_PAGEIN_STATE = 27;
lib/std/c/darwin/x86_64.zig+27
...@@ -33,3 +33,30 @@ pub const thread_state = extern struct {...@@ -33,3 +33,30 @@ pub const thread_state = extern struct {
3333
34pub const THREAD_STATE = 4;34pub const THREAD_STATE = 4;
35pub const THREAD_STATE_COUNT: c.mach_msg_type_number_t = @sizeOf(thread_state) / @sizeOf(c_int);35pub const THREAD_STATE_COUNT: c.mach_msg_type_number_t = @sizeOf(thread_state) / @sizeOf(c_int);
36
37pub const EXC_TYPES_COUNT = 14;
38pub const EXC_MASK_MACHINE = 0;
39
40pub const x86_THREAD_STATE32 = 1;
41pub const x86_FLOAT_STATE32 = 2;
42pub const x86_EXCEPTION_STATE32 = 3;
43pub const x86_THREAD_STATE64 = 4;
44pub const x86_FLOAT_STATE64 = 5;
45pub const x86_EXCEPTION_STATE64 = 6;
46pub const x86_THREAD_STATE = 7;
47pub const x86_FLOAT_STATE = 8;
48pub const x86_EXCEPTION_STATE = 9;
49pub const x86_DEBUG_STATE32 = 10;
50pub const x86_DEBUG_STATE64 = 11;
51pub const x86_DEBUG_STATE = 12;
52pub const THREAD_STATE_NONE = 13;
53pub const x86_AVX_STATE32 = 16;
54pub const x86_AVX_STATE64 = (x86_AVX_STATE32 + 1);
55pub const x86_AVX_STATE = (x86_AVX_STATE32 + 2);
56pub const x86_AVX512_STATE32 = 19;
57pub const x86_AVX512_STATE64 = (x86_AVX512_STATE32 + 1);
58pub const x86_AVX512_STATE = (x86_AVX512_STATE32 + 2);
59pub const x86_PAGEIN_STATE = 22;
60pub const x86_THREAD_FULL_STATE64 = 23;
61pub const x86_INSTRUCTION_STATE = 24;
62pub const x86_LAST_BRANCH_STATE = 25;
lib/std/child_process.zig+6
...@@ -60,6 +60,9 @@ pub const ChildProcess = struct {...@@ -60,6 +60,9 @@ pub const ChildProcess = struct {
60 /// Darwin-only. Disable ASLR for the child process.60 /// Darwin-only. Disable ASLR for the child process.
61 disable_aslr: bool = false,61 disable_aslr: bool = false,
6262
63 /// Darwin-only. Start child process in suspended state as if SIGSTOP was sent.
64 start_suspended: bool = false,
65
63 pub const Arg0Expand = os.Arg0Expand;66 pub const Arg0Expand = os.Arg0Expand;
6467
65 pub const SpawnError = error{68 pub const SpawnError = error{
...@@ -578,6 +581,9 @@ pub const ChildProcess = struct {...@@ -578,6 +581,9 @@ pub const ChildProcess = struct {
578 if (self.disable_aslr) {581 if (self.disable_aslr) {
579 flags |= os.darwin._POSIX_SPAWN_DISABLE_ASLR;582 flags |= os.darwin._POSIX_SPAWN_DISABLE_ASLR;
580 }583 }
584 if (self.start_suspended) {
585 flags |= os.darwin.POSIX_SPAWN_START_SUSPENDED;
586 }
581 try attr.set(flags);587 try attr.set(flags);
582588
583 var actions = try os.posix_spawn.Actions.init();589 var actions = try os.posix_spawn.Actions.init();
lib/std/os.zig+1
...@@ -42,6 +42,7 @@ pub const uefi = @import("os/uefi.zig");...@@ -42,6 +42,7 @@ pub const uefi = @import("os/uefi.zig");
42pub const wasi = @import("os/wasi.zig");42pub const wasi = @import("os/wasi.zig");
43pub const windows = @import("os/windows.zig");43pub const windows = @import("os/windows.zig");
44pub const posix_spawn = @import("os/posix_spawn.zig");44pub const posix_spawn = @import("os/posix_spawn.zig");
45pub const ptrace = @import("os/ptrace.zig");
4546
46comptime {47comptime {
47 assert(@import("std") == std); // std lib tests require --zig-lib-dir48 assert(@import("std") == std); // std lib tests require --zig-lib-dir
lib/std/os/darwin.zig+215-2
...@@ -17,11 +17,120 @@ const mach_task = if (builtin.target.isDarwin()) struct {...@@ -17,11 +17,120 @@ const mach_task = if (builtin.target.isDarwin()) struct {
17 Unexpected,17 Unexpected,
18 };18 };
1919
20 pub const MachTask = struct {20 pub const MachTask = extern struct {
21 port: std.c.mach_port_name_t,21 port: std.c.mach_port_name_t,
2222
23 pub fn isValid(self: MachTask) bool {23 pub fn isValid(self: MachTask) bool {
24 return self.port != 0;24 return self.port != std.c.TASK_NULL;
25 }
26
27 pub fn pidForTask(self: MachTask) MachError!std.os.pid_t {
28 var pid: std.os.pid_t = undefined;
29 switch (std.c.getKernError(std.c.pid_for_task(self.port, &pid))) {
30 .SUCCESS => return pid,
31 .FAILURE => return error.PermissionDenied,
32 else => |err| {
33 log.err("pid_for_task kernel call failed with error code: {s}", .{@tagName(err)});
34 return error.Unexpected;
35 },
36 }
37 }
38
39 pub fn allocatePort(self: MachTask, right: std.c.MACH_PORT_RIGHT) MachError!MachTask {
40 var out_port: std.c.mach_port_name_t = undefined;
41 switch (std.c.getKernError(std.c.mach_port_allocate(
42 self.port,
43 @enumToInt(right),
44 &out_port,
45 ))) {
46 .SUCCESS => return .{ .port = out_port },
47 .FAILURE => return error.PermissionDenied,
48 else => |err| {
49 log.err("mach_task_allocate kernel call failed with error code: {s}", .{@tagName(err)});
50 return error.Unexpected;
51 },
52 }
53 }
54
55 pub fn deallocatePort(self: MachTask, port: MachTask) void {
56 _ = std.c.getKernError(std.c.mach_port_deallocate(self.port, port.port));
57 }
58
59 pub fn insertRight(self: MachTask, port: MachTask, msg: std.c.MACH_MSG_TYPE) !void {
60 switch (std.c.getKernError(std.c.mach_port_insert_right(
61 self.port,
62 port.port,
63 port.port,
64 @enumToInt(msg),
65 ))) {
66 .SUCCESS => return,
67 .FAILURE => return error.PermissionDenied,
68 else => |err| {
69 log.err("mach_port_insert_right kernel call failed with error code: {s}", .{@tagName(err)});
70 return error.Unexpected;
71 },
72 }
73 }
74
75 pub const PortInfo = struct {
76 mask: std.c.exception_mask_t,
77 masks: [std.c.EXC_TYPES_COUNT]std.c.exception_mask_t,
78 ports: [std.c.EXC_TYPES_COUNT]std.c.mach_port_t,
79 behaviors: [std.c.EXC_TYPES_COUNT]std.c.exception_behavior_t,
80 flavors: [std.c.EXC_TYPES_COUNT]std.c.thread_state_flavor_t,
81 count: std.c.mach_msg_type_number_t,
82 };
83
84 pub fn getExceptionPorts(self: MachTask, mask: std.c.exception_mask_t) !PortInfo {
85 var info = PortInfo{
86 .mask = mask,
87 .masks = undefined,
88 .ports = undefined,
89 .behaviors = undefined,
90 .flavors = undefined,
91 .count = 0,
92 };
93 info.count = info.ports.len / @sizeOf(std.c.mach_port_t);
94
95 switch (std.c.getKernError(std.c.task_get_exception_ports(
96 self.port,
97 info.mask,
98 &info.masks,
99 &info.count,
100 &info.ports,
101 &info.behaviors,
102 &info.flavors,
103 ))) {
104 .SUCCESS => return info,
105 .FAILURE => return error.PermissionDenied,
106 else => |err| {
107 log.err("task_get_exception_ports kernel call failed with error code: {s}", .{@tagName(err)});
108 return error.Unexpected;
109 },
110 }
111 }
112
113 pub fn setExceptionPorts(
114 self: MachTask,
115 mask: std.c.exception_mask_t,
116 new_port: MachTask,
117 behavior: std.c.exception_behavior_t,
118 new_flavor: std.c.thread_state_flavor_t,
119 ) !void {
120 switch (std.c.getKernError(std.c.task_set_exception_ports(
121 self.port,
122 mask,
123 new_port.port,
124 behavior,
125 new_flavor,
126 ))) {
127 .SUCCESS => return,
128 .FAILURE => return error.PermissionDenied,
129 else => |err| {
130 log.err("task_set_exception_ports kernel call failed with error code: {s}", .{@tagName(err)});
131 return error.Unexpected;
132 },
133 }
25 }134 }
26135
27 pub const RegionInfo = struct {136 pub const RegionInfo = struct {
...@@ -304,6 +413,110 @@ const mach_task = if (builtin.target.isDarwin()) struct {...@@ -304,6 +413,110 @@ const mach_task = if (builtin.target.isDarwin()) struct {
304 },413 },
305 }414 }
306 }415 }
416
417 pub fn basicTaskInfo(task: MachTask) MachError!std.c.mach_task_basic_info {
418 var info: std.c.mach_task_basic_info = undefined;
419 var count = std.c.MACH_TASK_BASIC_INFO_COUNT;
420 switch (std.c.getKernError(std.c.task_info(
421 task.port,
422 std.c.MACH_TASK_BASIC_INFO,
423 @ptrCast(std.c.task_info_t, &info),
424 &count,
425 ))) {
426 .SUCCESS => return info,
427 else => |err| {
428 log.err("task_info kernel call failed with error code: {s}", .{@tagName(err)});
429 return error.Unexpected;
430 },
431 }
432 }
433
434 pub fn @"resume"(task: MachTask) MachError!void {
435 switch (std.c.getKernError(std.c.task_resume(task.port))) {
436 .SUCCESS => {},
437 else => |err| {
438 log.err("task_resume kernel call failed with error code: {s}", .{@tagName(err)});
439 return error.Unexpected;
440 },
441 }
442 }
443
444 pub fn @"suspend"(task: MachTask) MachError!void {
445 switch (std.c.getKernError(std.c.task_suspend(task.port))) {
446 .SUCCESS => {},
447 else => |err| {
448 log.err("task_suspend kernel call failed with error code: {s}", .{@tagName(err)});
449 return error.Unexpected;
450 },
451 }
452 }
453
454 const ThreadList = struct {
455 buf: []MachThread,
456
457 pub fn deinit(list: ThreadList) void {
458 const self_task = machTaskForSelf();
459 _ = std.c.vm_deallocate(
460 self_task.port,
461 @ptrToInt(list.buf.ptr),
462 @intCast(std.c.vm_size_t, list.buf.len * @sizeOf(std.c.mach_port_t)),
463 );
464 }
465 };
466
467 pub fn getThreads(task: MachTask) MachError!ThreadList {
468 var thread_list: std.c.mach_port_array_t = undefined;
469 var thread_count: std.c.mach_msg_type_number_t = undefined;
470 switch (std.c.getKernError(std.c.task_threads(task.port, &thread_list, &thread_count))) {
471 .SUCCESS => return ThreadList{ .buf = @ptrCast([*]MachThread, thread_list)[0..thread_count] },
472 else => |err| {
473 log.err("task_threads kernel call failed with error code: {s}", .{@tagName(err)});
474 return error.Unexpected;
475 },
476 }
477 }
478 };
479
480 pub const MachThread = extern struct {
481 port: std.c.mach_port_t,
482
483 pub fn isValid(thread: MachThread) bool {
484 return thread.port != std.c.THREAD_NULL;
485 }
486
487 pub fn getBasicInfo(thread: MachThread) MachError!std.c.thread_basic_info {
488 var info: std.c.thread_basic_info = undefined;
489 var count = std.c.THREAD_BASIC_INFO_COUNT;
490 switch (std.c.getKernError(std.c.thread_info(
491 thread.port,
492 std.c.THREAD_BASIC_INFO,
493 @ptrCast(std.c.thread_info_t, &info),
494 &count,
495 ))) {
496 .SUCCESS => return info,
497 else => |err| {
498 log.err("thread_info kernel call failed with error code: {s}", .{@tagName(err)});
499 return error.Unexpected;
500 },
501 }
502 }
503
504 pub fn getIdentifierInfo(thread: MachThread) MachError!std.c.thread_identifier_info {
505 var info: std.c.thread_identifier_info = undefined;
506 var count = std.c.THREAD_IDENTIFIER_INFO_COUNT;
507 switch (std.c.getKernError(std.c.thread_info(
508 thread.port,
509 std.c.THREAD_IDENTIFIER_INFO,
510 @ptrCast(std.c.thread_info_t, &info),
511 &count,
512 ))) {
513 .SUCCESS => return info,
514 else => |err| {
515 log.err("thread_info kernel call failed with error code: {s}", .{@tagName(err)});
516 return error.Unexpected;
517 },
518 }
519 }
307 };520 };
308521
309 pub fn machTaskForPid(pid: std.os.pid_t) MachError!MachTask {522 pub fn machTaskForPid(pid: std.os.pid_t) MachError!MachTask {
lib/std/os/ptrace.zig created+28
...@@ -0,0 +1,28 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4const os = @import("../os.zig");
5const system = os.system;
6const errno = system.getErrno;
7const pid_t = system.pid_t;
8const unexpectedErrno = os.unexpectedErrno;
9const UnexpectedError = os.UnexpectedError;
10
11pub usingnamespace ptrace;
12
13const ptrace = if (builtin.target.isDarwin()) struct {
14 pub const PtraceError = error{
15 ProcessNotFound,
16 PermissionDenied,
17 } || UnexpectedError;
18
19 pub fn ptrace(request: i32, pid: pid_t, addr: ?[*]u8, signal: i32) PtraceError!void {
20 switch (errno(system.ptrace(request, pid, addr, signal))) {
21 .SUCCESS => return,
22 .SRCH => return error.ProcessNotFound,
23 .INVAL => unreachable,
24 .BUSY, .PERM => return error.PermissionDenied,
25 else => |err| return unexpectedErrno(err),
26 }
27 }
28} else struct {};