From: Jeremie Courreges-Anglas Subject: Re: extend ptrace(2) PT_GET_THREAD_* to include thread names To: kurt@intricatesoftware.com Cc: cjeker@diehard.n-r-g.com, mark.kettenis@xs4all.nl, pascal@stumpf.co, ports@openbsd.org, tech@openbsd.org Date: Thu, 11 Dec 2025 00:37:52 +0100 On Wed, Dec 10, 2025 at 04:41:27PM +0000, kurt@intricatesoftware.com wrote: > Instead of gdb using sysctl(2) to get thread names let's extend > ptrace(2) PT_GET_THREAD_* to include thread names. This allows > gdb to use ptrace for both thread names and thread is alive > detection. > > I'm using a new define larger then _MAXCOMLEN to avoid that > define and header from propagating in to ptrace.h as well. > > The diff for gdb to use this and remove sysctl use follows > below as well. This would be committed a few days after the > pthread change is committed. > > okay for both? Works for me and looks correct, ok jca@ I got curious and looked at what it would take to support both the old and new structure sizes, and the diff below appears to work fine. The issue is more of a problem on slower architectures where kernel and packages can stay unsynchronized for a longer time. Thoughts? Index: kern/sys_process.c =================================================================== RCS file: /home/cvs/src/sys/kern/sys_process.c,v diff -u -p -r1.106 sys_process.c --- kern/sys_process.c 17 Feb 2025 15:45:55 -0000 1.106 +++ kern/sys_process.c 10 Dec 2025 23:23:11 -0000 @@ -81,10 +81,13 @@ static inline struct process *process_tp int ptrace_ctrl(struct proc *, int, pid_t, caddr_t, int); int ptrace_ustate(struct proc *, int, pid_t, void *, int, register_t *); -int ptrace_kstate(struct proc *, int, pid_t, void *); +int ptrace_kstate(struct proc *, int, pid_t, void *, int); int global_ptrace; /* [a] permit tracing of not children */ +struct optrace_thread_state { + pid_t pts_pid; +}; /* * Process debugging system call. @@ -104,6 +107,7 @@ sys_ptrace(struct proc *p, void *v, regi void *kaddr = NULL; /* kernelspace */ int data = SCARG(uap, data); union { + struct optrace_thread_state u_opts; struct ptrace_thread_state u_pts; struct ptrace_io_desc u_piod; struct ptrace_event u_pe; @@ -144,12 +148,18 @@ sys_ptrace(struct proc *p, void *v, regi break; case PT_GET_THREAD_FIRST: mode = OUT; - size = sizeof u.u_pts; + if (data == sizeof u.u_opts) + size = sizeof u.u_opts; + else + size = sizeof u.u_pts; kstate = 1; break; case PT_GET_THREAD_NEXT: mode = IN_OUT; - size = sizeof u.u_pts; + if (data == sizeof u.u_opts) + size = sizeof u.u_opts; + else + size = sizeof u.u_pts; kstate = 1; break; case PT_GET_EVENT_MASK: @@ -267,7 +277,7 @@ sys_ptrace(struct proc *p, void *v, regi } if (kstate) - error = ptrace_kstate(p, req, pid, kaddr); + error = ptrace_kstate(p, req, pid, kaddr, data); else error = ptrace_ustate(p, req, pid, kaddr, data, retval); @@ -572,7 +582,7 @@ fail: * ptrace kernel-state requests: thread list, event mask, process state */ int -ptrace_kstate(struct proc *p, int req, pid_t pid, void *addr) +ptrace_kstate(struct proc *p, int req, pid_t pid, void *addr, int data) { struct process *tr; /* target process */ struct ptrace_event *pe = addr; @@ -605,8 +615,11 @@ ptrace_kstate(struct proc *p, int req, p if (t == NULL) pts->pts_tid = -1; - else + else { pts->pts_tid = t->p_tid + THREAD_PID_OFFSET; + if (data == sizeof *pts) + strlcpy(pts->pts_name, t->p_name, sizeof(pts->pts_name)); + } return 0; } } Index: sys/ptrace.h =================================================================== RCS file: /home/cvs/src/sys/sys/ptrace.h,v diff -u -p -r1.16 ptrace.h --- sys/ptrace.h 16 Mar 2020 11:58:46 -0000 1.16 +++ sys/ptrace.h 10 Dec 2025 20:42:35 -0000 @@ -82,8 +82,11 @@ typedef struct ptrace_state { #define PT_GET_THREAD_FIRST 15 #define PT_GET_THREAD_NEXT 16 +#define PT_PTS_NAMELEN 32 /* must be >= sizeof(p_name) in struct proc */ + struct ptrace_thread_state { pid_t pts_tid; + char pts_name[PT_PTS_NAMELEN]; }; #define PT_FIRSTMACH 32 /* for machine-specific requests */ -- jca