| 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 | 155 | pub const vm_map_read_t = mach_port_t; |
| 156 | 156 | pub const vm_region_flavor_t = c_int; |
| 157 | 157 | pub const vm_region_info_t = *c_int; |
| 158 | pub const vm_region_recurse_info_t = *c_int; | |
| 158 | 159 | pub const mach_vm_address_t = usize; |
| 159 | 160 | pub const vm_offset_t = usize; |
| 160 | 161 | pub const mach_vm_size_t = u64; |
| ... | ... | @@ -193,13 +194,20 @@ pub extern "c" fn mach_vm_region( |
| 193 | 194 | info_cnt: *mach_msg_type_number_t, |
| 194 | 195 | object_name: *mach_port_t, |
| 195 | 196 | ) kern_return_t; |
| 196 | ||
| 197 | pub const VM_REGION_BASIC_INFO_64 = 9; | |
| 198 | pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_info_64) / @sizeOf(natural_t); | |
| 197 | pub extern "c" fn mach_vm_region_recurse( | |
| 198 | target_task: vm_map_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 | 206 | pub const vm_inherit_t = u32; |
| 201 | 207 | pub const memory_object_offset_t = u64; |
| 202 | 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 | 212 | pub const VM_INHERIT_SHARE: vm_inherit_t = 0; |
| 205 | 213 | pub const VM_INHERIT_COPY: vm_inherit_t = 1; |
| ... | ... | @@ -221,8 +229,47 @@ pub const VM_BEHAVIOR_REUSE: vm_behavior_t = 9; |
| 221 | 229 | pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10; |
| 222 | 230 | pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11; |
| 223 | 231 | |
| 224 | pub const vm32_object_id_t = u32; | |
| 225 | pub const vm_object_id_t = u64; | |
| 232 | pub const VM_REGION_BASIC_INFO_64 = 9; | |
| 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 | 274 | pub const vm_region_submap_info_64 = extern struct { |
| 228 | 275 | // present across protection |
| ... | ... | @@ -262,6 +309,34 @@ pub const vm_region_submap_info_64 = extern struct { |
| 262 | 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 | 340 | pub const thread_act_t = mach_port_t; |
| 266 | 341 | pub const thread_state_t = *natural_t; |
| 267 | 342 | pub const mach_port_array_t = *mach_port_t; |
| ... | ... | @@ -986,9 +1061,13 @@ pub const MAP = struct { |
| 986 | 1061 | }; |
| 987 | 1062 | |
| 988 | 1063 | pub const MSF = struct { |
| 989 | pub const ASYNC = 1; | |
| 990 | pub const INVALIDATE = 2; | |
| 991 | pub const SYNC = 4; | |
| 1064 | pub const ASYNC = 0x1; | |
| 1065 | pub const INVALIDATE = 0x2; | |
| 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 | 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 | 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 { | |
| 28 | var base_addr = address; | |
| 27 | pub const RegionInfo = struct { | |
| 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 | 59 | var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len; |
| 30 | 60 | var objname: std.c.mach_port_t = undefined; |
| 31 | var info: std.c.vm_region_submap_info_64 = undefined; | |
| 32 | var count: std.c.mach_msg_type_number_t = std.c.VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; | |
| 61 | var count: std.c.mach_msg_type_number_t = switch (tag) { | |
| 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 | 66 | switch (std.c.getKernError(std.c.mach_vm_region( |
| 34 | 67 | task.port, |
| 35 | &base_addr, | |
| 68 | &info.base_addr, | |
| 36 | 69 | &base_len, |
| 37 | std.c.VM_REGION_BASIC_INFO_64, | |
| 38 | @ptrCast(std.c.vm_region_info_t, &info), | |
| 70 | switch (tag) { | |
| 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 | 80 | &count, |
| 40 | 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 | 140 | .FAILURE => return error.PermissionDenied, |
| 44 | 141 | else => |err| { |
| 45 | 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 | 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 | 153 | pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: std.c.vm_prot_t) MachError!void { |
| 52 | 154 | return task.setProtectionImpl(address, len, true, prot); |
| 53 | 155 | } |
| ... | ... | @@ -216,4 +318,8 @@ const mach_task = if (builtin.target.isDarwin()) struct { |
| 216 | 318 | } |
| 217 | 319 | return MachTask{ .port = port }; |
| 218 | 320 | } |
| 321 | ||
| 322 | pub fn machTaskForSelf() MachTask { | |
| 323 | return .{ .port = std.c.mach_task_self() }; | |
| 324 | } | |
| 219 | 325 | } else struct {}; |