Add a thread debugging flag TDB_BOUNDARY

It indicates to a debugger that the thread is stopped at the
kernel->user exit path.

Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D37590
This commit is contained in:
Konstantin Belousov 2022-12-01 02:29:35 +02:00
parent e6feeae2f9
commit f0592b3c8d
3 changed files with 14 additions and 5 deletions

View File

@ -279,7 +279,7 @@ static void
ast_sig(struct thread *td, int tda) ast_sig(struct thread *td, int tda)
{ {
struct proc *p; struct proc *p;
int sig; int old_boundary, sig;
bool resched_sigs; bool resched_sigs;
p = td->td_proc; p = td->td_proc;
@ -321,12 +321,15 @@ ast_sig(struct thread *td, int tda)
!SIGISEMPTY(p->p_siglist)) { !SIGISEMPTY(p->p_siglist)) {
sigfastblock_fetch(td); sigfastblock_fetch(td);
PROC_LOCK(p); PROC_LOCK(p);
old_boundary = ~TDB_BOUNDARY | (td->td_dbgflags & TDB_BOUNDARY);
td->td_dbgflags |= TDB_BOUNDARY;
mtx_lock(&p->p_sigacts->ps_mtx); mtx_lock(&p->p_sigacts->ps_mtx);
while ((sig = cursig(td)) != 0) { while ((sig = cursig(td)) != 0) {
KASSERT(sig >= 0, ("sig %d", sig)); KASSERT(sig >= 0, ("sig %d", sig));
postsig(sig); postsig(sig);
} }
mtx_unlock(&p->p_sigacts->ps_mtx); mtx_unlock(&p->p_sigacts->ps_mtx);
td->td_dbgflags &= old_boundary;
PROC_UNLOCK(p); PROC_UNLOCK(p);
resched_sigs = true; resched_sigs = true;
} else { } else {

View File

@ -73,6 +73,7 @@ syscallenter(struct thread *td)
traced = (p->p_flag & P_TRACED) != 0; traced = (p->p_flag & P_TRACED) != 0;
if (__predict_false(traced || td->td_dbgflags & TDB_USERWR)) { if (__predict_false(traced || td->td_dbgflags & TDB_USERWR)) {
PROC_LOCK(p); PROC_LOCK(p);
MPASS((td->td_dbgflags & TDB_BOUNDARY) == 0);
td->td_dbgflags &= ~TDB_USERWR; td->td_dbgflags &= ~TDB_USERWR;
if (traced) if (traced)
td->td_dbgflags |= TDB_SCE; td->td_dbgflags |= TDB_SCE;
@ -201,7 +202,7 @@ syscallenter(struct thread *td)
td->td_retval[1]); td->td_retval[1]);
if (__predict_false(traced)) { if (__predict_false(traced)) {
PROC_LOCK(p); PROC_LOCK(p);
td->td_dbgflags &= ~TDB_SCE; td->td_dbgflags &= ~(TDB_SCE | TDB_BOUNDARY);
PROC_UNLOCK(p); PROC_UNLOCK(p);
} }
(p->p_sysent->sv_set_syscall_retval)(td, error); (p->p_sysent->sv_set_syscall_retval)(td, error);
@ -280,9 +281,13 @@ syscallret(struct thread *td)
*/ */
if (traced && if (traced &&
((td->td_dbgflags & (TDB_FORK | TDB_EXEC)) != 0 || ((td->td_dbgflags & (TDB_FORK | TDB_EXEC)) != 0 ||
(p->p_ptevents & PTRACE_SCX) != 0)) (p->p_ptevents & PTRACE_SCX) != 0)) {
MPASS((td->td_dbgflags & TDB_BOUNDARY) == 0);
td->td_dbgflags |= TDB_BOUNDARY;
ptracestop(td, SIGTRAP, NULL); ptracestop(td, SIGTRAP, NULL);
td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK); }
td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK |
TDB_BOUNDARY);
PROC_UNLOCK(p); PROC_UNLOCK(p);
} }
} }

View File

@ -522,7 +522,8 @@ enum {
#define TDB_FSTP 0x00001000 /* The thread is PT_ATTACH leader */ #define TDB_FSTP 0x00001000 /* The thread is PT_ATTACH leader */
#define TDB_STEP 0x00002000 /* (x86) PSL_T set for PT_STEP */ #define TDB_STEP 0x00002000 /* (x86) PSL_T set for PT_STEP */
#define TDB_SSWITCH 0x00004000 /* Suspended in ptracestop */ #define TDB_SSWITCH 0x00004000 /* Suspended in ptracestop */
#define TDB_COREDUMPREQ 0x00008000 /* Coredump request */ #define TDB_BOUNDARY 0x00008000 /* ptracestop() at boundary */
#define TDB_COREDUMPREQ 0x00010000 /* Coredump request */
/* /*
* "Private" flags kept in td_pflags: * "Private" flags kept in td_pflags: