From: claudio Date: Tue, 1 Oct 2024 08:28:34 +0000 (+0000) Subject: Adjust ptrace interface to properly suport single threaded continue. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=67526adf6fb7ac2e85efea943bd9c67badb42b18;p=openbsd Adjust ptrace interface to properly suport single threaded continue. Introduce P_TRACESINGLE flag to instruct the trapped thread to not wakeup the other threads (via single_thread_clear). This must be done like this since ptrace must wake just the single thread to ensure it runs first and gets the ps_xsig value from ptrace. Modern gdb depends on this for multi-threaded processes, when a breakpoint is hit gdb fixes up the trapping instruction and then single steps over it with only that thread. After that single step gdb continues with all threads. If all threads are run like now it is possible that one of the other threads hits a breakpoint before the single step is done which results in an assertion in gdb (because that is not expected). OK mpi@ --- diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 809b07cf910..8f8ab6405f6 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.338 2024/08/10 09:18:09 jsg Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.339 2024/10/01 08:28:34 claudio Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -840,7 +840,9 @@ trapsignal(struct proc *p, int signum, u_long trapno, int code, SCHED_UNLOCK(); signum = pr->ps_xsig; - single_thread_clear(p, 0); + if ((p->p_flag & P_TRACESINGLE) == 0) + single_thread_clear(p, 0); + atomic_clearbits_int(&p->p_flag, P_TRACESINGLE); /* * If we are no longer being traced, or the parent @@ -1359,7 +1361,9 @@ cursig(struct proc *p, struct sigctx *sctx) atomic_clearbits_int(&pr->ps_siglist, mask); } - single_thread_clear(p, 0); + if ((p->p_flag & P_TRACESINGLE) == 0) + single_thread_clear(p, 0); + atomic_clearbits_int(&p->p_flag, P_TRACESINGLE); /* * If we are no longer being traced, or the parent diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 9520d0ddc79..8d9daeb1120 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_process.c,v 1.99 2024/09/30 12:32:26 claudio Exp $ */ +/* $OpenBSD: sys_process.c,v 1.100 2024/10/01 08:28:34 claudio Exp $ */ /* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */ /*- @@ -441,6 +441,13 @@ ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data) if (pid < THREAD_PID_OFFSET && tr->ps_single) t = tr->ps_single; + else if (t == tr->ps_single) + atomic_setbits_int(&t->p_flag, P_TRACESINGLE); + else { + error = EINVAL; + goto fail; + } + /* If the address parameter is not (int *)1, set the pc. */ if ((int *)addr != (int *)1) diff --git a/sys/sys/proc.h b/sys/sys/proc.h index def830f83f9..1472a167da0 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.371 2024/09/01 03:09:00 jsg Exp $ */ +/* $OpenBSD: proc.h,v 1.372 2024/10/01 08:28:34 claudio Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -436,6 +436,7 @@ struct proc { #define P_SINTR 0x00000080 /* Sleep is interruptible. */ #define P_SYSTEM 0x00000200 /* No sigs, stats or swapping. */ #define P_TIMEOUT 0x00000400 /* Timing out during sleep. */ +#define P_TRACESINGLE 0x00001000 /* Ptrace: keep single threaded. */ #define P_WEXIT 0x00002000 /* Working on exiting. */ #define P_OWEUPC 0x00008000 /* Owe proc an addupc() at next ast. */ #define P_SUSPSINGLE 0x00080000 /* Need to stop for single threading. */ @@ -446,8 +447,8 @@ struct proc { #define P_BITS \ ("\20" "\01INKTR" "\02PROFPEND" "\03ALRMPEND" "\04SIGSUSPEND" \ "\05CANTSLEEP" "\06WSLEEP" "\010SINTR" "\012SYSTEM" "\013TIMEOUT" \ - "\016WEXIT" "\020OWEUPC" "\024SUSPSINGLE" "\033THREAD" \ - "\034SUSPSIG" "\037CPUPEG") + "\015TRACESINGLE" "\016WEXIT" "\020OWEUPC" "\024SUSPSINGLE" \ + "\033THREAD" "\034SUSPSIG" "\037CPUPEG") #define THREAD_PID_OFFSET 100000