authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-12 00:13:37+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-12 00:13:37+01:00
log612b9f4da1a682eeb4947e473199c5231ae10be0
tree3d15eb3231a4b75ac74842aeca7e33c19ccb64d2
parent402dfb5fd3272fafd5d13a3065e44ad6b0b28a8b

darwin: add defs and funcs for Mach exception handling


4 files changed, 216 insertions(+), 0 deletions(-)

lib/std/c/darwin.zig+108
...@@ -15,6 +15,86 @@ const arch_bits = switch (native_arch) {...@@ -15,6 +15,86 @@ 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
21/// Could not access memory
22pub const EXC_BAD_ACCESS = 1;
23/// Instruction failed
24pub const EXC_BAD_INSTRUCTION = 2;
25/// Arithmetic exception
26pub const EXC_ARITHMETIC = 3;
27/// Emulation instruction
28pub const EXC_EMULATION = 4;
29/// Software generated exception
30pub const EXC_SOFTWARE = 5;
31/// Trace, breakpoint, etc.
32pub const EXC_BREAKPOINT = 6;
33/// System calls.
34pub const EXC_SYSCALL = 7;
35/// Mach system calls.
36pub const EXC_MACH_SYSCALL = 8;
37/// RPC alert
38pub const EXC_RPC_ALERT = 9;
39/// Abnormal process exit
40pub const EXC_CRASH = 10;
41/// Hit resource consumption limit
42pub const EXC_RESOURCE = 11;
43/// Violated guarded resource protections
44pub const EXC_GUARD = 12;
45/// Abnormal process exited to corpse state
46pub const EXC_CORPSE_NOTIFY = 13;
47
48pub const EXC_MASK_BAD_ACCESS = 1 << EXC_BAD_ACCESS;
49pub const EXC_MASK_BAD_INSTRUCTION = 1 << EXC_BAD_INSTRUCTION;
50pub const EXC_MASK_ARITHMETIC = 1 << EXC_ARITHMETIC;
51pub const EXC_MASK_EMULATION = 1 << EXC_EMULATION;
52pub const EXC_MASK_SOFTWARE = 1 << EXC_SOFTWARE;
53pub const EXC_MASK_BREAKPOINT = 1 << EXC_BREAKPOINT;
54pub const EXC_MASK_SYSCALL = 1 << EXC_SYSCALL;
55pub const EXC_MASK_MACH_SYSCALL = 1 << EXC_MACH_SYSCALL;
56pub const EXC_MASK_RPC_ALERT = 1 << EXC_RPC_ALERT;
57pub const EXC_MASK_CRASH = 1 << EXC_CRASH;
58pub const EXC_MASK_RESOURCE = 1 << EXC_RESOURCE;
59pub const EXC_MASK_GUARD = 1 << EXC_GUARD;
60pub const EXC_MASK_CORPSE_NOTIFY = 1 << EXC_CORPSE_NOTIFY;
61pub const EXC_MASK_MACHINE = arch_bits.EXC_MASK_MACHINE;
62
63pub const EXC_MASK_ALL = EXC_MASK_BAD_ACCESS |
64 EXC_MASK_BAD_INSTRUCTION |
65 EXC_MASK_ARITHMETIC |
66 EXC_MASK_EMULATION |
67 EXC_MASK_SOFTWARE |
68 EXC_MASK_BREAKPOINT |
69 EXC_MASK_SYSCALL |
70 EXC_MASK_MACH_SYSCALL |
71 EXC_MASK_RPC_ALERT |
72 EXC_MASK_RESOURCE |
73 EXC_MASK_GUARD |
74 EXC_MASK_MACHINE;
75
76/// Send a catch_exception_raise message including the identity.
77pub const EXCEPTION_DEFAULT = 1;
78/// Send a catch_exception_raise_state message including the
79/// thread state.
80pub const EXCEPTION_STATE = 2;
81/// Send a catch_exception_raise_state_identity message including
82/// the thread identity and state.
83pub const EXCEPTION_STATE_IDENTITY = 3;
84/// Send a catch_exception_raise_identity_protected message including protected task
85/// and thread identity.
86pub const EXCEPTION_IDENTITY_PROTECTED = 4;
87/// Prefer sending a catch_exception_raice_backtrace message, if applicable.
88pub const MACH_EXCEPTION_BACKTRACE_PREFERRED = 0x20000000;
89/// include additional exception specific errors, not used yet.
90pub const MACH_EXCEPTION_ERRORS = 0x40000000;
91/// Send 64-bit code and subcode in the exception header */
92pub const MACH_EXCEPTION_CODES = 0x80000000;
93
94pub const MACH_EXCEPTION_MASK = MACH_EXCEPTION_CODES |
95 MACH_EXCEPTION_ERRORS |
96 MACH_EXCEPTION_BACKTRACE_PREFERRED;
97
18pub const ucontext_t = extern struct {98pub const ucontext_t = extern struct {
19 onstack: c_int,99 onstack: c_int,
20 sigmask: sigset_t,100 sigmask: sigset_t,
...@@ -166,6 +246,17 @@ pub const mach_vm_size_t = u64;...@@ -166,6 +246,17 @@ pub const mach_vm_size_t = u64;
166pub const mach_msg_type_number_t = natural_t;246pub const mach_msg_type_number_t = natural_t;
167pub const mach_msg_type_name_t = u32;247pub const mach_msg_type_name_t = u32;
168pub const mach_port_right_t = natural_t;248pub const mach_port_right_t = natural_t;
249pub const task_t = mach_port_t;
250pub const exception_mask_t = u32;
251pub const exception_mask_array_t = [*]exception_mask_t;
252pub const exception_handler_t = mach_port_t;
253pub const exception_handler_array_t = [*]exception_handler_t;
254pub const exception_port_t = exception_handler_t;
255pub const exception_port_array_t = exception_handler_array_t;
256pub const exception_flavor_array_t = [*]thread_state_flavor_t;
257pub const exception_behavior_t = i32;
258pub const exception_behavior_array_t = [*]exception_behavior_t;
259pub const thread_state_flavor_t = i32;
169pub const ipc_space_t = mach_port_t;260pub const ipc_space_t = mach_port_t;
170pub const ipc_space_port_t = ipc_space_t;261pub const ipc_space_port_t = ipc_space_t;
171262
...@@ -218,6 +309,23 @@ pub fn mach_task_self() callconv(.C) mach_port_t {...@@ -218,6 +309,23 @@ pub fn mach_task_self() callconv(.C) mach_port_t {
218 return mach_task_self_;309 return mach_task_self_;
219}310}
220311
312pub extern "c" fn task_get_exception_ports(
313 task: task_t,
314 exception_mask: exception_mask_t,
315 masks: exception_mask_array_t,
316 masks_cnt: *mach_msg_type_number_t,
317 old_handlers: exception_handler_array_t,
318 old_behaviors: exception_behavior_array_t,
319 old_flavors: exception_flavor_array_t,
320) kern_return_t;
321pub extern "c" fn task_set_exception_ports(
322 task: task_t,
323 exception_mask: exception_mask_t,
324 new_port: mach_port_t,
325 behavior: exception_behavior_t,
326 new_flavor: thread_state_flavor_t,
327) kern_return_t;
328
221pub const task_read_t = mach_port_t;329pub const task_read_t = mach_port_t;
222330
223pub extern "c" fn task_resume(target_task: task_read_t) kern_return_t;331pub extern "c" fn task_resume(target_task: task_read_t) kern_return_t;
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/os/darwin.zig+61
...@@ -60,6 +60,67 @@ const mach_task = if (builtin.target.isDarwin()) struct {...@@ -60,6 +60,67 @@ const mach_task = if (builtin.target.isDarwin()) struct {
60 }60 }
61 }61 }
6262
63 pub const PortInfo = struct {
64 mask: std.c.exception_mask_t,
65 masks: [std.c.EXC_TYPES_COUNT]std.c.exception_mask_t,
66 ports: [std.c.EXC_TYPES_COUNT]std.c.mach_port_t,
67 behaviors: [std.c.EXC_TYPES_COUNT]std.c.exception_behavior_t,
68 flavors: [std.c.EXC_TYPES_COUNT]std.c.thread_state_flavor_t,
69 count: std.c.mach_msg_type_number_t,
70 };
71
72 pub fn getExceptionPorts(self: MachTask, mask: std.c.exception_mask_t) !PortInfo {
73 var info = PortInfo{
74 .mask = mask,
75 .masks = undefined,
76 .ports = undefined,
77 .behaviors = undefined,
78 .flavors = undefined,
79 .count = 0,
80 };
81 info.count = info.ports.len / @sizeOf(std.c.mach_port_t);
82
83 switch (std.c.getKernError(std.c.task_get_exception_ports(
84 self.port,
85 info.mask,
86 &info.masks,
87 &info.count,
88 &info.ports,
89 &info.behaviors,
90 &info.flavors,
91 ))) {
92 .SUCCESS => return info,
93 .FAILURE => return error.PermissionDenied,
94 else => |err| {
95 log.err("task_get_exception_ports kernel call failed with error code: {s}", .{@tagName(err)});
96 return error.Unexpected;
97 },
98 }
99 }
100
101 pub fn setExceptionPorts(
102 self: MachTask,
103 mask: std.c.exception_mask_t,
104 new_port: MachTask,
105 behavior: std.c.exception_behavior_t,
106 new_flavor: std.c.thread_state_flavor_t,
107 ) !void {
108 switch (std.c.getKernError(std.c.task_set_exception_ports(
109 self.port,
110 mask,
111 new_port.port,
112 behavior,
113 new_flavor,
114 ))) {
115 .SUCCESS => return,
116 .FAILURE => return error.PermissionDenied,
117 else => |err| {
118 log.err("task_set_exception_ports kernel call failed with error code: {s}", .{@tagName(err)});
119 return error.Unexpected;
120 },
121 }
122 }
123
63 pub const RegionInfo = struct {124 pub const RegionInfo = struct {
64 pub const Tag = enum {125 pub const Tag = enum {
65 basic,126 basic,