Index: lib/libc/sys/ptrace.2 =================================================================== --- lib/libc/sys/ptrace.2 +++ lib/libc/sys/ptrace.2 @@ -2,7 +2,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd December 1, 2017 +.Dd May 22, 2018 .Dt PTRACE 2 .Os .Sh NAME @@ -606,6 +606,8 @@ is the count of array entries filled in. .It Dv PT_SETSTEP This request will turn on single stepping of the specified process. +The steeping mode is automatically turned off when the trap due to +the step is catched. .It Dv PT_CLEARSTEP This request will turn off single stepping of the specified process. .It Dv PT_SUSPEND Index: sys/amd64/amd64/machdep.c =================================================================== --- sys/amd64/amd64/machdep.c +++ sys/amd64/amd64/machdep.c @@ -1978,13 +1978,20 @@ int ptrace_single_step(struct thread *td) { - td->td_frame->tf_rflags |= PSL_T; + + if ((td->td_frame->tf_rflags & PSL_T) == 0) { + td->td_frame->tf_rflags |= PSL_T; + PROC_LOCK(td->td_proc); + td->td_dbgflags |= TDB_STEP; + PROC_UNLOCK(td->td_proc); + } return (0); } int ptrace_clear_single_step(struct thread *td) { + td->td_frame->tf_rflags &= ~PSL_T; return (0); } Index: sys/amd64/amd64/trap.c =================================================================== --- sys/amd64/amd64/trap.c +++ sys/amd64/amd64/trap.c @@ -285,8 +285,14 @@ signo = SIGTRAP; ucode = TRAP_TRACE; dr6 = rdr6(); - if (dr6 & DBREG_DR6_BS) - frame->tf_rflags &= ~PSL_T; + if ((dr6 & DBREG_DR6_BS) != 0) { + PROC_LOCK(td->td_proc); + if ((td->td_dbgflags & TDB_STEP) != 0) { + td->td_frame->tf_rflags &= ~PSL_T; + td->td_dbgflags &= ~TDB_STEP; + } + PROC_UNLOCK(td->td_proc); + } break; case T_ARITHTRAP: /* arithmetic trap */ Index: sys/i386/i386/machdep.c =================================================================== --- sys/i386/i386/machdep.c +++ sys/i386/i386/machdep.c @@ -2764,13 +2764,20 @@ int ptrace_single_step(struct thread *td) { - td->td_frame->tf_eflags |= PSL_T; + + if ((td->td_frame->tf_eflags & PSL_T) == 0) { + td->td_frame->tf_eflags |= PSL_T; + PROC_LOCK(td->td_proc); + td->td_dbgflags |= TDB_STEP; + PROC_UNLOCK(td->td_proc); + } return (0); } int ptrace_clear_single_step(struct thread *td) { + td->td_frame->tf_eflags &= ~PSL_T; return (0); } Index: sys/i386/i386/trap.c =================================================================== --- sys/i386/i386/trap.c +++ sys/i386/i386/trap.c @@ -337,8 +337,14 @@ signo = SIGTRAP; ucode = TRAP_TRACE; dr6 = rdr6(); - if (dr6 & DBREG_DR6_BS) - frame->tf_eflags &= ~PSL_T; + if ((dr6 & DBREG_DR6_BS) != 0) { + PROC_LOCK(td->td_proc); + if ((td->td_dbgflags & TDB_STEP) != 0) { + td->td_frame->tf_eflags &= ~PSL_T; + td->td_dbgflags &= ~TDB_STEP; + } + PROC_UNLOCK(td->td_proc); + } break; case T_ARITHTRAP: /* arithmetic trap */ @@ -357,7 +363,6 @@ if (frame->tf_eflags & PSL_VM) { signo = vm86_emulate((struct vm86frame *)frame); if (signo == SIGTRAP) { - type = T_TRCTRAP; load_dr6(rdr6() | 0x4000); goto user_trctrap_out; } Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -465,6 +465,7 @@ #define TDB_EXIT 0x00000400 /* Exiting LWP indicator for ptrace() */ #define TDB_VFORK 0x00000800 /* vfork indicator for ptrace() */ #define TDB_FSTP 0x00001000 /* The thread is PT_ATTACH leader */ +#define TDB_STEP 0x00002000 /* (x86) PSL_T set for PT_STEP */ /* * "Private" flags kept in td_pflags: