| author | |
| committer | |
| log | 648afbc839c8f367f42affd8a6ce8dce8e70a795 |
| tree | 78db1f2d729db1ec2d1be85149e842417e9935c6 |
| parent | 3c3826bf93f7cbd88ecc30b43afac12cde313ffa |
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; |
| 155 | pub const vm_map_read_t = mach_port_t; | 155 | pub const vm_map_read_t = mach_port_t; |
| 156 | pub const vm_region_flavor_t = c_int; | 156 | pub const vm_region_flavor_t = c_int; |
| 157 | pub const vm_region_info_t = *c_int; | 157 | pub const vm_region_info_t = *c_int; |
| 158 | pub const vm_region_recurse_info_t = *c_int; | ||
| 158 | pub const mach_vm_address_t = usize; | 159 | pub const mach_vm_address_t = usize; |
| 159 | pub const vm_offset_t = usize; | 160 | pub const vm_offset_t = usize; |
| 160 | pub const mach_vm_size_t = u64; | 161 | pub 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; |
| 196 | 197 | pub extern "c" fn mach_vm_region_recurse( | |
| 197 | pub const VM_REGION_BASIC_INFO_64 = 9; | 198 | target_task: vm_map_t, |
| 198 | pub 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; | ||
| 199 | 205 | ||
| 200 | pub const vm_inherit_t = u32; | 206 | pub const vm_inherit_t = u32; |
| 201 | pub const memory_object_offset_t = u64; | 207 | pub const memory_object_offset_t = u64; |
| 202 | pub const vm_behavior_t = i32; | 208 | pub const vm_behavior_t = i32; |
| 209 | pub const vm32_object_id_t = u32; | ||
| 210 | pub const vm_object_id_t = u64; | ||
| 203 | 211 | ||
| 204 | pub const VM_INHERIT_SHARE: vm_inherit_t = 0; | 212 | pub const VM_INHERIT_SHARE: vm_inherit_t = 0; |
| 205 | pub const VM_INHERIT_COPY: vm_inherit_t = 1; | 213 | pub 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; |
| 221 | pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10; | 229 | pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10; |
| 222 | pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11; | 230 | pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11; |
| 223 | 231 | ||
| 224 | pub const vm32_object_id_t = u32; | 232 | pub const VM_REGION_BASIC_INFO_64 = 9; |
| 225 | pub const vm_object_id_t = u64; | 233 | pub const VM_REGION_EXTENDED_INFO = 13; |
| 234 | pub const VM_REGION_TOP_INFO = 12; | ||
| 235 | pub const VM_REGION_SUBMAP_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_info_64) / @sizeOf(natural_t); | ||
| 236 | pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_short_info_64) / @sizeOf(natural_t); | ||
| 237 | pub const VM_REGION_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_basic_info_64) / @sizeOf(c_int); | ||
| 238 | pub const VM_REGION_EXTENDED_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_extended_info) / @sizeOf(natural_t); | ||
| 239 | pub const VM_REGION_TOP_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_top_info) / @sizeOf(natural_t); | ||
| 240 | |||
| 241 | pub 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 | |||
| 252 | pub 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 | |||
| 266 | pub 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 | }; | ||
| 226 | 273 | ||
| 227 | pub const vm_region_submap_info_64 = extern struct { | 274 | pub const vm_region_submap_info_64 = extern struct { |
| 228 | // present across protection | 275 | // 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 | }; |
| 264 | 311 | ||
| 312 | pub 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 | |||
| 265 | pub const thread_act_t = mach_port_t; | 340 | pub const thread_act_t = mach_port_t; |
| 266 | pub const thread_state_t = *natural_t; | 341 | pub const thread_state_t = *natural_t; |
| 267 | pub const mach_port_array_t = *mach_port_t; | 342 | pub 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 | }; |
| 987 | 1062 | ||
| 988 | pub const MSF = struct { | 1063 | pub 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 | }; |
| 993 | 1072 | ||
| 994 | pub const SA = struct { | 1073 | pub 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 | } |
| 26 | 26 | ||
| 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 | } |
| 50 | 147 | ||
| 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 {}; |