| author | |
| committer | |
| log | e1e414e62a86cc460ef215ea8050c953b68b6080 |
| tree | 833ddee60d5171271bb7f3f98d49c439e4e8139b |
| parent | bd242ce1ce9ef6ffb1af4432d892bf582dcdba8a |
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 | ... | @@ -296,7 +296,6 @@ set(ZIG_STAGE2_SOURCES |
| 296 | "${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig" | 296 | "${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig" |
| 297 | "${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig" | 297 | "${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig" |
| 298 | "${CMAKE_SOURCE_DIR}/lib/std/os.zig" | 298 | "${CMAKE_SOURCE_DIR}/lib/std/os.zig" |
| 299 | "${CMAKE_SOURCE_DIR}/lib/std/os/darwin.zig" | ||
| 300 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig" | 299 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig" |
| 301 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/errno/generic.zig" | 300 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/errno/generic.zig" |
| 302 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/x86_64.zig" | 301 | "${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; | ... | @@ -8,6 +8,7 @@ const iovec_const = std.os.iovec_const; |
| 8 | 8 | ||
| 9 | pub const aarch64 = @import("darwin/aarch64.zig"); | 9 | pub const aarch64 = @import("darwin/aarch64.zig"); |
| 10 | pub const x86_64 = @import("darwin/x86_64.zig"); | 10 | pub const x86_64 = @import("darwin/x86_64.zig"); |
| 11 | pub const cssm = @import("darwin/cssm.zig"); | ||
| 11 | 12 | ||
| 12 | const arch_bits = switch (native_arch) { | 13 | const arch_bits = switch (native_arch) { |
| 13 | .aarch64 => @import("darwin/aarch64.zig"), | 14 | .aarch64 => @import("darwin/aarch64.zig"), |
| ... | @@ -2179,6 +2180,14 @@ pub fn getKernError(err: kern_return_t) KernE { | ... | @@ -2179,6 +2180,14 @@ pub fn getKernError(err: kern_return_t) KernE { |
| 2179 | return @intToEnum(KernE, @truncate(u32, @intCast(usize, err))); | 2180 | return @intToEnum(KernE, @truncate(u32, @intCast(usize, err))); |
| 2180 | } | 2181 | } |
| 2181 | 2182 | ||
| 2183 | pub 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 | |||
| 2182 | /// Kernel return values | 2191 | /// Kernel return values |
| 2183 | pub const KernE = enum(u32) { | 2192 | pub const KernE = enum(u32) { |
| 2184 | SUCCESS = 0, | 2193 | SUCCESS = 0, |
| ... | @@ -3085,3 +3094,471 @@ pub const PT_DENY_ATTACH = 31; | ... | @@ -3085,3 +3094,471 @@ pub const PT_DENY_ATTACH = 31; |
| 3085 | pub const caddr_t = ?[*]u8; | 3094 | pub const caddr_t = ?[*]u8; |
| 3086 | 3095 | ||
| 3087 | pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int; | 3096 | pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int; |
| 3097 | |||
| 3098 | pub const MachError = error{ | ||
| 3099 | /// Not enough permissions held to perform the requested kernel | ||
| 3100 | /// call. | ||
| 3101 | PermissionDenied, | ||
| 3102 | } || std.os.UnexpectedError; | ||
| 3103 | |||
| 3104 | pub 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 | |||
| 3516 | pub 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 | |||
| 3552 | pub 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 | |||
| 3562 | pub 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 | ||
| 5 | pub const DB_RECORDTYPE_SCHEMA_START = 0x00000000; | ||
| 6 | pub const DB_RECORDTYPE_SCHEMA_END = DB_RECORDTYPE_SCHEMA_START + 4; | ||
| 7 | |||
| 8 | // Open Group Application Name Space Range Definition | ||
| 9 | pub const DB_RECORDTYPE_OPEN_GROUP_START = 0x0000000A; | ||
| 10 | pub const DB_RECORDTYPE_OPEN_GROUP_END = DB_RECORDTYPE_OPEN_GROUP_START + 8; | ||
| 11 | |||
| 12 | // Industry At Large Application Name Space Range Definition | ||
| 13 | pub const DB_RECORDTYPE_APP_DEFINED_START = 0x80000000; | ||
| 14 | pub const DB_RECORDTYPE_APP_DEFINED_END = 0xffffffff; | ||
| 15 | |||
| 16 | pub 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; | ... | @@ -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 = @import("os/darwin.zig"); | 32 | pub const darwin = std.c; |
| 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; |
| ... | @@ -41,7 +41,6 @@ pub const plan9 = @import("os/plan9.zig"); | ... | @@ -41,7 +41,6 @@ pub const plan9 = @import("os/plan9.zig"); |
| 41 | pub const uefi = @import("os/uefi.zig"); | 41 | pub const uefi = @import("os/uefi.zig"); |
| 42 | pub const wasi = @import("os/wasi.zig"); | 42 | pub const wasi = @import("os/wasi.zig"); |
| 43 | pub const windows = @import("os/windows.zig"); | 43 | pub const windows = @import("os/windows.zig"); |
| 44 | pub const ptrace = @import("os/ptrace.zig"); | ||
| 45 | 44 | ||
| 46 | comptime { | 45 | comptime { |
| 47 | assert(@import("std") == std); // std lib tests require --zig-lib-dir | 46 | assert(@import("std") == std); // std lib tests require --zig-lib-dir |
| ... | @@ -7127,3 +7126,25 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec { | ... | @@ -7127,3 +7126,25 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec { |
| 7127 | else => |err| return unexpectedErrno(err), | 7126 | else => |err| return unexpectedErrno(err), |
| 7128 | }; | 7127 | }; |
| 7129 | } | 7128 | } |
| 7129 | |||
| 7130 | pub const PtraceError = error{ | ||
| 7131 | DeviceBusy, | ||
| 7132 | ProcessNotFound, | ||
| 7133 | PermissionDenied, | ||
| 7134 | } || UnexpectedError; | ||
| 7135 | |||
| 7136 | /// TODO on other OSes | ||
| 7137 | pub 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const log = std.log; | ||
| 4 | const mem = std.mem; | ||
| 5 | |||
| 6 | pub const cssm = @import("darwin/cssm.zig"); | ||
| 7 | |||
| 8 | pub usingnamespace std.c; | ||
| 9 | pub usingnamespace mach_task; | ||
| 10 | |||
| 11 | const 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 | ||
| 5 | pub const DB_RECORDTYPE_SCHEMA_START = 0x00000000; | ||
| 6 | pub const DB_RECORDTYPE_SCHEMA_END = DB_RECORDTYPE_SCHEMA_START + 4; | ||
| 7 | |||
| 8 | // Open Group Application Name Space Range Definition | ||
| 9 | pub const DB_RECORDTYPE_OPEN_GROUP_START = 0x0000000A; | ||
| 10 | pub const DB_RECORDTYPE_OPEN_GROUP_END = DB_RECORDTYPE_OPEN_GROUP_START + 8; | ||
| 11 | |||
| 12 | // Industry At Large Application Name Space Range Definition | ||
| 13 | pub const DB_RECORDTYPE_APP_DEFINED_START = 0x80000000; | ||
| 14 | pub const DB_RECORDTYPE_APP_DEFINED_END = 0xffffffff; | ||
| 15 | |||
| 16 | pub 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 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | const os = @import("../os.zig"); | ||
| 5 | const system = os.system; | ||
| 6 | const errno = system.getErrno; | ||
| 7 | const pid_t = system.pid_t; | ||
| 8 | const unexpectedErrno = os.unexpectedErrno; | ||
| 9 | const UnexpectedError = os.UnexpectedError; | ||
| 10 | |||
| 11 | pub usingnamespace ptrace; | ||
| 12 | |||
| 13 | const 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 {}; | ||