authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-17 10:41:51+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-17 10:42:11+01:00
log648afbc839c8f367f42affd8a6ce8dce8e70a795
tree78db1f2d729db1ec2d1be85149e842417e9935c6
parent3c3826bf93f7cbd88ecc30b43afac12cde313ffa

macos: update Mach routines for accessing page info


2 files changed, 201 insertions(+), 16 deletions(-)

lib/std/c/darwin.zig+87-8
...@@ -155,6 +155,7 @@ pub const vm_map_t = mach_port_t;...@@ -155,6 +155,7 @@ pub const vm_map_t = mach_port_t;
155pub const vm_map_read_t = mach_port_t;155pub const vm_map_read_t = mach_port_t;
156pub const vm_region_flavor_t = c_int;156pub const vm_region_flavor_t = c_int;
157pub const vm_region_info_t = *c_int;157pub const vm_region_info_t = *c_int;
158pub const vm_region_recurse_info_t = *c_int;
158pub const mach_vm_address_t = usize;159pub const mach_vm_address_t = usize;
159pub const vm_offset_t = usize;160pub const vm_offset_t = usize;
160pub const mach_vm_size_t = u64;161pub const mach_vm_size_t = u64;
...@@ -193,13 +194,20 @@ pub extern "c" fn mach_vm_region(...@@ -193,13 +194,20 @@ pub extern "c" fn mach_vm_region(
193 info_cnt: *mach_msg_type_number_t,194 info_cnt: *mach_msg_type_number_t,
194 object_name: *mach_port_t,195 object_name: *mach_port_t,
195) kern_return_t;196) kern_return_t;
196197pub extern "c" fn mach_vm_region_recurse(
197pub const VM_REGION_BASIC_INFO_64 = 9;198 target_task: vm_map_t,
198pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_info_64) / @sizeOf(natural_t);199 address: *mach_vm_address_t,
200 size: *mach_vm_size_t,
201 nesting_depth: *natural_t,
202 info: vm_region_recurse_info_t,
203 info_cnt: *mach_msg_type_number_t,
204) kern_return_t;
199205
200pub const vm_inherit_t = u32;206pub const vm_inherit_t = u32;
201pub const memory_object_offset_t = u64;207pub const memory_object_offset_t = u64;
202pub const vm_behavior_t = i32;208pub const vm_behavior_t = i32;
209pub const vm32_object_id_t = u32;
210pub const vm_object_id_t = u64;
203211
204pub const VM_INHERIT_SHARE: vm_inherit_t = 0;212pub const VM_INHERIT_SHARE: vm_inherit_t = 0;
205pub const VM_INHERIT_COPY: vm_inherit_t = 1;213pub const VM_INHERIT_COPY: vm_inherit_t = 1;
...@@ -221,8 +229,47 @@ pub const VM_BEHAVIOR_REUSE: vm_behavior_t = 9;...@@ -221,8 +229,47 @@ pub const VM_BEHAVIOR_REUSE: vm_behavior_t = 9;
221pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10;229pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10;
222pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11;230pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11;
223231
224pub const vm32_object_id_t = u32;232pub const VM_REGION_BASIC_INFO_64 = 9;
225pub const vm_object_id_t = u64;233pub const VM_REGION_EXTENDED_INFO = 13;
234pub const VM_REGION_TOP_INFO = 12;
235pub const VM_REGION_SUBMAP_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_info_64) / @sizeOf(natural_t);
236pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_short_info_64) / @sizeOf(natural_t);
237pub const VM_REGION_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_basic_info_64) / @sizeOf(c_int);
238pub const VM_REGION_EXTENDED_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_extended_info) / @sizeOf(natural_t);
239pub const VM_REGION_TOP_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_top_info) / @sizeOf(natural_t);
240
241pub const vm_region_basic_info_64 = extern struct {
242 protection: vm_prot_t,
243 max_protection: vm_prot_t,
244 inheritance: vm_inherit_t,
245 shared: boolean_t,
246 reserved: boolean_t,
247 offset: memory_object_offset_t,
248 behavior: vm_behavior_t,
249 user_wired_count: u16,
250};
251
252pub const vm_region_extended_info = extern struct {
253 protection: vm_prot_t,
254 user_tag: u32,
255 pages_resident: u32,
256 pages_shared_now_private: u32,
257 pages_swapped_out: u32,
258 pages_dirtied: u32,
259 ref_count: u32,
260 shadow_depth: u16,
261 external_pager: u8,
262 share_mode: u8,
263 pages_reusable: u32,
264};
265
266pub const vm_region_top_info = extern struct {
267 obj_id: u32,
268 ref_count: u32,
269 private_pages_resident: u32,
270 shared_pages_resident: u32,
271 share_mode: u8,
272};
226273
227pub const vm_region_submap_info_64 = extern struct {274pub const vm_region_submap_info_64 = extern struct {
228 // present across protection275 // present across protection
...@@ -262,6 +309,34 @@ pub const vm_region_submap_info_64 = extern struct {...@@ -262,6 +309,34 @@ pub const vm_region_submap_info_64 = extern struct {
262 object_id_full: vm_object_id_t,309 object_id_full: vm_object_id_t,
263};310};
264311
312pub const vm_region_submap_short_info_64 = extern struct {
313 // present access protection
314 protection: vm_prot_t,
315 // max avail through vm_prot
316 max_protection: vm_prot_t,
317 // behavior of map/obj on fork
318 inheritance: vm_inherit_t,
319 // offset into object/map
320 offset: memory_object_offset_t,
321 // user tag on map entry
322 user_tag: u32,
323 // obj/map mappers, etc
324 ref_count: u32,
325 // only for obj
326 shadow_depth: u16,
327 // only for obj
328 external_pager: u8,
329 // see enumeration
330 share_mode: u8,
331 // submap vs obj
332 is_submap: boolean_t,
333 // access behavior hint
334 behavior: vm_behavior_t,
335 // obj/map name, not a handle
336 object_id: vm32_object_id_t,
337 user_wired_count: u16,
338};
339
265pub const thread_act_t = mach_port_t;340pub const thread_act_t = mach_port_t;
266pub const thread_state_t = *natural_t;341pub const thread_state_t = *natural_t;
267pub const mach_port_array_t = *mach_port_t;342pub const mach_port_array_t = *mach_port_t;
...@@ -986,9 +1061,13 @@ pub const MAP = struct {...@@ -986,9 +1061,13 @@ pub const MAP = struct {
986};1061};
9871062
988pub const MSF = struct {1063pub const MSF = struct {
989 pub const ASYNC = 1;1064 pub const ASYNC = 0x1;
990 pub const INVALIDATE = 2;1065 pub const INVALIDATE = 0x2;
991 pub const SYNC = 4;1066 // invalidate, leave mapped
1067 pub const KILLPAGES = 0x4;
1068 // deactivate, leave mapped
1069 pub const DEACTIVATE = 0x8;
1070 pub const SYNC = 0x10;
992};1071};
9931072
994pub const SA = struct {1073pub const SA = struct {
lib/std/os/darwin.zig+114-8
...@@ -24,22 +24,119 @@ const mach_task = if (builtin.target.isDarwin()) struct {...@@ -24,22 +24,119 @@ const mach_task = if (builtin.target.isDarwin()) struct {
24 return self.port != 0;24 return self.port != 0;
25 }25 }
2626
27 pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!std.c.vm_prot_t {27 pub const RegionInfo = struct {
28 var base_addr = address;28 pub const Tag = enum {
29 basic,
30 extended,
31 top,
32 };
33
34 base_addr: u64,
35 tag: Tag,
36 info: union {
37 basic: std.c.vm_region_basic_info_64,
38 extended: std.c.vm_region_extended_info,
39 top: std.c.vm_region_top_info,
40 },
41 };
42
43 pub fn getRegionInfo(
44 task: MachTask,
45 address: u64,
46 len: usize,
47 tag: RegionInfo.Tag,
48 ) MachError!RegionInfo {
49 var info: RegionInfo = .{
50 .base_addr = address,
51 .tag = tag,
52 .info = undefined,
53 };
54 switch (tag) {
55 .basic => info.info = .{ .basic = undefined },
56 .extended => info.info = .{ .extended = undefined },
57 .top => info.info = .{ .top = undefined },
58 }
29 var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len;59 var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len;
30 var objname: std.c.mach_port_t = undefined;60 var objname: std.c.mach_port_t = undefined;
31 var info: std.c.vm_region_submap_info_64 = undefined;61 var count: std.c.mach_msg_type_number_t = switch (tag) {
32 var count: std.c.mach_msg_type_number_t = std.c.VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;62 .basic => std.c.VM_REGION_BASIC_INFO_COUNT,
63 .extended => std.c.VM_REGION_EXTENDED_INFO_COUNT,
64 .top => std.c.VM_REGION_TOP_INFO_COUNT,
65 };
33 switch (std.c.getKernError(std.c.mach_vm_region(66 switch (std.c.getKernError(std.c.mach_vm_region(
34 task.port,67 task.port,
35 &base_addr,68 &info.base_addr,
36 &base_len,69 &base_len,
37 std.c.VM_REGION_BASIC_INFO_64,70 switch (tag) {
38 @ptrCast(std.c.vm_region_info_t, &info),71 .basic => std.c.VM_REGION_BASIC_INFO_64,
72 .extended => std.c.VM_REGION_EXTENDED_INFO,
73 .top => std.c.VM_REGION_TOP_INFO,
74 },
75 switch (tag) {
76 .basic => @ptrCast(std.c.vm_region_info_t, &info.info.basic),
77 .extended => @ptrCast(std.c.vm_region_info_t, &info.info.extended),
78 .top => @ptrCast(std.c.vm_region_info_t, &info.info.top),
79 },
39 &count,80 &count,
40 &objname,81 &objname,
41 ))) {82 ))) {
42 .SUCCESS => return info.protection,83 .SUCCESS => return info,
84 .FAILURE => return error.PermissionDenied,
85 else => |err| {
86 log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)});
87 return error.Unexpected;
88 },
89 }
90 }
91
92 pub const RegionSubmapInfo = struct {
93 pub const Tag = enum {
94 short,
95 full,
96 };
97
98 tag: Tag,
99 base_addr: u64,
100 info: union {
101 short: std.c.vm_region_submap_short_info_64,
102 full: std.c.vm_region_submap_info_64,
103 },
104 };
105
106 pub fn getRegionSubmapInfo(
107 task: MachTask,
108 address: u64,
109 len: usize,
110 nesting_depth: u32,
111 tag: RegionSubmapInfo.Tag,
112 ) MachError!RegionSubmapInfo {
113 var info: RegionSubmapInfo = .{
114 .base_addr = address,
115 .tag = tag,
116 .info = undefined,
117 };
118 switch (tag) {
119 .short => info.info = .{ .short = undefined },
120 .full => info.info = .{ .full = undefined },
121 }
122 var nesting = nesting_depth;
123 var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len;
124 var count: std.c.mach_msg_type_number_t = switch (tag) {
125 .short => std.c.VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
126 .full => std.c.VM_REGION_SUBMAP_INFO_COUNT_64,
127 };
128 switch (std.c.getKernError(std.c.mach_vm_region_recurse(
129 task.port,
130 &info.base_addr,
131 &base_len,
132 &nesting,
133 switch (tag) {
134 .short => @ptrCast(std.c.vm_region_recurse_info_t, &info.info.short),
135 .full => @ptrCast(std.c.vm_region_recurse_info_t, &info.info.full),
136 },
137 &count,
138 ))) {
139 .SUCCESS => return info,
43 .FAILURE => return error.PermissionDenied,140 .FAILURE => return error.PermissionDenied,
44 else => |err| {141 else => |err| {
45 log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)});142 log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)});
...@@ -48,6 +145,11 @@ const mach_task = if (builtin.target.isDarwin()) struct {...@@ -48,6 +145,11 @@ const mach_task = if (builtin.target.isDarwin()) struct {
48 }145 }
49 }146 }
50147
148 pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!std.c.vm_prot_t {
149 const info = try task.getRegionSubmapInfo(address, len, 0, .short);
150 return info.info.short.protection;
151 }
152
51 pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: std.c.vm_prot_t) MachError!void {153 pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: std.c.vm_prot_t) MachError!void {
52 return task.setProtectionImpl(address, len, true, prot);154 return task.setProtectionImpl(address, len, true, prot);
53 }155 }
...@@ -216,4 +318,8 @@ const mach_task = if (builtin.target.isDarwin()) struct {...@@ -216,4 +318,8 @@ const mach_task = if (builtin.target.isDarwin()) struct {
216 }318 }
217 return MachTask{ .port = port };319 return MachTask{ .port = port };
218 }320 }
321
322 pub fn machTaskForSelf() MachTask {
323 return .{ .port = std.c.mach_task_self() };
324 }
219} else struct {};325} else struct {};