| author | |
| committer | |
| log | 633c4a2a6094cd301648c2e2c6b5002917e0ef2c |
| tree | fdad1685dde93d39af844d257440ddd42ba3046b |
| parent | 2036af94e97f0ac16293556423c144ec9e1b8226 |
`std.os.darwin.MachTask` wraps `mach_port_t` and can be used to issue
kernel calls tied to the wrapped Mach kernel port/task.6 files changed, 255 insertions(+), 47 deletions(-)
CMakeLists.txt+1| ... | @@ -460,6 +460,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -460,6 +460,7 @@ set(ZIG_STAGE2_SOURCES |
| 460 | "${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig" | 460 | "${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig" |
| 461 | "${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig" | 461 | "${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig" |
| 462 | "${CMAKE_SOURCE_DIR}/lib/std/os.zig" | 462 | "${CMAKE_SOURCE_DIR}/lib/std/os.zig" |
| 463 | "${CMAKE_SOURCE_DIR}/lib/std/os/darwin.zig" | ||
| 463 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig" | 464 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig" |
| 464 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/errno/generic.zig" | 465 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/errno/generic.zig" |
| 465 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/x86_64.zig" | 466 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/x86_64.zig" |
lib/std/c/darwin.zig+18-7| ... | @@ -201,9 +201,9 @@ pub const vm_object_id_t = u64; | ... | @@ -201,9 +201,9 @@ pub const vm_object_id_t = u64; |
| 201 | 201 | ||
| 202 | pub const vm_region_submap_info_64 = extern struct { | 202 | pub const vm_region_submap_info_64 = extern struct { |
| 203 | // present across protection | 203 | // present across protection |
| 204 | protection: std.macho.vm_prot_t, | 204 | protection: vm_prot_t, |
| 205 | // max avail through vm_prot | 205 | // max avail through vm_prot |
| 206 | max_protection: std.macho.vm_prot_t, | 206 | max_protection: vm_prot_t, |
| 207 | // behavior of map/obj on fork | 207 | // behavior of map/obj on fork |
| 208 | inheritance: vm_inherit_t, | 208 | inheritance: vm_inherit_t, |
| 209 | // offset into object/map | 209 | // offset into object/map |
| ... | @@ -391,6 +391,7 @@ pub const task_vm_info = extern struct { | ... | @@ -391,6 +391,7 @@ pub const task_vm_info = extern struct { |
| 391 | }; | 391 | }; |
| 392 | pub const task_vm_info_data_t = task_vm_info; | 392 | pub const task_vm_info_data_t = task_vm_info; |
| 393 | 393 | ||
| 394 | pub const vm_prot_t = c_int; | ||
| 394 | pub const boolean_t = c_int; | 395 | pub const boolean_t = c_int; |
| 395 | 396 | ||
| 396 | pub extern "c" fn mach_vm_protect( | 397 | pub extern "c" fn mach_vm_protect( |
| ... | @@ -398,7 +399,7 @@ pub extern "c" fn mach_vm_protect( | ... | @@ -398,7 +399,7 @@ pub extern "c" fn mach_vm_protect( |
| 398 | address: mach_vm_address_t, | 399 | address: mach_vm_address_t, |
| 399 | size: mach_vm_size_t, | 400 | size: mach_vm_size_t, |
| 400 | set_maximum: boolean_t, | 401 | set_maximum: boolean_t, |
| 401 | new_protection: std.macho.vm_prot_t, | 402 | new_protection: vm_prot_t, |
| 402 | ) kern_return_t; | 403 | ) kern_return_t; |
| 403 | 404 | ||
| 404 | pub extern "c" fn mach_port_deallocate(target_tport: mach_port_name_t, task: mach_port_name_t) kern_return_t; | 405 | pub extern "c" fn mach_port_deallocate(target_tport: mach_port_name_t, task: mach_port_name_t) kern_return_t; |
| ... | @@ -920,13 +921,19 @@ pub const STDERR_FILENO = 2; | ... | @@ -920,13 +921,19 @@ pub const STDERR_FILENO = 2; |
| 920 | 921 | ||
| 921 | pub const PROT = struct { | 922 | pub const PROT = struct { |
| 922 | /// [MC2] no permissions | 923 | /// [MC2] no permissions |
| 923 | pub const NONE = 0x00; | 924 | pub const NONE: vm_prot_t = 0x00; |
| 924 | /// [MC2] pages can be read | 925 | /// [MC2] pages can be read |
| 925 | pub const READ = 0x01; | 926 | pub const READ: vm_prot_t = 0x01; |
| 926 | /// [MC2] pages can be written | 927 | /// [MC2] pages can be written |
| 927 | pub const WRITE = 0x02; | 928 | pub const WRITE: vm_prot_t = 0x02; |
| 928 | /// [MC2] pages can be executed | 929 | /// [MC2] pages can be executed |
| 929 | pub const EXEC = 0x04; | 930 | pub const EXEC: vm_prot_t = 0x04; |
| 931 | /// When a caller finds that they cannot obtain write permission on a | ||
| 932 | /// mapped entry, the following flag can be used. The entry will be | ||
| 933 | /// made "needs copy" effectively copying the object (using COW), | ||
| 934 | /// and write permission will be added to the maximum protections for | ||
| 935 | /// the associated entry. | ||
| 936 | pub const COPY: vm_prot_t = 0x10; | ||
| 930 | }; | 937 | }; |
| 931 | 938 | ||
| 932 | pub const MAP = struct { | 939 | pub const MAP = struct { |
| ... | @@ -1771,6 +1778,10 @@ pub const E = enum(u16) { | ... | @@ -1771,6 +1778,10 @@ pub const E = enum(u16) { |
| 1771 | _, | 1778 | _, |
| 1772 | }; | 1779 | }; |
| 1773 | 1780 | ||
| 1781 | pub fn getKernError(err: kern_return_t) KernE { | ||
| 1782 | return @intToEnum(KernE, err); | ||
| 1783 | } | ||
| 1784 | |||
| 1774 | /// Kernel return values | 1785 | /// Kernel return values |
| 1775 | pub const KernE = enum(u8) { | 1786 | pub const KernE = enum(u8) { |
| 1776 | SUCCESS = 0, | 1787 | SUCCESS = 0, |
lib/std/macho.zig+10-31| ... | @@ -2,12 +2,16 @@ const std = @import("std"); | ... | @@ -2,12 +2,16 @@ const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const io = std.io; | 4 | const io = std.io; |
| 5 | const os = std.os.darwin; | ||
| 5 | const mem = std.mem; | 6 | const mem = std.mem; |
| 6 | const meta = std.meta; | 7 | const meta = std.meta; |
| 7 | const testing = std.testing; | 8 | const testing = std.testing; |
| 8 | 9 | ||
| 9 | const Allocator = mem.Allocator; | 10 | const Allocator = mem.Allocator; |
| 10 | 11 | ||
| 12 | pub const cpu_type_t = os.integer_t; | ||
| 13 | pub const cpu_subtype_t = os.integer_t; | ||
| 14 | |||
| 11 | pub const mach_header = extern struct { | 15 | pub const mach_header = extern struct { |
| 12 | magic: u32, | 16 | magic: u32, |
| 13 | cputype: cpu_type_t, | 17 | cputype: cpu_type_t, |
| ... | @@ -601,10 +605,10 @@ pub const segment_command = extern struct { | ... | @@ -601,10 +605,10 @@ pub const segment_command = extern struct { |
| 601 | filesize: u32, | 605 | filesize: u32, |
| 602 | 606 | ||
| 603 | /// maximum VM protection | 607 | /// maximum VM protection |
| 604 | maxprot: vm_prot_t, | 608 | maxprot: os.vm_prot_t, |
| 605 | 609 | ||
| 606 | /// initial VM protection | 610 | /// initial VM protection |
| 607 | initprot: vm_prot_t, | 611 | initprot: os.vm_prot_t, |
| 608 | 612 | ||
| 609 | /// number of sections in segment | 613 | /// number of sections in segment |
| 610 | nsects: u32, | 614 | nsects: u32, |
| ... | @@ -638,10 +642,10 @@ pub const segment_command_64 = extern struct { | ... | @@ -638,10 +642,10 @@ pub const segment_command_64 = extern struct { |
| 638 | filesize: u64 = 0, | 642 | filesize: u64 = 0, |
| 639 | 643 | ||
| 640 | /// maximum VM protection | 644 | /// maximum VM protection |
| 641 | maxprot: vm_prot_t = VM_PROT_NONE, | 645 | maxprot: os.vm_prot_t = os.PROT.NONE, |
| 642 | 646 | ||
| 643 | /// initial VM protection | 647 | /// initial VM protection |
| 644 | initprot: vm_prot_t = VM_PROT_NONE, | 648 | initprot: os.vm_prot_t = os.PROT.NONE, |
| 645 | 649 | ||
| 646 | /// number of sections in segment | 650 | /// number of sections in segment |
| 647 | nsects: u32 = 0, | 651 | nsects: u32 = 0, |
| ... | @@ -1438,11 +1442,6 @@ pub const S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15; | ... | @@ -1438,11 +1442,6 @@ pub const S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15; |
| 1438 | /// 32-bit offsets to initializers | 1442 | /// 32-bit offsets to initializers |
| 1439 | pub const S_INIT_FUNC_OFFSETS = 0x16; | 1443 | pub const S_INIT_FUNC_OFFSETS = 0x16; |
| 1440 | 1444 | ||
| 1441 | pub const cpu_type_t = integer_t; | ||
| 1442 | pub const cpu_subtype_t = integer_t; | ||
| 1443 | pub const integer_t = c_int; | ||
| 1444 | pub const vm_prot_t = c_int; | ||
| 1445 | |||
| 1446 | /// CPU type targeting 64-bit Intel-based Macs | 1445 | /// CPU type targeting 64-bit Intel-based Macs |
| 1447 | pub const CPU_TYPE_X86_64: cpu_type_t = 0x01000007; | 1446 | pub const CPU_TYPE_X86_64: cpu_type_t = 0x01000007; |
| 1448 | 1447 | ||
| ... | @@ -1455,26 +1454,6 @@ pub const CPU_SUBTYPE_X86_64_ALL: cpu_subtype_t = 0x3; | ... | @@ -1455,26 +1454,6 @@ pub const CPU_SUBTYPE_X86_64_ALL: cpu_subtype_t = 0x3; |
| 1455 | /// All ARM-based Macs | 1454 | /// All ARM-based Macs |
| 1456 | pub const CPU_SUBTYPE_ARM_ALL: cpu_subtype_t = 0x0; | 1455 | pub const CPU_SUBTYPE_ARM_ALL: cpu_subtype_t = 0x0; |
| 1457 | 1456 | ||
| 1458 | // Protection values defined as bits within the vm_prot_t type | ||
| 1459 | /// No VM protection | ||
| 1460 | pub const VM_PROT_NONE: vm_prot_t = 0x0; | ||
| 1461 | |||
| 1462 | /// VM read permission | ||
| 1463 | pub const VM_PROT_READ: vm_prot_t = 0x1; | ||
| 1464 | |||
| 1465 | /// VM write permission | ||
| 1466 | pub const VM_PROT_WRITE: vm_prot_t = 0x2; | ||
| 1467 | |||
| 1468 | /// VM execute permission | ||
| 1469 | pub const VM_PROT_EXECUTE: vm_prot_t = 0x4; | ||
| 1470 | |||
| 1471 | /// When a caller finds that they cannot obtain write permission on a | ||
| 1472 | /// mapped entry, the following flag can be used. The entry will be | ||
| 1473 | /// made "needs copy" effectively copying the object (using COW), | ||
| 1474 | /// and write permission will be added to the maximum protections for | ||
| 1475 | /// the associated entry. | ||
| 1476 | pub const VM_PROT_COPY: vm_prot_t = 0x10; | ||
| 1477 | |||
| 1478 | // The following are used to encode rebasing information | 1457 | // The following are used to encode rebasing information |
| 1479 | pub const REBASE_TYPE_POINTER: u8 = 1; | 1458 | pub const REBASE_TYPE_POINTER: u8 = 1; |
| 1480 | pub const REBASE_TYPE_TEXT_ABSOLUTE32: u8 = 2; | 1459 | pub const REBASE_TYPE_TEXT_ABSOLUTE32: u8 = 2; |
| ... | @@ -2169,8 +2148,8 @@ test "read-write segment command" { | ... | @@ -2169,8 +2148,8 @@ test "read-write segment command" { |
| 2169 | .vmaddr = 4294967296, | 2148 | .vmaddr = 4294967296, |
| 2170 | .vmsize = 294912, | 2149 | .vmsize = 294912, |
| 2171 | .filesize = 294912, | 2150 | .filesize = 294912, |
| 2172 | .maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, | 2151 | .maxprot = os.PROT.READ | os.PROT.WRITE | os.PROT.EXEC, |
| 2173 | .initprot = VM_PROT_EXECUTE | VM_PROT_READ, | 2152 | .initprot = os.PROT.EXEC | os.PROT.READ, |
| 2174 | .nsects = 1, | 2153 | .nsects = 1, |
| 2175 | }, | 2154 | }, |
| 2176 | }; | 2155 | }; |
lib/std/os.zig+1-1| ... | @@ -29,7 +29,7 @@ const Allocator = std.mem.Allocator; | ... | @@ -29,7 +29,7 @@ const Allocator = std.mem.Allocator; |
| 29 | const Preopen = std.fs.wasi.Preopen; | 29 | const Preopen = std.fs.wasi.Preopen; |
| 30 | const PreopenList = std.fs.wasi.PreopenList; | 30 | const PreopenList = std.fs.wasi.PreopenList; |
| 31 | 31 | ||
| 32 | pub const darwin = std.c; | 32 | pub const darwin = @import("os/darwin.zig"); |
| 33 | pub const dragonfly = std.c; | 33 | pub const dragonfly = std.c; |
| 34 | pub const freebsd = std.c; | 34 | pub const freebsd = std.c; |
| 35 | pub const haiku = std.c; | 35 | pub const haiku = std.c; |
lib/std/os/darwin.zig created+216| ... | @@ -0,0 +1,216 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const log = std.log; | ||
| 3 | const mem = std.mem; | ||
| 4 | const os = @This(); | ||
| 5 | |||
| 6 | pub usingnamespace @import("../c.zig"); | ||
| 7 | |||
| 8 | pub const MachError = error{ | ||
| 9 | /// Not enough permissions held to perform the requested kernel | ||
| 10 | /// call. | ||
| 11 | PermissionDenied, | ||
| 12 | /// Kernel returned an unhandled and unexpected error code. | ||
| 13 | /// This is a catch-all for any yet unobserved kernel response | ||
| 14 | /// to some Mach message. | ||
| 15 | Unexpected, | ||
| 16 | }; | ||
| 17 | |||
| 18 | pub const MachTask = struct { | ||
| 19 | port: os.mach_port_name_t, | ||
| 20 | |||
| 21 | pub fn isValid(self: MachTask) bool { | ||
| 22 | return self.port != 0; | ||
| 23 | } | ||
| 24 | |||
| 25 | pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!os.vm_prot_t { | ||
| 26 | var base_addr = address; | ||
| 27 | var base_len: os.mach_vm_size_t = if (len == 1) 2 else len; | ||
| 28 | var objname: os.mach_port_t = undefined; | ||
| 29 | var info: os.vm_region_submap_info_64 = undefined; | ||
| 30 | var count: os.mach_msg_type_number_t = os.VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; | ||
| 31 | switch (os.getKernError(os.mach_vm_region( | ||
| 32 | task.port, | ||
| 33 | &base_addr, | ||
| 34 | &base_len, | ||
| 35 | os.VM_REGION_BASIC_INFO_64, | ||
| 36 | @ptrCast(os.vm_region_info_t, &info), | ||
| 37 | &count, | ||
| 38 | &objname, | ||
| 39 | ))) { | ||
| 40 | .SUCCESS => return info.protection, | ||
| 41 | .FAILURE => return error.PermissionDenied, | ||
| 42 | else => |err| { | ||
| 43 | log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)}); | ||
| 44 | return error.Unexpected; | ||
| 45 | }, | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: os.vm_prot_t) MachError!void { | ||
| 50 | return task.setProtectionImpl(address, len, true, prot); | ||
| 51 | } | ||
| 52 | |||
| 53 | pub fn setCurrProtection(task: MachTask, address: u64, len: usize, prot: os.vm_prot_t) MachError!void { | ||
| 54 | return task.setProtectionImpl(address, len, false, prot); | ||
| 55 | } | ||
| 56 | |||
| 57 | fn setProtectionImpl(task: MachTask, address: u64, len: usize, set_max: bool, prot: os.vm_prot_t) MachError!void { | ||
| 58 | switch (os.getKernError(os.mach_vm_protect(task.port, address, len, @boolToInt(set_max), prot))) { | ||
| 59 | .SUCCESS => return, | ||
| 60 | .FAILURE => return error.PermissionDenied, | ||
| 61 | else => |err| { | ||
| 62 | log.err("mach_vm_protect kernel call failed with error code: {s}", .{@tagName(err)}); | ||
| 63 | return error.Unexpected; | ||
| 64 | }, | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Will write to VM even if current protection attributes specifically prohibit | ||
| 69 | /// us from doing so, by temporarily setting protection level to a level with VM_PROT_COPY | ||
| 70 | /// variant, and resetting after a successful or unsuccessful write. | ||
| 71 | pub fn writeMemProtected(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize { | ||
| 72 | const curr_prot = try task.getCurrProtection(address, buf.len); | ||
| 73 | try task.setCurrProtection( | ||
| 74 | address, | ||
| 75 | buf.len, | ||
| 76 | os.PROT.READ | os.PROT.WRITE | os.PROT.COPY, | ||
| 77 | ); | ||
| 78 | defer { | ||
| 79 | task.setCurrProtection(address, buf.len, curr_prot) catch {}; | ||
| 80 | } | ||
| 81 | return task.writeMem(address, buf, arch); | ||
| 82 | } | ||
| 83 | |||
| 84 | pub fn writeMem(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize { | ||
| 85 | const count = buf.len; | ||
| 86 | var total_written: usize = 0; | ||
| 87 | var curr_addr = address; | ||
| 88 | const page_size = try getPageSize(task); // TODO we probably can assume value here | ||
| 89 | var out_buf = buf[0..]; | ||
| 90 | |||
| 91 | while (total_written < count) { | ||
| 92 | const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_written); | ||
| 93 | switch (os.getKernError(os.mach_vm_write( | ||
| 94 | task.port, | ||
| 95 | curr_addr, | ||
| 96 | @ptrToInt(out_buf.ptr), | ||
| 97 | @intCast(os.mach_msg_type_number_t, curr_size), | ||
| 98 | ))) { | ||
| 99 | .SUCCESS => {}, | ||
| 100 | .FAILURE => return error.PermissionDenied, | ||
| 101 | else => |err| { | ||
| 102 | log.err("mach_vm_write kernel call failed with error code: {s}", .{@tagName(err)}); | ||
| 103 | return error.Unexpected; | ||
| 104 | }, | ||
| 105 | } | ||
| 106 | |||
| 107 | switch (arch) { | ||
| 108 | .aarch64 => { | ||
| 109 | var mattr_value: os.vm_machine_attribute_val_t = os.MATTR_VAL_CACHE_FLUSH; | ||
| 110 | switch (os.getKernError(os.vm_machine_attribute( | ||
| 111 | task.port, | ||
| 112 | curr_addr, | ||
| 113 | curr_size, | ||
| 114 | os.MATTR_CACHE, | ||
| 115 | &mattr_value, | ||
| 116 | ))) { | ||
| 117 | .SUCCESS => {}, | ||
| 118 | .FAILURE => return error.PermissionDenied, | ||
| 119 | else => |err| { | ||
| 120 | log.err("vm_machine_attribute kernel call failed with error code: {s}", .{@tagName(err)}); | ||
| 121 | return error.Unexpected; | ||
| 122 | }, | ||
| 123 | } | ||
| 124 | }, | ||
| 125 | .x86_64 => {}, | ||
| 126 | else => unreachable, | ||
| 127 | } | ||
| 128 | |||
| 129 | out_buf = out_buf[curr_size..]; | ||
| 130 | total_written += curr_size; | ||
| 131 | curr_addr += curr_size; | ||
| 132 | } | ||
| 133 | |||
| 134 | return total_written; | ||
| 135 | } | ||
| 136 | |||
| 137 | pub fn readMem(task: MachTask, address: u64, buf: []u8) MachError!usize { | ||
| 138 | const count = buf.len; | ||
| 139 | var total_read: usize = 0; | ||
| 140 | var curr_addr = address; | ||
| 141 | const page_size = try getPageSize(task); // TODO we probably can assume value here | ||
| 142 | var out_buf = buf[0..]; | ||
| 143 | |||
| 144 | while (total_read < count) { | ||
| 145 | const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_read); | ||
| 146 | var curr_bytes_read: os.mach_msg_type_number_t = 0; | ||
| 147 | var vm_memory: os.vm_offset_t = undefined; | ||
| 148 | switch (os.getKernError(os.mach_vm_read(task.port, curr_addr, curr_size, &vm_memory, &curr_bytes_read))) { | ||
| 149 | .SUCCESS => {}, | ||
| 150 | .FAILURE => return error.PermissionDenied, | ||
| 151 | else => |err| { | ||
| 152 | log.err("mach_vm_read kernel call failed with error code: {s}", .{@tagName(err)}); | ||
| 153 | return error.Unexpected; | ||
| 154 | }, | ||
| 155 | } | ||
| 156 | |||
| 157 | @memcpy(out_buf[0..].ptr, @intToPtr([*]const u8, vm_memory), curr_bytes_read); | ||
| 158 | _ = os.vm_deallocate(os.mach_task_self(), vm_memory, curr_bytes_read); | ||
| 159 | |||
| 160 | out_buf = out_buf[curr_bytes_read..]; | ||
| 161 | curr_addr += curr_bytes_read; | ||
| 162 | total_read += curr_bytes_read; | ||
| 163 | } | ||
| 164 | |||
| 165 | return total_read; | ||
| 166 | } | ||
| 167 | |||
| 168 | fn maxBytesLeftInPage(page_size: usize, address: u64, count: usize) usize { | ||
| 169 | var left = count; | ||
| 170 | if (page_size > 0) { | ||
| 171 | const page_offset = address % page_size; | ||
| 172 | const bytes_left_in_page = page_size - page_offset; | ||
| 173 | if (count > bytes_left_in_page) { | ||
| 174 | left = bytes_left_in_page; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | return left; | ||
| 178 | } | ||
| 179 | |||
| 180 | fn getPageSize(task: MachTask) MachError!usize { | ||
| 181 | if (task.isValid()) { | ||
| 182 | var info_count = os.TASK_VM_INFO_COUNT; | ||
| 183 | var vm_info: os.task_vm_info_data_t = undefined; | ||
| 184 | switch (os.getKernError(os.task_info( | ||
| 185 | task.port, | ||
| 186 | os.TASK_VM_INFO, | ||
| 187 | @ptrCast(os.task_info_t, &vm_info), | ||
| 188 | &info_count, | ||
| 189 | ))) { | ||
| 190 | .SUCCESS => return @intCast(usize, vm_info.page_size), | ||
| 191 | else => {}, | ||
| 192 | } | ||
| 193 | } | ||
| 194 | var page_size: os.vm_size_t = undefined; | ||
| 195 | switch (os.getKernError(os._host_page_size(os.mach_host_self(), &page_size))) { | ||
| 196 | .SUCCESS => return page_size, | ||
| 197 | else => |err| { | ||
| 198 | log.err("_host_page_size kernel call failed with error code: {s}", .{@tagName(err)}); | ||
| 199 | return error.Unexpected; | ||
| 200 | }, | ||
| 201 | } | ||
| 202 | } | ||
| 203 | }; | ||
| 204 | |||
| 205 | pub fn machTaskForPid(pid: os.pid_t) MachError!MachTask { | ||
| 206 | var port: os.mach_port_name_t = undefined; | ||
| 207 | switch (os.getKernError(os.task_for_pid(os.mach_task_self(), pid, &port))) { | ||
| 208 | .SUCCESS => {}, | ||
| 209 | .FAILURE => return error.PermissionDenied, | ||
| 210 | else => |err| { | ||
| 211 | log.err("task_for_pid kernel call failed with error code: {s}", .{@tagName(err)}); | ||
| 212 | return error.Unexpected; | ||
| 213 | }, | ||
| 214 | } | ||
| 215 | return MachTask{ .port = port }; | ||
| 216 | } | ||
src/link/MachO.zig+9-8| ... | @@ -4,6 +4,7 @@ const std = @import("std"); | ... | @@ -4,6 +4,7 @@ const std = @import("std"); |
| 4 | const build_options = @import("build_options"); | 4 | const build_options = @import("build_options"); |
| 5 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const darwin = std.os.darwin; | ||
| 7 | const fmt = std.fmt; | 8 | const fmt = std.fmt; |
| 8 | const fs = std.fs; | 9 | const fs = std.fs; |
| 9 | const log = std.log.scoped(.link); | 10 | const log = std.log.scoped(.link); |
| ... | @@ -4382,8 +4383,8 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4382,8 +4383,8 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4382 | .vmaddr = pagezero_vmsize, | 4383 | .vmaddr = pagezero_vmsize, |
| 4383 | .vmsize = needed_size, | 4384 | .vmsize = needed_size, |
| 4384 | .filesize = needed_size, | 4385 | .filesize = needed_size, |
| 4385 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE, | 4386 | .maxprot = darwin.PROT.READ | darwin.PROT.EXEC, |
| 4386 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE, | 4387 | .initprot = darwin.PROT.READ | darwin.PROT.EXEC, |
| 4387 | }, | 4388 | }, |
| 4388 | }, | 4389 | }, |
| 4389 | }); | 4390 | }); |
| ... | @@ -4487,8 +4488,8 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4487,8 +4488,8 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4487 | .vmsize = needed_size, | 4488 | .vmsize = needed_size, |
| 4488 | .fileoff = fileoff, | 4489 | .fileoff = fileoff, |
| 4489 | .filesize = needed_size, | 4490 | .filesize = needed_size, |
| 4490 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4491 | .maxprot = darwin.PROT.READ | darwin.PROT.WRITE, |
| 4491 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4492 | .initprot = darwin.PROT.READ | darwin.PROT.WRITE, |
| 4492 | }, | 4493 | }, |
| 4493 | }, | 4494 | }, |
| 4494 | }); | 4495 | }); |
| ... | @@ -4536,8 +4537,8 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4536,8 +4537,8 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4536 | .vmsize = needed_size, | 4537 | .vmsize = needed_size, |
| 4537 | .fileoff = fileoff, | 4538 | .fileoff = fileoff, |
| 4538 | .filesize = needed_size, | 4539 | .filesize = needed_size, |
| 4539 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4540 | .maxprot = darwin.PROT.READ | darwin.PROT.WRITE, |
| 4540 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4541 | .initprot = darwin.PROT.READ | darwin.PROT.WRITE, |
| 4541 | }, | 4542 | }, |
| 4542 | }, | 4543 | }, |
| 4543 | }); | 4544 | }); |
| ... | @@ -4645,8 +4646,8 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4645,8 +4646,8 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4645 | .segname = makeStaticString("__LINKEDIT"), | 4646 | .segname = makeStaticString("__LINKEDIT"), |
| 4646 | .vmaddr = vmaddr, | 4647 | .vmaddr = vmaddr, |
| 4647 | .fileoff = fileoff, | 4648 | .fileoff = fileoff, |
| 4648 | .maxprot = macho.VM_PROT_READ, | 4649 | .maxprot = darwin.PROT.READ, |
| 4649 | .initprot = macho.VM_PROT_READ, | 4650 | .initprot = darwin.PROT.READ, |
| 4650 | }, | 4651 | }, |
| 4651 | }, | 4652 | }, |
| 4652 | }); | 4653 | }); |