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) {
1085610856 else => {},
1085710857};
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
1085910871pub extern "c" fn sem_init(sem: *sem_t, pshared: c_int, value: c_uint) c_int;
1086010872pub extern "c" fn sem_destroy(sem: *sem_t) c_int;
1086110873pub 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;
1130511317pub const pthread_attr_set_qos_class_np = darwin.pthread_attr_set_qos_class_np;
1130611318pub const pthread_get_qos_class_np = darwin.pthread_get_qos_class_np;
1130711319pub const pthread_set_qos_class_self_np = darwin.pthread_set_qos_class_self_np;
11308pub const ptrace = darwin.ptrace;
1130911320pub const qos_class_t = darwin.qos_class_t;
1131011321pub const task_flavor_t = darwin.task_flavor_t;
1131111322pub 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;
1134111352pub const vm_region_submap_short_info_64 = darwin.vm_region_submap_short_info_64;
1134211353pub const vm_region_top_info = darwin.vm_region_top_info;
1134311354
11344pub const caddr_t = darwin.caddr_t;
1134511355pub const exception_behavior_array_t = darwin.exception_behavior_array_t;
1134611356pub const exception_behavior_t = darwin.exception_behavior_t;
1134711357pub const exception_data_t = darwin.exception_data_t;
......@@ -11466,6 +11476,9 @@ const private = struct {
1146611476 extern "c" fn mlockall(flags: MCL) c_int;
1146711477 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
1146911482 /// macos modernized symbols.
1147011483 /// x86_64 links to $INODE64 suffix for 64-bit support.
1147111484 /// 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;
44const assert = std.debug.assert;
55const AF = std.c.AF;
66const PROT = std.c.PROT;
7const caddr_t = std.c.caddr_t;
78const fd_t = std.c.fd_t;
89const iovec_const = std.posix.iovec_const;
910const mode_t = std.c.mode_t;
......@@ -1318,8 +1319,6 @@ pub const PT = enum(c_int) {
13181319 _,
13191320};
13201321
1321pub const caddr_t = ?[*]u8;
1322
13231322pub extern "c" fn ptrace(request: PT, pid: pid_t, addr: caddr_t, data: c_int) c_int;
13241323
13251324pub const POSIX_SPAWN = packed struct(c_short) {
lib/std/c/dragonfly.zig+2
......@@ -1,6 +1,7 @@
11const std = @import("../std.zig");
22
33const SIG = std.c.SIG;
4const caddr_t = std.c.caddr_t;
45const gid_t = std.c.gid_t;
56const iovec = std.c.iovec;
67const pid_t = std.c.pid_t;
......@@ -8,6 +9,7 @@ const socklen_t = std.c.socklen_t;
89const uid_t = std.c.uid_t;
910
1011pub 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;
1113pub extern "c" fn umtx_sleep(ptr: *const volatile c_int, value: c_int, timeout: c_int) c_int;
1214pub 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;
55const PATH_MAX = std.c.PATH_MAX;
66const blkcnt_t = std.c.blkcnt_t;
77const blksize_t = std.c.blksize_t;
8const caddr_t = std.c.caddr_t;
89const dev_t = std.c.dev_t;
910const fd_t = std.c.fd_t;
1011const gid_t = std.c.gid_t;
......@@ -25,6 +26,8 @@ comptime {
2526 assert(builtin.os.tag == .freebsd); // Prevent access of std.c symbols on wrong OS.
2627}
2728
29pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
30
2831pub extern "c" fn kinfo_getfile(pid: pid_t, cntp: *c_int) ?[*]kinfo_file;
2932pub 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;
55const sigval_t = std.c.sigval_t;
66const 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
810pub const lwpid_t = i32;
911
1012pub extern "c" fn _lwp_self() lwpid_t;
lib/std/c/openbsd.zig+3
......@@ -2,6 +2,7 @@ const std = @import("../std.zig");
22const assert = std.debug.assert;
33const maxInt = std.math.maxInt;
44const builtin = @import("builtin");
5const caddr_t = std.c.caddr_t;
56const iovec = std.posix.iovec;
67const iovec_const = std.posix.iovec_const;
78const passwd = std.c.passwd;
......@@ -13,6 +14,8 @@ comptime {
1314 assert(builtin.os.tag == .openbsd); // Prevent access of std.c symbols on wrong OS.
1415}
1516
17pub extern "c" fn ptrace(request: c_int, pid: pid_t, addr: caddr_t, data: c_int) c_int;
18
1619pub const pthread_spinlock_t = extern struct {
1720 inner: ?*anyopaque = null,
1821};
lib/std/posix.zig+75-7
......@@ -7377,18 +7377,33 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!system.itimerspec {
73777377}
73787378
73797379pub const PtraceError = error{
7380 DeadLock,
73807381 DeviceBusy,
73817382 InputOutput,
7383 NameTooLong,
7384 OperationNotSupported,
7385 OutOfMemory,
73827386 ProcessNotFound,
73837387 PermissionDenied,
73847388} || UnexpectedError;
73857389
7386pub fn ptrace(request: u32, pid: pid_t, addr: usize, signal: usize) PtraceError!void {
7387 if (native_os == .windows or native_os == .wasi)
7388 @compileError("Unsupported OS");
7389
7390pub fn ptrace(request: u32, pid: pid_t, addr: usize, data: usize) PtraceError!void {
73907391 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))) {
73927407 .SUCCESS => {},
73937408 .SRCH => error.ProcessNotFound,
73947409 .FAULT => unreachable,
......@@ -7400,27 +7415,80 @@ pub fn ptrace(request: u32, pid: pid_t, addr: usize, signal: usize) PtraceError!
74007415 },
74017416
74027417 .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(
74037462 @intCast(request),
74047463 pid,
74057464 @ptrFromInt(addr),
7406 @intCast(signal),
7465 @intCast(data),
74077466 ))) {
74087467 .SUCCESS => {},
74097468 .SRCH => error.ProcessNotFound,
74107469 .INVAL => unreachable,
74117470 .PERM => error.PermissionDenied,
74127471 .BUSY => error.DeviceBusy,
7472 .DEADLK => error.DeadLock,
74137473 else => |err| return unexpectedErrno(err),
74147474 },
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 ))) {
74177482 .SUCCESS => {},
74187483 .SRCH => error.ProcessNotFound,
74197484 .INVAL => unreachable,
74207485 .PERM => error.PermissionDenied,
74217486 .BUSY => error.DeviceBusy,
7487 .NOTSUP => error.OperationNotSupported,
74227488 else => |err| return unexpectedErrno(err),
74237489 },
7490
7491 else => @compileError("std.posix.ptrace unimplemented for target OS"),
74247492 };
74257493}
74267494