Add ptrace(PT_GET_SC_ARGS) command to return debuggee' current syscall

arguments.

Reviewed by:	jhb (previous version)
Sponsored by:	The FreeBSD Foundation
MFC after:	3 weeks
Differential revision:	https://reviews.freebsd.org/D11080
This commit is contained in:
Konstantin Belousov 2017-06-12 21:15:43 +00:00
parent f5a077c390
commit b43ce76c77
3 changed files with 52 additions and 1 deletions

View File

@ -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 August 29, 2016
.Dd June 11, 2017
.Dt PTRACE 2
.Os
.Sh NAME
@ -643,6 +643,26 @@ and
.Fa data
arguments are used the same as for
.Dv PT_CONTINUE.
.It Dv PT_GET_SC_ARGS
For the thread which is stopped in either
.Dv PL_FLAG_SCE
or
.Dv PL_FLAG_SCX
state, that is, on entry or exit to a syscall,
this request fetches the syscall arguments.
.Pp
The arguments are copied out into the buffer pointed to by the
.Fa addr
pointer, sequentially.
Each syscall argument is stored as the machine word.
Kernel copies out as many arguments as the syscall accepts,
see the
.Va pl_syscall_narg
member of the
.Vt struct ptrace_lwpinfo ,
but not more than the
.Fa data
bytes in total are copied.
.It Dv PT_FOLLOW_FORK
This request controls tracing for new child processes of a traced process.
If

View File

@ -586,6 +586,7 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
struct ptrace_lwpinfo32 pl32;
struct ptrace_vm_entry32 pve32;
#endif
char args[nitems(td->td_sa.args) * sizeof(register_t)];
int ptevents;
} r;
void *addr;
@ -606,6 +607,7 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
case PT_GETFPREGS:
case PT_GETDBREGS:
case PT_LWPINFO:
case PT_GET_SC_ARGS:
break;
case PT_SETREGS:
error = COPYIN(uap->addr, &r.reg, sizeof r.reg);
@ -663,6 +665,10 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
/* NB: The size in uap->data is validated in kern_ptrace(). */
error = copyout(&r.pl, uap->addr, uap->data);
break;
case PT_GET_SC_ARGS:
error = copyout(r.args, uap->addr, MIN(uap->data,
sizeof(r.args)));
break;
}
return (error);
@ -739,6 +745,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_GET_EVENT_MASK:
case PT_SET_EVENT_MASK:
case PT_DETACH:
case PT_GET_SC_ARGS:
sx_xlock(&proctree_lock);
proctree_locked = 1;
break;
@ -1009,6 +1016,28 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
p->p_pid, p->p_ptevents, tmp);
p->p_ptevents = tmp;
break;
case PT_GET_SC_ARGS:
CTR1(KTR_PTRACE, "PT_GET_SC_ARGS: pid %d", p->p_pid);
if ((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) == 0
#ifdef COMPAT_FREEBSD32
|| (wrap32 && !safe)
#endif
) {
error = EINVAL;
break;
}
bzero(addr, sizeof(td2->td_sa.args));
#ifdef COMPAT_FREEBSD32
if (wrap32)
for (num = 0; num < nitems(td2->td_sa.args); num++)
((uint32_t *)addr)[num] = (uint32_t)
td2->td_sa.args[num];
else
#endif
bcopy(td2->td_sa.args, addr, td2->td_sa.narg *
sizeof(register_t));
break;
case PT_STEP:
case PT_CONTINUE:

View File

@ -69,6 +69,8 @@
#define PT_GET_EVENT_MASK 25 /* get mask of optional events */
#define PT_SET_EVENT_MASK 26 /* set mask of optional events */
#define PT_GET_SC_ARGS 27 /* fetch syscall args */
#define PT_GETREGS 33 /* get general-purpose registers */
#define PT_SETREGS 34 /* set general-purpose registers */
#define PT_GETFPREGS 35 /* get floating-point registers */