Index: sys/amd64/amd64/machdep.c =================================================================== --- sys/amd64/amd64/machdep.c +++ sys/amd64/amd64/machdep.c @@ -1976,15 +1976,26 @@ } int -ptrace_single_step(struct thread *td) +ptrace_single_step(struct thread *td, bool onetime) { - td->td_frame->tf_rflags |= PSL_T; + bool t_set; + + t_set = (td->td_frame->tf_rflags & PSL_T) != 0; + if (!t_set) { + td->td_frame->tf_rflags |= PSL_T; + if (onetime) { + 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 @@ -2762,15 +2762,26 @@ } int -ptrace_single_step(struct thread *td) +ptrace_single_step(struct thread *td, bool onetime) { - td->td_frame->tf_eflags |= PSL_T; + bool t_set; + + t_set = (td->td_frame->tf_eflags & PSL_T) != 0; + if (!t_set) { + td->td_frame->tf_eflags |= PSL_T; + if (onetime) { + 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/kern/sys_process.c =================================================================== --- sys/kern/sys_process.c +++ sys/kern/sys_process.c @@ -221,7 +221,7 @@ proc_sstep(struct thread *td) { - PROC_ACTION(ptrace_single_step(td)); + PROC_ACTION(ptrace_single_step(td, true)); } int @@ -950,7 +950,7 @@ case PT_SETSTEP: CTR2(KTR_PTRACE, "PT_SETSTEP: tid %d (pid %d)", td2->td_tid, p->p_pid); - error = ptrace_single_step(td2); + error = ptrace_single_step(td2, false); break; case PT_SUSPEND: @@ -1052,7 +1052,7 @@ case PT_STEP: CTR3(KTR_PTRACE, "PT_STEP: tid %d (pid %d), sig = %d", td2->td_tid, p->p_pid, data); - error = ptrace_single_step(td2); + error = ptrace_single_step(td2, true); if (error) goto out; break; 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: Index: sys/sys/ptrace.h =================================================================== --- sys/sys/ptrace.h +++ sys/sys/ptrace.h @@ -172,7 +172,7 @@ #ifdef _KERNEL int ptrace_set_pc(struct thread *_td, unsigned long _addr); -int ptrace_single_step(struct thread *_td); +int ptrace_single_step(struct thread *_td, bool onetime); int ptrace_clear_single_step(struct thread *_td); #ifdef __HAVE_PTRACE_MACHDEP