authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-15 10:12:48+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-16 11:42:30+01:00
loge1e414e62a86cc460ef215ea8050c953b68b6080
tree833ddee60d5171271bb7f3f98d49c439e4e8139b
parentbd242ce1ce9ef6ffb1af4432d892bf582dcdba8a

std: move os/darwin.zig and related to c/darwin.zig

Move to c/darwin.zig as they really are libSystem/libc imports/wrappers. As an added bonus, get rid of the nasty `usingnamespace`s which are now unneeded. Finally, add `os.ptrace` but currently only implemented on darwin.

7 files changed, 547 insertions(+), 618 deletions(-)

CMakeLists.txt-1
......@@ -296,7 +296,6 @@ set(ZIG_STAGE2_SOURCES
296296 "${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig"
297297 "${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig"
298298 "${CMAKE_SOURCE_DIR}/lib/std/os.zig"
299 "${CMAKE_SOURCE_DIR}/lib/std/os/darwin.zig"
300299 "${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig"
301300 "${CMAKE_SOURCE_DIR}/lib/std/os/linux/errno/generic.zig"
302301 "${CMAKE_SOURCE_DIR}/lib/std/os/linux/x86_64.zig"
lib/std/c/darwin.zig+477
......@@ -8,6 +8,7 @@ const iovec_const = std.os.iovec_const;
88
99pub const aarch64 = @import("darwin/aarch64.zig");
1010pub const x86_64 = @import("darwin/x86_64.zig");
11pub const cssm = @import("darwin/cssm.zig");
1112
1213const arch_bits = switch (native_arch) {
1314 .aarch64 => @import("darwin/aarch64.zig"),
......@@ -2179,6 +2180,14 @@ pub fn getKernError(err: kern_return_t) KernE {
21792180 return @intToEnum(KernE, @truncate(u32, @intCast(usize, err)));
21802181}
21812182
2183pub fn unexpectedKernError(err: KernE) std.os.UnexpectedError {
2184 if (std.os.unexpected_error_tracing) {
2185 std.debug.print("unexpected errno: {d}\n", .{@enumToInt(err)});
2186 std.debug.dumpCurrentStackTrace(null);
2187 }
2188 return error.Unexpected;
2189}
2190
21822191/// Kernel return values
21832192pub const KernE = enum(u32) {
21842193 SUCCESS = 0,
......@@ -3085,3 +3094,471 @@ pub const PT_DENY_ATTACH = 31;
30853094pub const caddr_t = ?[*]u8;
30863095
30873096pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
3097
3098pub const MachError = error{
3099 /// Not enough permissions held to perform the requested kernel
3100 /// call.
3101 PermissionDenied,
3102} || std.os.UnexpectedError;
3103
3104pub const MachTask = extern struct {
3105 port: mach_port_name_t,
3106
3107 pub fn isValid(self: MachTask) bool {
3108 return self.port != TASK_NULL;
3109 }
3110
3111 pub fn pidForTask(self: MachTask) MachError!std.os.pid_t {
3112 var pid: std.os.pid_t = undefined;
3113 switch (getKernError(pid_for_task(self.port, &pid))) {
3114 .SUCCESS => return pid,
3115 .FAILURE => return error.PermissionDenied,
3116 else => |err| return unexpectedKernError(err),
3117 }
3118 }
3119
3120 pub fn allocatePort(self: MachTask, right: MACH_PORT_RIGHT) MachError!MachTask {
3121 var out_port: mach_port_name_t = undefined;
3122 switch (getKernError(mach_port_allocate(
3123 self.port,
3124 @enumToInt(right),
3125 &out_port,
3126 ))) {
3127 .SUCCESS => return .{ .port = out_port },
3128 .FAILURE => return error.PermissionDenied,
3129 else => |err| return unexpectedKernError(err),
3130 }
3131 }
3132
3133 pub fn deallocatePort(self: MachTask, port: MachTask) void {
3134 _ = getKernError(mach_port_deallocate(self.port, port.port));
3135 }
3136
3137 pub fn insertRight(self: MachTask, port: MachTask, msg: MACH_MSG_TYPE) !void {
3138 switch (getKernError(mach_port_insert_right(
3139 self.port,
3140 port.port,
3141 port.port,
3142 @enumToInt(msg),
3143 ))) {
3144 .SUCCESS => return,
3145 .FAILURE => return error.PermissionDenied,
3146 else => |err| return unexpectedKernError(err),
3147 }
3148 }
3149
3150 pub const PortInfo = struct {
3151 mask: exception_mask_t,
3152 masks: [EXC_TYPES_COUNT]exception_mask_t,
3153 ports: [EXC_TYPES_COUNT]mach_port_t,
3154 behaviors: [EXC_TYPES_COUNT]exception_behavior_t,
3155 flavors: [EXC_TYPES_COUNT]thread_state_flavor_t,
3156 count: mach_msg_type_number_t,
3157 };
3158
3159 pub fn getExceptionPorts(self: MachTask, mask: exception_mask_t) !PortInfo {
3160 var info = PortInfo{
3161 .mask = mask,
3162 .masks = undefined,
3163 .ports = undefined,
3164 .behaviors = undefined,
3165 .flavors = undefined,
3166 .count = 0,
3167 };
3168 info.count = info.ports.len / @sizeOf(mach_port_t);
3169
3170 switch (getKernError(task_get_exception_ports(
3171 self.port,
3172 info.mask,
3173 &info.masks,
3174 &info.count,
3175 &info.ports,
3176 &info.behaviors,
3177 &info.flavors,
3178 ))) {
3179 .SUCCESS => return info,
3180 .FAILURE => return error.PermissionDenied,
3181 else => |err| return unexpectedKernError(err),
3182 }
3183 }
3184
3185 pub fn setExceptionPorts(
3186 self: MachTask,
3187 mask: exception_mask_t,
3188 new_port: MachTask,
3189 behavior: exception_behavior_t,
3190 new_flavor: thread_state_flavor_t,
3191 ) !void {
3192 switch (getKernError(task_set_exception_ports(
3193 self.port,
3194 mask,
3195 new_port.port,
3196 behavior,
3197 new_flavor,
3198 ))) {
3199 .SUCCESS => return,
3200 .FAILURE => return error.PermissionDenied,
3201 else => |err| return unexpectedKernError(err),
3202 }
3203 }
3204
3205 pub const RegionInfo = struct {
3206 pub const Tag = enum {
3207 basic,
3208 extended,
3209 top,
3210 };
3211
3212 base_addr: u64,
3213 tag: Tag,
3214 info: union {
3215 basic: vm_region_basic_info_64,
3216 extended: vm_region_extended_info,
3217 top: vm_region_top_info,
3218 },
3219 };
3220
3221 pub fn getRegionInfo(
3222 task: MachTask,
3223 address: u64,
3224 len: usize,
3225 tag: RegionInfo.Tag,
3226 ) MachError!RegionInfo {
3227 var info: RegionInfo = .{
3228 .base_addr = address,
3229 .tag = tag,
3230 .info = undefined,
3231 };
3232 switch (tag) {
3233 .basic => info.info = .{ .basic = undefined },
3234 .extended => info.info = .{ .extended = undefined },
3235 .top => info.info = .{ .top = undefined },
3236 }
3237 var base_len: mach_vm_size_t = if (len == 1) 2 else len;
3238 var objname: mach_port_t = undefined;
3239 var count: mach_msg_type_number_t = switch (tag) {
3240 .basic => VM_REGION_BASIC_INFO_COUNT,
3241 .extended => VM_REGION_EXTENDED_INFO_COUNT,
3242 .top => VM_REGION_TOP_INFO_COUNT,
3243 };
3244 switch (getKernError(mach_vm_region(
3245 task.port,
3246 &info.base_addr,
3247 &base_len,
3248 switch (tag) {
3249 .basic => VM_REGION_BASIC_INFO_64,
3250 .extended => VM_REGION_EXTENDED_INFO,
3251 .top => VM_REGION_TOP_INFO,
3252 },
3253 switch (tag) {
3254 .basic => @ptrCast(vm_region_info_t, &info.info.basic),
3255 .extended => @ptrCast(vm_region_info_t, &info.info.extended),
3256 .top => @ptrCast(vm_region_info_t, &info.info.top),
3257 },
3258 &count,
3259 &objname,
3260 ))) {
3261 .SUCCESS => return info,
3262 .FAILURE => return error.PermissionDenied,
3263 else => |err| return unexpectedKernError(err),
3264 }
3265 }
3266
3267 pub const RegionSubmapInfo = struct {
3268 pub const Tag = enum {
3269 short,
3270 full,
3271 };
3272
3273 tag: Tag,
3274 base_addr: u64,
3275 info: union {
3276 short: vm_region_submap_short_info_64,
3277 full: vm_region_submap_info_64,
3278 },
3279 };
3280
3281 pub fn getRegionSubmapInfo(
3282 task: MachTask,
3283 address: u64,
3284 len: usize,
3285 nesting_depth: u32,
3286 tag: RegionSubmapInfo.Tag,
3287 ) MachError!RegionSubmapInfo {
3288 var info: RegionSubmapInfo = .{
3289 .base_addr = address,
3290 .tag = tag,
3291 .info = undefined,
3292 };
3293 switch (tag) {
3294 .short => info.info = .{ .short = undefined },
3295 .full => info.info = .{ .full = undefined },
3296 }
3297 var nesting = nesting_depth;
3298 var base_len: mach_vm_size_t = if (len == 1) 2 else len;
3299 var count: mach_msg_type_number_t = switch (tag) {
3300 .short => VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
3301 .full => VM_REGION_SUBMAP_INFO_COUNT_64,
3302 };
3303 switch (getKernError(mach_vm_region_recurse(
3304 task.port,
3305 &info.base_addr,
3306 &base_len,
3307 &nesting,
3308 switch (tag) {
3309 .short => @ptrCast(vm_region_recurse_info_t, &info.info.short),
3310 .full => @ptrCast(vm_region_recurse_info_t, &info.info.full),
3311 },
3312 &count,
3313 ))) {
3314 .SUCCESS => return info,
3315 .FAILURE => return error.PermissionDenied,
3316 else => |err| return unexpectedKernError(err),
3317 }
3318 }
3319
3320 pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!vm_prot_t {
3321 const info = try task.getRegionSubmapInfo(address, len, 0, .short);
3322 return info.info.short.protection;
3323 }
3324
3325 pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: vm_prot_t) MachError!void {
3326 return task.setProtectionImpl(address, len, true, prot);
3327 }
3328
3329 pub fn setCurrProtection(task: MachTask, address: u64, len: usize, prot: vm_prot_t) MachError!void {
3330 return task.setProtectionImpl(address, len, false, prot);
3331 }
3332
3333 fn setProtectionImpl(task: MachTask, address: u64, len: usize, set_max: bool, prot: vm_prot_t) MachError!void {
3334 switch (getKernError(mach_vm_protect(task.port, address, len, @boolToInt(set_max), prot))) {
3335 .SUCCESS => return,
3336 .FAILURE => return error.PermissionDenied,
3337 else => |err| return unexpectedKernError(err),
3338 }
3339 }
3340
3341 /// Will write to VM even if current protection attributes specifically prohibit
3342 /// us from doing so, by temporarily setting protection level to a level with VM_PROT_COPY
3343 /// variant, and resetting after a successful or unsuccessful write.
3344 pub fn writeMemProtected(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize {
3345 const curr_prot = try task.getCurrProtection(address, buf.len);
3346 try task.setCurrProtection(
3347 address,
3348 buf.len,
3349 PROT.READ | PROT.WRITE | PROT.COPY,
3350 );
3351 defer {
3352 task.setCurrProtection(address, buf.len, curr_prot) catch {};
3353 }
3354 return task.writeMem(address, buf, arch);
3355 }
3356
3357 pub fn writeMem(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize {
3358 const count = buf.len;
3359 var total_written: usize = 0;
3360 var curr_addr = address;
3361 const page_size = try getPageSize(task); // TODO we probably can assume value here
3362 var out_buf = buf[0..];
3363
3364 while (total_written < count) {
3365 const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_written);
3366 switch (getKernError(mach_vm_write(
3367 task.port,
3368 curr_addr,
3369 @ptrToInt(out_buf.ptr),
3370 @intCast(mach_msg_type_number_t, curr_size),
3371 ))) {
3372 .SUCCESS => {},
3373 .FAILURE => return error.PermissionDenied,
3374 else => |err| return unexpectedKernError(err),
3375 }
3376
3377 switch (arch) {
3378 .aarch64 => {
3379 var mattr_value: vm_machine_attribute_val_t = MATTR_VAL_CACHE_FLUSH;
3380 switch (getKernError(vm_machine_attribute(
3381 task.port,
3382 curr_addr,
3383 curr_size,
3384 MATTR_CACHE,
3385 &mattr_value,
3386 ))) {
3387 .SUCCESS => {},
3388 .FAILURE => return error.PermissionDenied,
3389 else => |err| return unexpectedKernError(err),
3390 }
3391 },
3392 .x86_64 => {},
3393 else => unreachable,
3394 }
3395
3396 out_buf = out_buf[curr_size..];
3397 total_written += curr_size;
3398 curr_addr += curr_size;
3399 }
3400
3401 return total_written;
3402 }
3403
3404 pub fn readMem(task: MachTask, address: u64, buf: []u8) MachError!usize {
3405 const count = buf.len;
3406 var total_read: usize = 0;
3407 var curr_addr = address;
3408 const page_size = try getPageSize(task); // TODO we probably can assume value here
3409 var out_buf = buf[0..];
3410
3411 while (total_read < count) {
3412 const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_read);
3413 var curr_bytes_read: mach_msg_type_number_t = 0;
3414 var vm_memory: vm_offset_t = undefined;
3415 switch (getKernError(mach_vm_read(task.port, curr_addr, curr_size, &vm_memory, &curr_bytes_read))) {
3416 .SUCCESS => {},
3417 .FAILURE => return error.PermissionDenied,
3418 else => |err| return unexpectedKernError(err),
3419 }
3420
3421 @memcpy(out_buf[0..].ptr, @intToPtr([*]const u8, vm_memory), curr_bytes_read);
3422 _ = vm_deallocate(mach_task_self(), vm_memory, curr_bytes_read);
3423
3424 out_buf = out_buf[curr_bytes_read..];
3425 curr_addr += curr_bytes_read;
3426 total_read += curr_bytes_read;
3427 }
3428
3429 return total_read;
3430 }
3431
3432 fn maxBytesLeftInPage(page_size: usize, address: u64, count: usize) usize {
3433 var left = count;
3434 if (page_size > 0) {
3435 const page_offset = address % page_size;
3436 const bytes_left_in_page = page_size - page_offset;
3437 if (count > bytes_left_in_page) {
3438 left = bytes_left_in_page;
3439 }
3440 }
3441 return left;
3442 }
3443
3444 fn getPageSize(task: MachTask) MachError!usize {
3445 if (task.isValid()) {
3446 var info_count = TASK_VM_INFO_COUNT;
3447 var vm_info: task_vm_info_data_t = undefined;
3448 switch (getKernError(task_info(
3449 task.port,
3450 TASK_VM_INFO,
3451 @ptrCast(task_info_t, &vm_info),
3452 &info_count,
3453 ))) {
3454 .SUCCESS => return @intCast(usize, vm_info.page_size),
3455 else => {},
3456 }
3457 }
3458 var page_size: vm_size_t = undefined;
3459 switch (getKernError(_host_page_size(mach_host_self(), &page_size))) {
3460 .SUCCESS => return page_size,
3461 else => |err| return unexpectedKernError(err),
3462 }
3463 }
3464
3465 pub fn basicTaskInfo(task: MachTask) MachError!mach_task_basic_info {
3466 var info: mach_task_basic_info = undefined;
3467 var count = MACH_TASK_BASIC_INFO_COUNT;
3468 switch (getKernError(task_info(
3469 task.port,
3470 MACH_TASK_BASIC_INFO,
3471 @ptrCast(task_info_t, &info),
3472 &count,
3473 ))) {
3474 .SUCCESS => return info,
3475 else => |err| return unexpectedKernError(err),
3476 }
3477 }
3478
3479 pub fn @"resume"(task: MachTask) MachError!void {
3480 switch (getKernError(task_resume(task.port))) {
3481 .SUCCESS => {},
3482 else => |err| return unexpectedKernError(err),
3483 }
3484 }
3485
3486 pub fn @"suspend"(task: MachTask) MachError!void {
3487 switch (getKernError(task_suspend(task.port))) {
3488 .SUCCESS => {},
3489 else => |err| return unexpectedKernError(err),
3490 }
3491 }
3492
3493 const ThreadList = struct {
3494 buf: []MachThread,
3495
3496 pub fn deinit(list: ThreadList) void {
3497 const self_task = machTaskForSelf();
3498 _ = vm_deallocate(
3499 self_task.port,
3500 @ptrToInt(list.buf.ptr),
3501 @intCast(vm_size_t, list.buf.len * @sizeOf(mach_port_t)),
3502 );
3503 }
3504 };
3505
3506 pub fn getThreads(task: MachTask) MachError!ThreadList {
3507 var thread_list: mach_port_array_t = undefined;
3508 var thread_count: mach_msg_type_number_t = undefined;
3509 switch (getKernError(task_threads(task.port, &thread_list, &thread_count))) {
3510 .SUCCESS => return ThreadList{ .buf = @ptrCast([*]MachThread, thread_list)[0..thread_count] },
3511 else => |err| return unexpectedKernError(err),
3512 }
3513 }
3514};
3515
3516pub const MachThread = extern struct {
3517 port: mach_port_t,
3518
3519 pub fn isValid(thread: MachThread) bool {
3520 return thread.port != THREAD_NULL;
3521 }
3522
3523 pub fn getBasicInfo(thread: MachThread) MachError!thread_basic_info {
3524 var info: thread_basic_info = undefined;
3525 var count = THREAD_BASIC_INFO_COUNT;
3526 switch (getKernError(thread_info(
3527 thread.port,
3528 THREAD_BASIC_INFO,
3529 @ptrCast(thread_info_t, &info),
3530 &count,
3531 ))) {
3532 .SUCCESS => return info,
3533 else => |err| return unexpectedKernError(err),
3534 }
3535 }
3536
3537 pub fn getIdentifierInfo(thread: MachThread) MachError!thread_identifier_info {
3538 var info: thread_identifier_info = undefined;
3539 var count = THREAD_IDENTIFIER_INFO_COUNT;
3540 switch (getKernError(thread_info(
3541 thread.port,
3542 THREAD_IDENTIFIER_INFO,
3543 @ptrCast(thread_info_t, &info),
3544 &count,
3545 ))) {
3546 .SUCCESS => return info,
3547 else => |err| return unexpectedKernError(err),
3548 }
3549 }
3550};
3551
3552pub fn machTaskForPid(pid: std.os.pid_t) MachError!MachTask {
3553 var port: mach_port_name_t = undefined;
3554 switch (getKernError(task_for_pid(mach_task_self(), pid, &port))) {
3555 .SUCCESS => {},
3556 .FAILURE => return error.PermissionDenied,
3557 else => |err| return unexpectedKernError(err),
3558 }
3559 return MachTask{ .port = port };
3560}
3561
3562pub fn machTaskForSelf() MachTask {
3563 return .{ .port = mach_task_self() };
3564}
lib/std/c/darwin/cssm.zig created+47
......@@ -0,0 +1,47 @@
1// Common Security Services Manager
2// Security.framework/Headers/cssm*.h
3
4// Schema Management Name Space Range Definition
5pub const DB_RECORDTYPE_SCHEMA_START = 0x00000000;
6pub const DB_RECORDTYPE_SCHEMA_END = DB_RECORDTYPE_SCHEMA_START + 4;
7
8// Open Group Application Name Space Range Definition
9pub const DB_RECORDTYPE_OPEN_GROUP_START = 0x0000000A;
10pub const DB_RECORDTYPE_OPEN_GROUP_END = DB_RECORDTYPE_OPEN_GROUP_START + 8;
11
12// Industry At Large Application Name Space Range Definition
13pub const DB_RECORDTYPE_APP_DEFINED_START = 0x80000000;
14pub const DB_RECORDTYPE_APP_DEFINED_END = 0xffffffff;
15
16pub const DB_RECORDTYPE = enum(u32) {
17 // Record Types defined in the Schema Management Name Space
18 SCHEMA_INFO = DB_RECORDTYPE_SCHEMA_START + 0,
19 SCHEMA_INDEXES = DB_RECORDTYPE_SCHEMA_START + 1,
20 SCHEMA_ATTRIBUTES = DB_RECORDTYPE_SCHEMA_START + 2,
21 SCHEMA_PARSING_MODULE = DB_RECORDTYPE_SCHEMA_START + 3,
22
23 // Record Types defined in the Open Group Application Name Space
24 ANY = DB_RECORDTYPE_OPEN_GROUP_START + 0,
25 CERT = DB_RECORDTYPE_OPEN_GROUP_START + 1,
26 CRL = DB_RECORDTYPE_OPEN_GROUP_START + 2,
27 POLICY = DB_RECORDTYPE_OPEN_GROUP_START + 3,
28 GENERIC = DB_RECORDTYPE_OPEN_GROUP_START + 4,
29 PUBLIC_KEY = DB_RECORDTYPE_OPEN_GROUP_START + 5,
30 PRIVATE_KEY = DB_RECORDTYPE_OPEN_GROUP_START + 6,
31 SYMMETRIC_KEY = DB_RECORDTYPE_OPEN_GROUP_START + 7,
32 ALL_KEYS = DB_RECORDTYPE_OPEN_GROUP_START + 8,
33
34 // AppleFileDL record types
35 GENERIC_PASSWORD = DB_RECORDTYPE_APP_DEFINED_START + 0,
36 INTERNET_PASSWORD = DB_RECORDTYPE_APP_DEFINED_START + 1,
37 APPLESHARE_PASSWORD = DB_RECORDTYPE_APP_DEFINED_START + 2,
38
39 X509_CERTIFICATE = DB_RECORDTYPE_APP_DEFINED_START + 0x1000,
40 USER_TRUST,
41 X509_CRL,
42 UNLOCK_REFERRAL,
43 EXTENDED_ATTRIBUTE,
44 METADATA = DB_RECORDTYPE_APP_DEFINED_START + 0x8000,
45
46 _,
47};
lib/std/os.zig+23-2
......@@ -29,7 +29,7 @@ const Allocator = std.mem.Allocator;
2929const Preopen = std.fs.wasi.Preopen;
3030const PreopenList = std.fs.wasi.PreopenList;
3131
32pub const darwin = @import("os/darwin.zig");
32pub const darwin = std.c;
3333pub const dragonfly = std.c;
3434pub const freebsd = std.c;
3535pub const haiku = std.c;
......@@ -41,7 +41,6 @@ pub const plan9 = @import("os/plan9.zig");
4141pub const uefi = @import("os/uefi.zig");
4242pub const wasi = @import("os/wasi.zig");
4343pub const windows = @import("os/windows.zig");
44pub const ptrace = @import("os/ptrace.zig");
4544
4645comptime {
4746 assert(@import("std") == std); // std lib tests require --zig-lib-dir
......@@ -7127,3 +7126,25 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {
71277126 else => |err| return unexpectedErrno(err),
71287127 };
71297128}
7129
7130pub const PtraceError = error{
7131 DeviceBusy,
7132 ProcessNotFound,
7133 PermissionDenied,
7134} || UnexpectedError;
7135
7136/// TODO on other OSes
7137pub fn ptrace(request: i32, pid: pid_t, addr: ?[*]u8, signal: i32) PtraceError!void {
7138 switch (builtin.os.tag) {
7139 .macos, .ios, .tvos, .watchos => {},
7140 else => @compileError("TODO implement ptrace"),
7141 }
7142 return switch (errno(system.ptrace(request, pid, addr, signal))) {
7143 .SUCCESS => {},
7144 .SRCH => error.ProcessNotFound,
7145 .INVAL => unreachable,
7146 .PERM => error.PermissionDenied,
7147 .BUSY => error.DeviceBusy,
7148 else => |err| return unexpectedErrno(err),
7149 };
7150}
lib/std/os/darwin.zig deleted-540
......@@ -1,540 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const log = std.log;
4const mem = std.mem;
5
6pub const cssm = @import("darwin/cssm.zig");
7
8pub usingnamespace std.c;
9pub usingnamespace mach_task;
10
11const mach_task = if (builtin.target.isDarwin()) struct {
12 pub const MachError = error{
13 /// Not enough permissions held to perform the requested kernel
14 /// call.
15 PermissionDenied,
16 /// Kernel returned an unhandled and unexpected error code.
17 /// This is a catch-all for any yet unobserved kernel response
18 /// to some Mach message.
19 Unexpected,
20 };
21
22 pub const MachTask = extern struct {
23 port: std.c.mach_port_name_t,
24
25 pub fn isValid(self: MachTask) bool {
26 return self.port != std.c.TASK_NULL;
27 }
28
29 pub fn pidForTask(self: MachTask) MachError!std.os.pid_t {
30 var pid: std.os.pid_t = undefined;
31 switch (std.c.getKernError(std.c.pid_for_task(self.port, &pid))) {
32 .SUCCESS => return pid,
33 .FAILURE => return error.PermissionDenied,
34 else => |err| {
35 log.err("pid_for_task kernel call failed with error code: {s}", .{@tagName(err)});
36 return error.Unexpected;
37 },
38 }
39 }
40
41 pub fn allocatePort(self: MachTask, right: std.c.MACH_PORT_RIGHT) MachError!MachTask {
42 var out_port: std.c.mach_port_name_t = undefined;
43 switch (std.c.getKernError(std.c.mach_port_allocate(
44 self.port,
45 @enumToInt(right),
46 &out_port,
47 ))) {
48 .SUCCESS => return .{ .port = out_port },
49 .FAILURE => return error.PermissionDenied,
50 else => |err| {
51 log.err("mach_task_allocate kernel call failed with error code: {s}", .{@tagName(err)});
52 return error.Unexpected;
53 },
54 }
55 }
56
57 pub fn deallocatePort(self: MachTask, port: MachTask) void {
58 _ = std.c.getKernError(std.c.mach_port_deallocate(self.port, port.port));
59 }
60
61 pub fn insertRight(self: MachTask, port: MachTask, msg: std.c.MACH_MSG_TYPE) !void {
62 switch (std.c.getKernError(std.c.mach_port_insert_right(
63 self.port,
64 port.port,
65 port.port,
66 @enumToInt(msg),
67 ))) {
68 .SUCCESS => return,
69 .FAILURE => return error.PermissionDenied,
70 else => |err| {
71 log.err("mach_port_insert_right kernel call failed with error code: {s}", .{@tagName(err)});
72 return error.Unexpected;
73 },
74 }
75 }
76
77 pub const PortInfo = struct {
78 mask: std.c.exception_mask_t,
79 masks: [std.c.EXC_TYPES_COUNT]std.c.exception_mask_t,
80 ports: [std.c.EXC_TYPES_COUNT]std.c.mach_port_t,
81 behaviors: [std.c.EXC_TYPES_COUNT]std.c.exception_behavior_t,
82 flavors: [std.c.EXC_TYPES_COUNT]std.c.thread_state_flavor_t,
83 count: std.c.mach_msg_type_number_t,
84 };
85
86 pub fn getExceptionPorts(self: MachTask, mask: std.c.exception_mask_t) !PortInfo {
87 var info = PortInfo{
88 .mask = mask,
89 .masks = undefined,
90 .ports = undefined,
91 .behaviors = undefined,
92 .flavors = undefined,
93 .count = 0,
94 };
95 info.count = info.ports.len / @sizeOf(std.c.mach_port_t);
96
97 switch (std.c.getKernError(std.c.task_get_exception_ports(
98 self.port,
99 info.mask,
100 &info.masks,
101 &info.count,
102 &info.ports,
103 &info.behaviors,
104 &info.flavors,
105 ))) {
106 .SUCCESS => return info,
107 .FAILURE => return error.PermissionDenied,
108 else => |err| {
109 log.err("task_get_exception_ports kernel call failed with error code: {s}", .{@tagName(err)});
110 return error.Unexpected;
111 },
112 }
113 }
114
115 pub fn setExceptionPorts(
116 self: MachTask,
117 mask: std.c.exception_mask_t,
118 new_port: MachTask,
119 behavior: std.c.exception_behavior_t,
120 new_flavor: std.c.thread_state_flavor_t,
121 ) !void {
122 switch (std.c.getKernError(std.c.task_set_exception_ports(
123 self.port,
124 mask,
125 new_port.port,
126 behavior,
127 new_flavor,
128 ))) {
129 .SUCCESS => return,
130 .FAILURE => return error.PermissionDenied,
131 else => |err| {
132 log.err("task_set_exception_ports kernel call failed with error code: {s}", .{@tagName(err)});
133 return error.Unexpected;
134 },
135 }
136 }
137
138 pub const RegionInfo = struct {
139 pub const Tag = enum {
140 basic,
141 extended,
142 top,
143 };
144
145 base_addr: u64,
146 tag: Tag,
147 info: union {
148 basic: std.c.vm_region_basic_info_64,
149 extended: std.c.vm_region_extended_info,
150 top: std.c.vm_region_top_info,
151 },
152 };
153
154 pub fn getRegionInfo(
155 task: MachTask,
156 address: u64,
157 len: usize,
158 tag: RegionInfo.Tag,
159 ) MachError!RegionInfo {
160 var info: RegionInfo = .{
161 .base_addr = address,
162 .tag = tag,
163 .info = undefined,
164 };
165 switch (tag) {
166 .basic => info.info = .{ .basic = undefined },
167 .extended => info.info = .{ .extended = undefined },
168 .top => info.info = .{ .top = undefined },
169 }
170 var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len;
171 var objname: std.c.mach_port_t = undefined;
172 var count: std.c.mach_msg_type_number_t = switch (tag) {
173 .basic => std.c.VM_REGION_BASIC_INFO_COUNT,
174 .extended => std.c.VM_REGION_EXTENDED_INFO_COUNT,
175 .top => std.c.VM_REGION_TOP_INFO_COUNT,
176 };
177 switch (std.c.getKernError(std.c.mach_vm_region(
178 task.port,
179 &info.base_addr,
180 &base_len,
181 switch (tag) {
182 .basic => std.c.VM_REGION_BASIC_INFO_64,
183 .extended => std.c.VM_REGION_EXTENDED_INFO,
184 .top => std.c.VM_REGION_TOP_INFO,
185 },
186 switch (tag) {
187 .basic => @ptrCast(std.c.vm_region_info_t, &info.info.basic),
188 .extended => @ptrCast(std.c.vm_region_info_t, &info.info.extended),
189 .top => @ptrCast(std.c.vm_region_info_t, &info.info.top),
190 },
191 &count,
192 &objname,
193 ))) {
194 .SUCCESS => return info,
195 .FAILURE => return error.PermissionDenied,
196 else => |err| {
197 log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)});
198 return error.Unexpected;
199 },
200 }
201 }
202
203 pub const RegionSubmapInfo = struct {
204 pub const Tag = enum {
205 short,
206 full,
207 };
208
209 tag: Tag,
210 base_addr: u64,
211 info: union {
212 short: std.c.vm_region_submap_short_info_64,
213 full: std.c.vm_region_submap_info_64,
214 },
215 };
216
217 pub fn getRegionSubmapInfo(
218 task: MachTask,
219 address: u64,
220 len: usize,
221 nesting_depth: u32,
222 tag: RegionSubmapInfo.Tag,
223 ) MachError!RegionSubmapInfo {
224 var info: RegionSubmapInfo = .{
225 .base_addr = address,
226 .tag = tag,
227 .info = undefined,
228 };
229 switch (tag) {
230 .short => info.info = .{ .short = undefined },
231 .full => info.info = .{ .full = undefined },
232 }
233 var nesting = nesting_depth;
234 var base_len: std.c.mach_vm_size_t = if (len == 1) 2 else len;
235 var count: std.c.mach_msg_type_number_t = switch (tag) {
236 .short => std.c.VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
237 .full => std.c.VM_REGION_SUBMAP_INFO_COUNT_64,
238 };
239 switch (std.c.getKernError(std.c.mach_vm_region_recurse(
240 task.port,
241 &info.base_addr,
242 &base_len,
243 &nesting,
244 switch (tag) {
245 .short => @ptrCast(std.c.vm_region_recurse_info_t, &info.info.short),
246 .full => @ptrCast(std.c.vm_region_recurse_info_t, &info.info.full),
247 },
248 &count,
249 ))) {
250 .SUCCESS => return info,
251 .FAILURE => return error.PermissionDenied,
252 else => |err| {
253 log.err("mach_vm_region kernel call failed with error code: {s}", .{@tagName(err)});
254 return error.Unexpected;
255 },
256 }
257 }
258
259 pub fn getCurrProtection(task: MachTask, address: u64, len: usize) MachError!std.c.vm_prot_t {
260 const info = try task.getRegionSubmapInfo(address, len, 0, .short);
261 return info.info.short.protection;
262 }
263
264 pub fn setMaxProtection(task: MachTask, address: u64, len: usize, prot: std.c.vm_prot_t) MachError!void {
265 return task.setProtectionImpl(address, len, true, prot);
266 }
267
268 pub fn setCurrProtection(task: MachTask, address: u64, len: usize, prot: std.c.vm_prot_t) MachError!void {
269 return task.setProtectionImpl(address, len, false, prot);
270 }
271
272 fn setProtectionImpl(task: MachTask, address: u64, len: usize, set_max: bool, prot: std.c.vm_prot_t) MachError!void {
273 switch (std.c.getKernError(std.c.mach_vm_protect(task.port, address, len, @boolToInt(set_max), prot))) {
274 .SUCCESS => return,
275 .FAILURE => return error.PermissionDenied,
276 else => |err| {
277 log.err("mach_vm_protect kernel call failed with error code: {s}", .{@tagName(err)});
278 return error.Unexpected;
279 },
280 }
281 }
282
283 /// Will write to VM even if current protection attributes specifically prohibit
284 /// us from doing so, by temporarily setting protection level to a level with VM_PROT_COPY
285 /// variant, and resetting after a successful or unsuccessful write.
286 pub fn writeMemProtected(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize {
287 const curr_prot = try task.getCurrProtection(address, buf.len);
288 try task.setCurrProtection(
289 address,
290 buf.len,
291 std.c.PROT.READ | std.c.PROT.WRITE | std.c.PROT.COPY,
292 );
293 defer {
294 task.setCurrProtection(address, buf.len, curr_prot) catch {};
295 }
296 return task.writeMem(address, buf, arch);
297 }
298
299 pub fn writeMem(task: MachTask, address: u64, buf: []const u8, arch: std.Target.Cpu.Arch) MachError!usize {
300 const count = buf.len;
301 var total_written: usize = 0;
302 var curr_addr = address;
303 const page_size = try getPageSize(task); // TODO we probably can assume value here
304 var out_buf = buf[0..];
305
306 while (total_written < count) {
307 const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_written);
308 switch (std.c.getKernError(std.c.mach_vm_write(
309 task.port,
310 curr_addr,
311 @ptrToInt(out_buf.ptr),
312 @intCast(std.c.mach_msg_type_number_t, curr_size),
313 ))) {
314 .SUCCESS => {},
315 .FAILURE => return error.PermissionDenied,
316 else => |err| {
317 log.err("mach_vm_write kernel call failed with error code: {s}", .{@tagName(err)});
318 return error.Unexpected;
319 },
320 }
321
322 switch (arch) {
323 .aarch64 => {
324 var mattr_value: std.c.vm_machine_attribute_val_t = std.c.MATTR_VAL_CACHE_FLUSH;
325 switch (std.c.getKernError(std.c.vm_machine_attribute(
326 task.port,
327 curr_addr,
328 curr_size,
329 std.c.MATTR_CACHE,
330 &mattr_value,
331 ))) {
332 .SUCCESS => {},
333 .FAILURE => return error.PermissionDenied,
334 else => |err| {
335 log.err("vm_machine_attribute kernel call failed with error code: {s}", .{@tagName(err)});
336 return error.Unexpected;
337 },
338 }
339 },
340 .x86_64 => {},
341 else => unreachable,
342 }
343
344 out_buf = out_buf[curr_size..];
345 total_written += curr_size;
346 curr_addr += curr_size;
347 }
348
349 return total_written;
350 }
351
352 pub fn readMem(task: MachTask, address: u64, buf: []u8) MachError!usize {
353 const count = buf.len;
354 var total_read: usize = 0;
355 var curr_addr = address;
356 const page_size = try getPageSize(task); // TODO we probably can assume value here
357 var out_buf = buf[0..];
358
359 while (total_read < count) {
360 const curr_size = maxBytesLeftInPage(page_size, curr_addr, count - total_read);
361 var curr_bytes_read: std.c.mach_msg_type_number_t = 0;
362 var vm_memory: std.c.vm_offset_t = undefined;
363 switch (std.c.getKernError(std.c.mach_vm_read(task.port, curr_addr, curr_size, &vm_memory, &curr_bytes_read))) {
364 .SUCCESS => {},
365 .FAILURE => return error.PermissionDenied,
366 else => |err| {
367 log.err("mach_vm_read kernel call failed with error code: {s}", .{@tagName(err)});
368 return error.Unexpected;
369 },
370 }
371
372 @memcpy(out_buf[0..].ptr, @intToPtr([*]const u8, vm_memory), curr_bytes_read);
373 _ = std.c.vm_deallocate(std.c.mach_task_self(), vm_memory, curr_bytes_read);
374
375 out_buf = out_buf[curr_bytes_read..];
376 curr_addr += curr_bytes_read;
377 total_read += curr_bytes_read;
378 }
379
380 return total_read;
381 }
382
383 fn maxBytesLeftInPage(page_size: usize, address: u64, count: usize) usize {
384 var left = count;
385 if (page_size > 0) {
386 const page_offset = address % page_size;
387 const bytes_left_in_page = page_size - page_offset;
388 if (count > bytes_left_in_page) {
389 left = bytes_left_in_page;
390 }
391 }
392 return left;
393 }
394
395 fn getPageSize(task: MachTask) MachError!usize {
396 if (task.isValid()) {
397 var info_count = std.c.TASK_VM_INFO_COUNT;
398 var vm_info: std.c.task_vm_info_data_t = undefined;
399 switch (std.c.getKernError(std.c.task_info(
400 task.port,
401 std.c.TASK_VM_INFO,
402 @ptrCast(std.c.task_info_t, &vm_info),
403 &info_count,
404 ))) {
405 .SUCCESS => return @intCast(usize, vm_info.page_size),
406 else => {},
407 }
408 }
409 var page_size: std.c.vm_size_t = undefined;
410 switch (std.c.getKernError(std.c._host_page_size(std.c.mach_host_self(), &page_size))) {
411 .SUCCESS => return page_size,
412 else => |err| {
413 log.err("_host_page_size kernel call failed with error code: {s}", .{@tagName(err)});
414 return error.Unexpected;
415 },
416 }
417 }
418
419 pub fn basicTaskInfo(task: MachTask) MachError!std.c.mach_task_basic_info {
420 var info: std.c.mach_task_basic_info = undefined;
421 var count = std.c.MACH_TASK_BASIC_INFO_COUNT;
422 switch (std.c.getKernError(std.c.task_info(
423 task.port,
424 std.c.MACH_TASK_BASIC_INFO,
425 @ptrCast(std.c.task_info_t, &info),
426 &count,
427 ))) {
428 .SUCCESS => return info,
429 else => |err| {
430 log.err("task_info kernel call failed with error code: {s}", .{@tagName(err)});
431 return error.Unexpected;
432 },
433 }
434 }
435
436 pub fn @"resume"(task: MachTask) MachError!void {
437 switch (std.c.getKernError(std.c.task_resume(task.port))) {
438 .SUCCESS => {},
439 else => |err| {
440 log.err("task_resume kernel call failed with error code: {s}", .{@tagName(err)});
441 return error.Unexpected;
442 },
443 }
444 }
445
446 pub fn @"suspend"(task: MachTask) MachError!void {
447 switch (std.c.getKernError(std.c.task_suspend(task.port))) {
448 .SUCCESS => {},
449 else => |err| {
450 log.err("task_suspend kernel call failed with error code: {s}", .{@tagName(err)});
451 return error.Unexpected;
452 },
453 }
454 }
455
456 const ThreadList = struct {
457 buf: []MachThread,
458
459 pub fn deinit(list: ThreadList) void {
460 const self_task = machTaskForSelf();
461 _ = std.c.vm_deallocate(
462 self_task.port,
463 @ptrToInt(list.buf.ptr),
464 @intCast(std.c.vm_size_t, list.buf.len * @sizeOf(std.c.mach_port_t)),
465 );
466 }
467 };
468
469 pub fn getThreads(task: MachTask) MachError!ThreadList {
470 var thread_list: std.c.mach_port_array_t = undefined;
471 var thread_count: std.c.mach_msg_type_number_t = undefined;
472 switch (std.c.getKernError(std.c.task_threads(task.port, &thread_list, &thread_count))) {
473 .SUCCESS => return ThreadList{ .buf = @ptrCast([*]MachThread, thread_list)[0..thread_count] },
474 else => |err| {
475 log.err("task_threads kernel call failed with error code: {s}", .{@tagName(err)});
476 return error.Unexpected;
477 },
478 }
479 }
480 };
481
482 pub const MachThread = extern struct {
483 port: std.c.mach_port_t,
484
485 pub fn isValid(thread: MachThread) bool {
486 return thread.port != std.c.THREAD_NULL;
487 }
488
489 pub fn getBasicInfo(thread: MachThread) MachError!std.c.thread_basic_info {
490 var info: std.c.thread_basic_info = undefined;
491 var count = std.c.THREAD_BASIC_INFO_COUNT;
492 switch (std.c.getKernError(std.c.thread_info(
493 thread.port,
494 std.c.THREAD_BASIC_INFO,
495 @ptrCast(std.c.thread_info_t, &info),
496 &count,
497 ))) {
498 .SUCCESS => return info,
499 else => |err| {
500 log.err("thread_info kernel call failed with error code: {s}", .{@tagName(err)});
501 return error.Unexpected;
502 },
503 }
504 }
505
506 pub fn getIdentifierInfo(thread: MachThread) MachError!std.c.thread_identifier_info {
507 var info: std.c.thread_identifier_info = undefined;
508 var count = std.c.THREAD_IDENTIFIER_INFO_COUNT;
509 switch (std.c.getKernError(std.c.thread_info(
510 thread.port,
511 std.c.THREAD_IDENTIFIER_INFO,
512 @ptrCast(std.c.thread_info_t, &info),
513 &count,
514 ))) {
515 .SUCCESS => return info,
516 else => |err| {
517 log.err("thread_info kernel call failed with error code: {s}", .{@tagName(err)});
518 return error.Unexpected;
519 },
520 }
521 }
522 };
523
524 pub fn machTaskForPid(pid: std.os.pid_t) MachError!MachTask {
525 var port: std.c.mach_port_name_t = undefined;
526 switch (std.c.getKernError(std.c.task_for_pid(std.c.mach_task_self(), pid, &port))) {
527 .SUCCESS => {},
528 .FAILURE => return error.PermissionDenied,
529 else => |err| {
530 log.err("task_for_pid kernel call failed with error code: {s}", .{@tagName(err)});
531 return error.Unexpected;
532 },
533 }
534 return MachTask{ .port = port };
535 }
536
537 pub fn machTaskForSelf() MachTask {
538 return .{ .port = std.c.mach_task_self() };
539 }
540} else struct {};
lib/std/os/darwin/cssm.zig deleted-47
......@@ -1,47 +0,0 @@
1// Common Security Services Manager
2// Security.framework/Headers/cssm*.h
3
4// Schema Management Name Space Range Definition
5pub const DB_RECORDTYPE_SCHEMA_START = 0x00000000;
6pub const DB_RECORDTYPE_SCHEMA_END = DB_RECORDTYPE_SCHEMA_START + 4;
7
8// Open Group Application Name Space Range Definition
9pub const DB_RECORDTYPE_OPEN_GROUP_START = 0x0000000A;
10pub const DB_RECORDTYPE_OPEN_GROUP_END = DB_RECORDTYPE_OPEN_GROUP_START + 8;
11
12// Industry At Large Application Name Space Range Definition
13pub const DB_RECORDTYPE_APP_DEFINED_START = 0x80000000;
14pub const DB_RECORDTYPE_APP_DEFINED_END = 0xffffffff;
15
16pub const DB_RECORDTYPE = enum(u32) {
17 // Record Types defined in the Schema Management Name Space
18 SCHEMA_INFO = DB_RECORDTYPE_SCHEMA_START + 0,
19 SCHEMA_INDEXES = DB_RECORDTYPE_SCHEMA_START + 1,
20 SCHEMA_ATTRIBUTES = DB_RECORDTYPE_SCHEMA_START + 2,
21 SCHEMA_PARSING_MODULE = DB_RECORDTYPE_SCHEMA_START + 3,
22
23 // Record Types defined in the Open Group Application Name Space
24 ANY = DB_RECORDTYPE_OPEN_GROUP_START + 0,
25 CERT = DB_RECORDTYPE_OPEN_GROUP_START + 1,
26 CRL = DB_RECORDTYPE_OPEN_GROUP_START + 2,
27 POLICY = DB_RECORDTYPE_OPEN_GROUP_START + 3,
28 GENERIC = DB_RECORDTYPE_OPEN_GROUP_START + 4,
29 PUBLIC_KEY = DB_RECORDTYPE_OPEN_GROUP_START + 5,
30 PRIVATE_KEY = DB_RECORDTYPE_OPEN_GROUP_START + 6,
31 SYMMETRIC_KEY = DB_RECORDTYPE_OPEN_GROUP_START + 7,
32 ALL_KEYS = DB_RECORDTYPE_OPEN_GROUP_START + 8,
33
34 // AppleFileDL record types
35 GENERIC_PASSWORD = DB_RECORDTYPE_APP_DEFINED_START + 0,
36 INTERNET_PASSWORD = DB_RECORDTYPE_APP_DEFINED_START + 1,
37 APPLESHARE_PASSWORD = DB_RECORDTYPE_APP_DEFINED_START + 2,
38
39 X509_CERTIFICATE = DB_RECORDTYPE_APP_DEFINED_START + 0x1000,
40 USER_TRUST,
41 X509_CRL,
42 UNLOCK_REFERRAL,
43 EXTENDED_ATTRIBUTE,
44 METADATA = DB_RECORDTYPE_APP_DEFINED_START + 0x8000,
45
46 _,
47};
lib/std/os/ptrace.zig deleted-28
......@@ -1,28 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4const os = @import("../os.zig");
5const system = os.system;
6const errno = system.getErrno;
7const pid_t = system.pid_t;
8const unexpectedErrno = os.unexpectedErrno;
9const UnexpectedError = os.UnexpectedError;
10
11pub usingnamespace ptrace;
12
13const ptrace = if (builtin.target.isDarwin()) struct {
14 pub const PtraceError = error{
15 ProcessNotFound,
16 PermissionDenied,
17 } || UnexpectedError;
18
19 pub fn ptrace(request: i32, pid: pid_t, addr: ?[*]u8, signal: i32) PtraceError!void {
20 switch (errno(system.ptrace(request, pid, addr, signal))) {
21 .SUCCESS => return,
22 .SRCH => return error.ProcessNotFound,
23 .INVAL => unreachable,
24 .BUSY, .PERM => return error.PermissionDenied,
25 else => |err| return unexpectedErrno(err),
26 }
27 }
28} else struct {};