authorgravatar for justus@klausecker.deJustus Klausecker <justus@klausecker.de> 2025-09-13 14:12:56+02:00
committergravatar for justus@klausecker.deJustus Klausecker <justus@klausecker.de> 2025-09-13 14:35:19+02:00
log9b4cae4750ca7f2ce46286f6f55766ff95859521
tree652dec0001acec88a2b346ee310a52640e7b564e
parentbfda12efcf2f6b4bc6803f520108b7ce05636965

std.posix.ptrace: support more platforms more correctly


7 files changed, 101 insertions(+), 11 deletions(-)

lib/std/c.zig+15-2
...@@ -10856,6 +10856,18 @@ pub const pthread_threadid_np = switch (native_os) {...@@ -10856,6 +10856,18 @@ pub const pthread_threadid_np = switch (native_os) {
10856 else => {},10856 else => {},
10857};10857};
1085810858
10859pub const caddr_t = ?[*]u8;
10860
10861pub const ptrace = switch (native_os) {
10862 .linux, .serenity => private.ptrace,
10863 .macos, .ios, .tvos, .watchos, .visionos => darwin.ptrace,
10864 .dragonfly => dragonfly.ptrace,
10865 .freebsd => freebsd.ptrace,
10866 .netbsd => netbsd.ptrace,
10867 .openbsd => openbsd.ptrace,
10868 else => {},
10869};
10870
10859pub extern "c" fn sem_init(sem: *sem_t, pshared: c_int, value: c_uint) c_int;10871pub extern "c" fn sem_init(sem: *sem_t, pshared: c_int, value: c_uint) c_int;
10860pub extern "c" fn sem_destroy(sem: *sem_t) c_int;10872pub extern "c" fn sem_destroy(sem: *sem_t) c_int;
10861pub extern "c" fn sem_open(name: [*:0]const u8, flag: c_int, mode: mode_t, value: c_uint) *sem_t;10873pub extern "c" fn sem_open(name: [*:0]const u8, flag: c_int, mode: mode_t, value: c_uint) *sem_t;
...@@ -11305,7 +11317,6 @@ pub const pthread_attr_get_qos_class_np = darwin.pthread_attr_get_qos_class_np;...@@ -11305,7 +11317,6 @@ pub const pthread_attr_get_qos_class_np = darwin.pthread_attr_get_qos_class_np;
11305pub const pthread_attr_set_qos_class_np = darwin.pthread_attr_set_qos_class_np;11317pub const pthread_attr_set_qos_class_np = darwin.pthread_attr_set_qos_class_np;
11306pub const pthread_get_qos_class_np = darwin.pthread_get_qos_class_np;11318pub const pthread_get_qos_class_np = darwin.pthread_get_qos_class_np;
11307pub const pthread_set_qos_class_self_np = darwin.pthread_set_qos_class_self_np;11319pub const pthread_set_qos_class_self_np = darwin.pthread_set_qos_class_self_np;
11308pub const ptrace = darwin.ptrace;
11309pub const qos_class_t = darwin.qos_class_t;11320pub const qos_class_t = darwin.qos_class_t;
11310pub const task_flavor_t = darwin.task_flavor_t;11321pub const task_flavor_t = darwin.task_flavor_t;
11311pub const task_for_pid = darwin.task_for_pid;11322pub const task_for_pid = darwin.task_for_pid;
...@@ -11341,7 +11352,6 @@ pub const vm_region_submap_info_64 = darwin.vm_region_submap_info_64;...@@ -11341,7 +11352,6 @@ pub const vm_region_submap_info_64 = darwin.vm_region_submap_info_64;
11341pub const vm_region_submap_short_info_64 = darwin.vm_region_submap_short_info_64;11352pub const vm_region_submap_short_info_64 = darwin.vm_region_submap_short_info_64;
11342pub const vm_region_top_info = darwin.vm_region_top_info;11353pub const vm_region_top_info = darwin.vm_region_top_info;
1134311354
11344pub const caddr_t = darwin.caddr_t;
11345pub const exception_behavior_array_t = darwin.exception_behavior_array_t;11355pub const exception_behavior_array_t = darwin.exception_behavior_array_t;
11346pub const exception_behavior_t = darwin.exception_behavior_t;11356pub const exception_behavior_t = darwin.exception_behavior_t;
11347pub const exception_data_t = darwin.exception_data_t;11357pub const exception_data_t = darwin.exception_data_t;
...@@ -11466,6 +11476,9 @@ const private = struct {...@@ -11466,6 +11476,9 @@ const private = struct {
11466 extern "c" fn mlockall(flags: MCL) c_int;11476 extern "c" fn mlockall(flags: MCL) c_int;
11467 extern "c" fn munlockall() c_int;11477 extern "c" fn munlockall() c_int;
1146811478
11479 // linux and https://github.com/SerenityOS/serenity/blob/502caef9a40bccc7459f9835f2174a601106299a/Userland/Libraries/LibC/sys/ptrace.cpp
11480 extern "c" fn ptrace(request: c_int, pid: pid_t, addr: ?*anyopaque, data: ?*anyopaque) c_long;
11481
11469 /// macos modernized symbols.11482 /// macos modernized symbols.
11470 /// x86_64 links to $INODE64 suffix for 64-bit support.11483 /// x86_64 links to $INODE64 suffix for 64-bit support.
11471 /// Note these are not necessary on aarch64.11484 /// Note these are not necessary on aarch64.
lib/std/c/darwin.zig+1-2
...@@ -4,6 +4,7 @@ const native_arch = builtin.target.cpu.arch;...@@ -4,6 +4,7 @@ const native_arch = builtin.target.cpu.arch;
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const AF = std.c.AF;5const AF = std.c.AF;
6const PROT = std.c.PROT;6const PROT = std.c.PROT;
7const caddr_t = std.c.caddr_t;
7const fd_t = std.c.fd_t;8const fd_t = std.c.fd_t;
8const iovec_const = std.posix.iovec_const;9const iovec_const = std.posix.iovec_const;
9const mode_t = std.c.mode_t;10const mode_t = std.c.mode_t;
...@@ -1318,8 +1319,6 @@ pub const PT = enum(c_int) {...@@ -1318,8 +1319,6 @@ pub const PT = enum(c_int) {
1318 _,1319 _,
1319};1320};
13201321
1321pub const caddr_t = ?[*]u8;
1322
1323pub extern "c" fn ptrace(request: PT, pid: pid_t, addr: caddr_t, data: c_int) c_int;1322pub extern "c" fn ptrace(request: PT, pid: pid_t, addr: caddr_t, data: c_int) c_int;
13241323
1325pub const POSIX_SPAWN = packed struct(c_short) {1324pub const POSIX_SPAWN = packed struct(c_short) {
lib/std/c/dragonfly.zig+2
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
22
3const SIG = std.c.SIG;3const SIG = std.c.SIG;
4const caddr_t = std.c.caddr_t;
4const gid_t = std.c.gid_t;5const gid_t = std.c.gid_t;
5const iovec = std.c.iovec;6const iovec = std.c.iovec;
6const pid_t = std.c.pid_t;7const pid_t = std.c.pid_t;
...@@ -8,6 +9,7 @@ const socklen_t = std.c.socklen_t;...@@ -8,6 +9,7 @@ const socklen_t = std.c.socklen_t;
8const uid_t = std.c.uid_t;9const uid_t = std.c.uid_t;
910
10pub extern "c" fn lwp_gettid() c_int;11pub extern "c" fn lwp_gettid() c_int;
12pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
11pub extern "c" fn umtx_sleep(ptr: *const volatile c_int, value: c_int, timeout: c_int) c_int;13pub extern "c" fn umtx_sleep(ptr: *const volatile c_int, value: c_int, timeout: c_int) c_int;
12pub extern "c" fn umtx_wakeup(ptr: *const volatile c_int, count: c_int) c_int;14pub extern "c" fn umtx_wakeup(ptr: *const volatile c_int, count: c_int) c_int;
1315
lib/std/c/freebsd.zig+3
...@@ -5,6 +5,7 @@ const assert = std.debug.assert;...@@ -5,6 +5,7 @@ const assert = std.debug.assert;
5const PATH_MAX = std.c.PATH_MAX;5const PATH_MAX = std.c.PATH_MAX;
6const blkcnt_t = std.c.blkcnt_t;6const blkcnt_t = std.c.blkcnt_t;
7const blksize_t = std.c.blksize_t;7const blksize_t = std.c.blksize_t;
8const caddr_t = std.c.caddr_t;
8const dev_t = std.c.dev_t;9const dev_t = std.c.dev_t;
9const fd_t = std.c.fd_t;10const fd_t = std.c.fd_t;
10const gid_t = std.c.gid_t;11const gid_t = std.c.gid_t;
...@@ -25,6 +26,8 @@ comptime {...@@ -25,6 +26,8 @@ comptime {
25 assert(builtin.os.tag == .freebsd); // Prevent access of std.c symbols on wrong OS.26 assert(builtin.os.tag == .freebsd); // Prevent access of std.c symbols on wrong OS.
26}27}
2728
29pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
30
28pub extern "c" fn kinfo_getfile(pid: pid_t, cntp: *c_int) ?[*]kinfo_file;31pub extern "c" fn kinfo_getfile(pid: pid_t, cntp: *c_int) ?[*]kinfo_file;
29pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*off_t, fd_out: fd_t, off_out: ?*off_t, len: usize, flags: u32) usize;32pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*off_t, fd_out: fd_t, off_out: ?*off_t, len: usize, flags: u32) usize;
3033
lib/std/c/netbsd.zig+2
...@@ -5,6 +5,8 @@ const pthread_t = std.c.pthread_t;...@@ -5,6 +5,8 @@ const pthread_t = std.c.pthread_t;
5const sigval_t = std.c.sigval_t;5const sigval_t = std.c.sigval_t;
6const uid_t = std.c.uid_t;6const uid_t = std.c.uid_t;
77
8pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: ?*anyopaque, data: c_int) c_int;
9
8pub const lwpid_t = i32;10pub const lwpid_t = i32;
911
10pub extern "c" fn _lwp_self() lwpid_t;12pub extern "c" fn _lwp_self() lwpid_t;
lib/std/c/openbsd.zig+3
...@@ -2,6 +2,7 @@ const std = @import("../std.zig");...@@ -2,6 +2,7 @@ const std = @import("../std.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const maxInt = std.math.maxInt;3const maxInt = std.math.maxInt;
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const caddr_t = std.c.caddr_t;
5const iovec = std.posix.iovec;6const iovec = std.posix.iovec;
6const iovec_const = std.posix.iovec_const;7const iovec_const = std.posix.iovec_const;
7const passwd = std.c.passwd;8const passwd = std.c.passwd;
...@@ -13,6 +14,8 @@ comptime {...@@ -13,6 +14,8 @@ comptime {
13 assert(builtin.os.tag == .openbsd); // Prevent access of std.c symbols on wrong OS.14 assert(builtin.os.tag == .openbsd); // Prevent access of std.c symbols on wrong OS.
14}15}
1516
17pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
18
16pub const pthread_spinlock_t = extern struct {19pub const pthread_spinlock_t = extern struct {
17 inner: ?*anyopaque = null,20 inner: ?*anyopaque = null,
18};21};
lib/std/posix.zig+75-7
...@@ -7377,18 +7377,33 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!system.itimerspec {...@@ -7377,18 +7377,33 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!system.itimerspec {
7377}7377}
73787378
7379pub const PtraceError = error{7379pub const PtraceError = error{
7380 DeadLock,
7380 DeviceBusy,7381 DeviceBusy,
7381 InputOutput,7382 InputOutput,
7383 NameTooLong,
7384 OperationNotSupported,
7385 OutOfMemory,
7382 ProcessNotFound,7386 ProcessNotFound,
7383 PermissionDenied,7387 PermissionDenied,
7384} || UnexpectedError;7388} || UnexpectedError;
73857389
7386pub fn ptrace(request: u32, pid: pid_t, addr: usize, signal: usize) PtraceError!void {7390pub fn ptrace(request: u32, pid: pid_t, addr: usize, data: usize) PtraceError!void {
7387 if (native_os == .windows or native_os == .wasi)
7388 @compileError("Unsupported OS");
7389
7390 return switch (native_os) {7391 return switch (native_os) {
7391 .linux => switch (errno(linux.ptrace(request, pid, addr, signal, 0))) {7392 .windows,
7393 .wasi,
7394 .emscripten,
7395 .haiku,
7396 .solaris,
7397 .illumos,
7398 .plan9,
7399 => @compileError("ptrace unsupported by target OS"),
7400
7401 .linux => switch (errno(if (builtin.link_libc) std.c.ptrace(
7402 @intCast(request),
7403 pid,
7404 @ptrFromInt(addr),
7405 @ptrFromInt(data),
7406 ) else linux.ptrace(request, pid, addr, data, 0))) {
7392 .SUCCESS => {},7407 .SUCCESS => {},
7393 .SRCH => error.ProcessNotFound,7408 .SRCH => error.ProcessNotFound,
7394 .FAULT => unreachable,7409 .FAULT => unreachable,
...@@ -7400,27 +7415,80 @@ pub fn ptrace(request: u32, pid: pid_t, addr: usize, signal: usize) PtraceError!...@@ -7400,27 +7415,80 @@ pub fn ptrace(request: u32, pid: pid_t, addr: usize, signal: usize) PtraceError!
7400 },7415 },
74017416
7402 .macos, .ios, .tvos, .watchos, .visionos => switch (errno(std.c.ptrace(7417 .macos, .ios, .tvos, .watchos, .visionos => switch (errno(std.c.ptrace(
7418 @enumFromInt(request),
7419 pid,
7420 @ptrFromInt(addr),
7421 @intCast(data),
7422 ))) {
7423 .SUCCESS => {},
7424 .SRCH => error.ProcessNotFound,
7425 .INVAL => unreachable,
7426 .PERM => error.PermissionDenied,
7427 .BUSY => error.DeviceBusy,
7428 else => |err| return unexpectedErrno(err),
7429 },
7430
7431 .dragonfly => switch (errno(std.c.ptrace(
7432 @intCast(request),
7433 pid,
7434 @ptrFromInt(addr),
7435 @intCast(data),
7436 ))) {
7437 .SUCCESS => {},
7438 .SRCH => error.ProcessNotFound,
7439 .INVAL => unreachable,
7440 .PERM => error.PermissionDenied,
7441 .BUSY => error.DeviceBusy,
7442 else => |err| return unexpectedErrno(err),
7443 },
7444
7445 .freebsd => switch (errno(std.c.ptrace(
7446 @intCast(request),
7447 pid,
7448 @ptrFromInt(addr),
7449 @intCast(data),
7450 ))) {
7451 .SUCCESS => {},
7452 .SRCH => error.ProcessNotFound,
7453 .INVAL => unreachable,
7454 .PERM => error.PermissionDenied,
7455 .BUSY => error.DeviceBusy,
7456 .NOENT, .NOMEM => error.OutOfMemory,
7457 .NAMETOOLONG => error.NameTooLong,
7458 else => |err| return unexpectedErrno(err),
7459 },
7460
7461 .netbsd => switch (errno(std.c.ptrace(
7403 @intCast(request),7462 @intCast(request),
7404 pid,7463 pid,
7405 @ptrFromInt(addr),7464 @ptrFromInt(addr),
7406 @intCast(signal),7465 @intCast(data),
7407 ))) {7466 ))) {
7408 .SUCCESS => {},7467 .SUCCESS => {},
7409 .SRCH => error.ProcessNotFound,7468 .SRCH => error.ProcessNotFound,
7410 .INVAL => unreachable,7469 .INVAL => unreachable,
7411 .PERM => error.PermissionDenied,7470 .PERM => error.PermissionDenied,
7412 .BUSY => error.DeviceBusy,7471 .BUSY => error.DeviceBusy,
7472 .DEADLK => error.DeadLock,
7413 else => |err| return unexpectedErrno(err),7473 else => |err| return unexpectedErrno(err),
7414 },7474 },
74157475
7416 else => switch (errno(system.ptrace(request, pid, addr, signal))) {7476 .openbsd => switch (errno(std.c.ptrace(
7477 @intCast(request),
7478 pid,
7479 @ptrFromInt(addr),
7480 @intCast(data),
7481 ))) {
7417 .SUCCESS => {},7482 .SUCCESS => {},
7418 .SRCH => error.ProcessNotFound,7483 .SRCH => error.ProcessNotFound,
7419 .INVAL => unreachable,7484 .INVAL => unreachable,
7420 .PERM => error.PermissionDenied,7485 .PERM => error.PermissionDenied,
7421 .BUSY => error.DeviceBusy,7486 .BUSY => error.DeviceBusy,
7487 .NOTSUP => error.OperationNotSupported,
7422 else => |err| return unexpectedErrno(err),7488 else => |err| return unexpectedErrno(err),
7423 },7489 },
7490
7491 else => @compileError("std.posix.ptrace unimplemented for target OS"),
7424 };7492 };
7425}7493}
74267494