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:
parent
f5a077c390
commit
b43ce76c77
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user