mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 03:03:09 +00:00
macos: update Mach routines for accessing page info
This commit is contained in:
parent
3c3826bf93
commit
648afbc839
@ -155,6 +155,7 @@ pub const vm_map_t = mach_port_t;
|
||||
pub const vm_map_read_t = mach_port_t;
|
||||
pub const vm_region_flavor_t = c_int;
|
||||
pub const vm_region_info_t = *c_int;
|
||||
pub const vm_region_recurse_info_t = *c_int;
|
||||
pub const mach_vm_address_t = usize;
|
||||
pub const vm_offset_t = usize;
|
||||
pub const mach_vm_size_t = u64;
|
||||
@ -193,13 +194,20 @@ pub extern "c" fn mach_vm_region(
|
||||
info_cnt: *mach_msg_type_number_t,
|
||||
object_name: *mach_port_t,
|
||||
) kern_return_t;
|
||||
|
||||
pub const VM_REGION_BASIC_INFO_64 = 9;
|
||||
pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_info_64) / @sizeOf(natural_t);
|
||||
pub extern "c" fn mach_vm_region_recurse(
|
||||
target_task: vm_map_t,
|
||||
address: *mach_vm_address_t,
|
||||
size: *mach_vm_size_t,
|
||||
nesting_depth: *natural_t,
|
||||
info: vm_region_recurse_info_t,
|
||||
info_cnt: *mach_msg_type_number_t,
|
||||
) kern_return_t;
|
||||
|
||||
pub const vm_inherit_t = u32;
|
||||
pub const memory_object_offset_t = u64;
|
||||
pub const vm_behavior_t = i32;
|
||||
pub const vm32_object_id_t = u32;
|
||||
pub const vm_object_id_t = u64;
|
||||
|
||||
pub const VM_INHERIT_SHARE: vm_inherit_t = 0;
|
||||
pub const VM_INHERIT_COPY: vm_inherit_t = 1;
|
||||
@ -221,8 +229,47 @@ pub const VM_BEHAVIOR_REUSE: vm_behavior_t = 9;
|
||||
pub const VM_BEHAVIOR_CAN_REUSE: vm_behavior_t = 10;
|
||||
pub const VM_BEHAVIOR_PAGEOUT: vm_behavior_t = 11;
|
||||
|
||||
pub const vm32_object_id_t = u32;
|
||||
pub const vm_object_id_t = u64;
|
||||
pub const VM_REGION_BASIC_INFO_64 = 9;
|
||||
pub const VM_REGION_EXTENDED_INFO = 13;
|
||||
pub const VM_REGION_TOP_INFO = 12;
|
||||
pub const VM_REGION_SUBMAP_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_info_64) / @sizeOf(natural_t);
|
||||
pub const VM_REGION_SUBMAP_SHORT_INFO_COUNT_64: mach_msg_type_number_t = @sizeOf(vm_region_submap_short_info_64) / @sizeOf(natural_t);
|
||||
pub const VM_REGION_BASIC_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_basic_info_64) / @sizeOf(c_int);
|
||||
pub const VM_REGION_EXTENDED_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_extended_info) / @sizeOf(natural_t);
|
||||
pub const VM_REGION_TOP_INFO_COUNT: mach_msg_type_number_t = @sizeOf(vm_region_top_info) / @sizeOf(natural_t);
|
||||
|
||||
pub const vm_region_basic_info_64 = extern struct {
|
||||
protection: vm_prot_t,
|
||||
max_protection: vm_prot_t,
|
||||
inheritance: vm_inherit_t,
|
||||
shared: boolean_t,
|
||||
reserved: boolean_t,
|
||||
offset: memory_object_offset_t,
|
||||
behavior: vm_behavior_t,
|
||||
user_wired_count: u16,
|
||||
};
|
||||
|
||||
pub const vm_region_extended_info = extern struct {
|
||||
protection: vm_prot_t,
|
||||
user_tag: u32,
|
||||
pages_resident: u32,
|
||||
pages_shared_now_private: u32,
|
||||
pages_swapped_out: u32,
|
||||
pages_dirtied: u32,
|
||||
ref_count: u32,
|
||||
shadow_depth: u16,
|
||||
external_pager: u8,
|
||||
share_mode: u8,
|
||||
pages_reusable: u32,
|
||||
};
|
||||
|
||||
pub const vm_region_top_info = extern struct {
|
||||
obj_id: u32,
|
||||
ref_count: u32,
|
||||
private_pages_resident: u32,
|
||||
shared_pages_resident: u32,
|
||||
share_mode: u8,
|
||||
};
|
||||
|
||||
pub const vm_region_submap_info_64 = extern struct {
|
||||
// present across protection
|
||||
@ -262,6 +309,34 @@ pub const vm_region_submap_info_64 = extern struct {
|
||||
object_id_full: vm_object_id_t,
|
||||
};
|
||||
|
||||
pub const vm_region_submap_short_info_64 = extern struct {
|
||||
// present access protection
|
||||
protection: vm_prot_t,
|
||||
// max avail through vm_prot
|
||||
max_protection: vm_prot_t,
|
||||
// behavior of map/obj on fork
|
||||
inheritance: vm_inherit_t,
|
||||
// offset into object/map
|
||||
offset: memory_object_offset_t,
|
||||
// user tag on map entry
|
||||
user_tag: u32,
|
||||
// obj/map mappers, etc
|
||||
ref_count: u32,
|
||||
// only for obj
|
||||
shadow_depth: u16,
|
||||
// only for obj
|
||||
external_pager: u8,
|
||||
// see enumeration
|
||||
share_mode: u8,
|
||||
// submap vs obj
|
||||
is_submap: boolean_t,
|
||||
// access behavior hint
|
||||
behavior: vm_behavior_t,
|
||||
// obj/map name, not a handle
|
||||
object_id: vm32_object_id_t,
|
||||
user_wired_count: u16,
|
||||
};
|
||||
|
||||
pub const thread_act_t = mach_port_t;
|
||||
pub const thread_state_t = *natural_t;
|
||||
pub const mach_port_array_t = *mach_port_t;
|
||||
@ -986,9 +1061,13 @@ pub const MAP = struct {
|
||||
};
|
||||
|
||||
pub const MSF = struct {
|
||||
pub const ASYNC = 1;
|
||||
pub const INVALIDATE = 2;
|
||||
pub const SYNC = 4;
|
||||
pub const ASYNC = 0x1;
|
||||
pub const INVALIDATE = 0x2;
|
||||
// invalidate, leave mapped
|
||||
pub const KILLPAGES = 0x4;
|
||||
// deactivate, leave mapped
|
||||
pub const DEACTIVATE = 0x8;
|
||||
pub const SYNC = 0x10;
|
||||
};
|
||||
|
||||
pub const SA = struct {
|
||||
|
||||
@ -24,22 +24,63 @@ const mach_task = if (builtin.target.isDarwin()) struct {
|
||||
return self.port != 0;
|
||||
}
|
||||
|
||||
pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!std.c.vm_prot_t {
|
||||
var base_addr = address;
|
||||
pub const RegionInfo = struct {
|
||||
pub const Tag = enum {
|
||||
basic,
|
||||
extended,
|
||||
top,
|
||||
};
|
||||
|
||||
base_addr: u64,
|
||||
tag: Tag,
|
||||
info: union {
|
||||
basic: std.c.vm_region_basic_info_64,
|
||||
extended: std.c.vm_region_extended_info,
|
||||
top: std.c.vm_region_top_info,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn getRegionInfo(
|
||||
task: MachTask,
|
||||
address: u64,
|
||||
len: usize,
|
||||
tag: RegionInfo.Tag,
|
||||
) MachError!RegionInfo {
|
||||
var info: RegionInfo = .{
|
||||
.base_addr = address,
|
||||
.tag = tag,
|
||||
.info = undefined,
|
||||
};
|
||||
switch (tag) {
|
||||
.basic => info.info = .{ .basic = undefined },
|
||||
.extended => info.info = .{ .extended = undefined },
|
||||
.top => info.info = .{ .top = undefined },
|
||||
}
|
||||
var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len;
|
||||
var objname: std.c.mach_port_t = undefined;
|
||||
var info: std.c.vm_region_submap_info_64 = undefined;
|
||||
var count: std.c.mach_msg_type_number_t = std.c.VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
|
||||
var count: std.c.mach_msg_type_number_t = switch (tag) {
|
||||
.basic => std.c.VM_REGION_BASIC_INFO_COUNT,
|
||||
.extended => std.c.VM_REGION_EXTENDED_INFO_COUNT,
|
||||
.top => std.c.VM_REGION_TOP_INFO_COUNT,
|
||||
};
|
||||
switch (std.c.getKernError(std.c.mach_vm_region(
|
||||
task.port,
|
||||
&base_addr,
|
||||
&info.base_addr,
|
||||
&base_len,
|
||||
std.c.VM_REGION_BASIC_INFO_64,
|
||||
@ptrCast(std.c.vm_region_info_t, &info),
|
||||
switch (tag) {
|
||||
.basic => std.c.VM_REGION_BASIC_INFO_64,
|
||||
.extended => std.c.VM_REGION_EXTENDED_INFO,
|
||||
.top => std.c.VM_REGION_TOP_INFO,
|
||||
},
|
||||
switch (tag) {
|
||||
.basic => @ptrCast(std.c.vm_region_info_t, &info.info.basic),
|
||||
.extended => @ptrCast(std.c.vm_region_info_t, &info.info.extended),
|
||||
.top => @ptrCast(std.c.vm_region_info_t, &info.info.top),
|
||||
},
|
||||
&count,
|
||||
&objname,
|
||||
))) {
|
||||
.SUCCESS => return info.protection,
|
||||
.SUCCESS => return info,
|
||||
.FAILURE => return error.PermissionDenied,
|
||||
else => |err| {
|
||||
log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)});
|
||||
@ -48,6 +89,67 @@ const mach_task = if (builtin.target.isDarwin()) struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub const RegionSubmapInfo = struct {
|
||||
pub const Tag = enum {
|
||||
short,
|
||||
full,
|
||||
};
|
||||
|
||||
tag: Tag,
|
||||
base_addr: u64,
|
||||
info: union {
|
||||
short: std.c.vm_region_submap_short_info_64,
|
||||
full: std.c.vm_region_submap_info_64,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn getRegionSubmapInfo(
|
||||
task: MachTask,
|
||||
address: u64,
|
||||
len: usize,
|
||||
nesting_depth: u32,
|
||||
tag: RegionSubmapInfo.Tag,
|
||||
) MachError!RegionSubmapInfo {
|
||||
var info: RegionSubmapInfo = .{
|
||||
.base_addr = address,
|
||||
.tag = tag,
|
||||
.info = undefined,
|
||||
};
|
||||
switch (tag) {
|
||||
.short => info.info = .{ .short = undefined },
|
||||
.full => info.info = .{ .full = undefined },
|
||||
}
|
||||
var nesting = nesting_depth;
|
||||
var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len;
|
||||
var count: std.c.mach_msg_type_number_t = switch (tag) {
|
||||
.short => std.c.VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
|
||||
.full => std.c.VM_REGION_SUBMAP_INFO_COUNT_64,
|
||||
};
|
||||
switch (std.c.getKernError(std.c.mach_vm_region_recurse(
|
||||
task.port,
|
||||
&info.base_addr,
|
||||
&base_len,
|
||||
&nesting,
|
||||
switch (tag) {
|
||||
.short => @ptrCast(std.c.vm_region_recurse_info_t, &info.info.short),
|
||||
.full => @ptrCast(std.c.vm_region_recurse_info_t, &info.info.full),
|
||||
},
|
||||
&count,
|
||||
))) {
|
||||
.SUCCESS => return info,
|
||||
.FAILURE => return error.PermissionDenied,
|
||||
else => |err| {
|
||||
log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)});
|
||||
return error.Unexpected;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!std.c.vm_prot_t {
|
||||
const info = try task.getRegionSubmapInfo(address, len, 0, .short);
|
||||
return info.info.short.protection;
|
||||
}
|
||||
|
||||
pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: std.c.vm_prot_t) MachError!void {
|
||||
return task.setProtectionImpl(address, len, true, prot);
|
||||
}
|
||||
@ -216,4 +318,8 @@ const mach_task = if (builtin.target.isDarwin()) struct {
|
||||
}
|
||||
return MachTask{ .port = port };
|
||||
}
|
||||
|
||||
pub fn machTaskForSelf() MachTask {
|
||||
return .{ .port = std.c.mach_task_self() };
|
||||
}
|
||||
} else struct {};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user