| 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 | 296 | "${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig" |
| 297 | 297 | "${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig" |
| 298 | 298 | "${CMAKE_SOURCE_DIR}/lib/std/os.zig" |
| 299 | "${CMAKE_SOURCE_DIR}/lib/std/os/darwin.zig" | |
| 300 | 299 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig" |
| 301 | 300 | "${CMAKE_SOURCE_DIR}/lib/std/os/linux/errno/generic.zig" |
| 302 | 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 | 8 | |
| 9 | 9 | pub const aarch64 = @import("darwin/aarch64.zig"); |
| 10 | 10 | pub const x86_64 = @import("darwin/x86_64.zig"); |
| 11 | pub const cssm = @import("darwin/cssm.zig"); | |
| 11 | 12 | |
| 12 | 13 | const arch_bits = switch (native_arch) { |
| 13 | 14 | .aarch64 => @import("darwin/aarch64.zig"), |
| ... | ... | @@ -2179,6 +2180,14 @@ pub fn getKernError(err: kern_return_t) KernE { |
| 2179 | 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 | 2191 | /// Kernel return values |
| 2183 | 2192 | pub const KernE = enum(u32) { |
| 2184 | 2193 | SUCCESS = 0, |
| ... | ... | @@ -3085,3 +3094,471 @@ pub const PT_DENY_ATTACH = 31; |
| 3085 | 3094 | pub const caddr_t = ?[*]u8; |
| 3086 | 3095 | |
| 3087 | 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 | 29 | const Preopen = std.fs.wasi.Preopen; |
| 30 | 30 | const PreopenList = std.fs.wasi.PreopenList; |
| 31 | 31 | |
| 32 | pub const darwin = @import("os/darwin.zig"); | |
| 32 | pub const darwin = std.c; | |
| 33 | 33 | pub const dragonfly = std.c; |
| 34 | 34 | pub const freebsd = std.c; |
| 35 | 35 | pub const haiku = std.c; |
| ... | ... | @@ -41,7 +41,6 @@ pub const plan9 = @import("os/plan9.zig"); |
| 41 | 41 | pub const uefi = @import("os/uefi.zig"); |
| 42 | 42 | pub const wasi = @import("os/wasi.zig"); |
| 43 | 43 | pub const windows = @import("os/windows.zig"); |
| 44 | pub const ptrace = @import("os/ptrace.zig"); | |
| 45 | 44 | |
| 46 | 45 | comptime { |
| 47 | 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 | 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 {}; |