Export current system call code and argument count for system call entry

and exit events. procfs stop events for system call tracing report these
values (argument count for system call entry and code for system call exit),
but ptrace() does not provide this information. (Note that while the system
call code can be determined in an ABI-specific manner during system call
entry, it is not generally available during system call exit.)

The values are exported via new fields at the end of struct ptrace_lwpinfo
available via PT_LWPINFO.

Reviewed by:	kib
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D3536
This commit is contained in:
John Baldwin 2015-09-01 22:24:54 +00:00
parent 45d4c036ec
commit 183b68f74f
4 changed files with 22 additions and 1 deletions

View File

@ -85,6 +85,8 @@ syscallenter(struct thread *td, struct syscall_args *sa)
STOPEVENT(p, S_SCE, sa->narg); STOPEVENT(p, S_SCE, sa->narg);
if (p->p_flag & P_TRACED && p->p_stops & S_PT_SCE) { if (p->p_flag & P_TRACED && p->p_stops & S_PT_SCE) {
PROC_LOCK(p); PROC_LOCK(p);
td->td_dbg_sc_code = sa->code;
td->td_dbg_sc_narg = sa->narg;
ptracestop((td), SIGTRAP); ptracestop((td), SIGTRAP);
PROC_UNLOCK(p); PROC_UNLOCK(p);
} }
@ -94,6 +96,10 @@ syscallenter(struct thread *td, struct syscall_args *sa)
* debugger modified registers or memory. * debugger modified registers or memory.
*/ */
error = (p->p_sysent->sv_fetch_syscall_args)(td, sa); error = (p->p_sysent->sv_fetch_syscall_args)(td, sa);
PROC_LOCK(p);
td->td_dbg_sc_code = sa->code;
td->td_dbg_sc_narg = sa->narg;
PROC_UNLOCK(p);
#ifdef KTRACE #ifdef KTRACE
if (KTRPOINT(td, KTR_SYSCALL)) if (KTRPOINT(td, KTR_SYSCALL))
ktrsyscall(sa->code, sa->narg, sa->args); ktrsyscall(sa->code, sa->narg, sa->args);

View File

@ -97,6 +97,8 @@ struct ptrace_lwpinfo32 {
struct siginfo32 pl_siginfo; /* siginfo for signal */ struct siginfo32 pl_siginfo; /* siginfo for signal */
char pl_tdname[MAXCOMLEN + 1]; /* LWP name. */ char pl_tdname[MAXCOMLEN + 1]; /* LWP name. */
int pl_child_pid; /* New child pid */ int pl_child_pid; /* New child pid */
u_int pl_syscall_code;
u_int pl_syscall_narg;
}; };
#endif #endif
@ -481,6 +483,8 @@ ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo); siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
strcpy(pl32->pl_tdname, pl->pl_tdname); strcpy(pl32->pl_tdname, pl->pl_tdname);
pl32->pl_child_pid = pl->pl_child_pid; pl32->pl_child_pid = pl->pl_child_pid;
pl32->pl_syscall_code = pl->pl_syscall_code;
pl32->pl_syscall_narg = pl->pl_syscall_narg;
} }
#endif /* COMPAT_FREEBSD32 */ #endif /* COMPAT_FREEBSD32 */
@ -1211,6 +1215,13 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
pl->pl_sigmask = td2->td_sigmask; pl->pl_sigmask = td2->td_sigmask;
pl->pl_siglist = td2->td_siglist; pl->pl_siglist = td2->td_siglist;
strcpy(pl->pl_tdname, td2->td_name); strcpy(pl->pl_tdname, td2->td_name);
if ((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) != 0) {
pl->pl_syscall_code = td2->td_dbg_sc_code;
pl->pl_syscall_narg = td2->td_dbg_sc_narg;
} else {
pl->pl_syscall_code = 0;
pl->pl_syscall_narg = 0;
}
#ifdef COMPAT_FREEBSD32 #ifdef COMPAT_FREEBSD32
if (wrap32) if (wrap32)
ptrace_lwpinfo_to32(pl, pl32); ptrace_lwpinfo_to32(pl, pl32);

View File

@ -174,6 +174,7 @@ struct procdesc;
struct racct; struct racct;
struct sbuf; struct sbuf;
struct sleepqueue; struct sleepqueue;
struct syscall_args;
struct td_sched; struct td_sched;
struct thread; struct thread;
struct trapframe; struct trapframe;
@ -282,6 +283,8 @@ struct thread {
int td_no_sleeping; /* (k) Sleeping disabled count. */ int td_no_sleeping; /* (k) Sleeping disabled count. */
int td_dom_rr_idx; /* (k) RR Numa domain selection. */ int td_dom_rr_idx; /* (k) RR Numa domain selection. */
void *td_su; /* (k) FFS SU private */ void *td_su; /* (k) FFS SU private */
u_int td_dbg_sc_code; /* (c) Syscall code to debugger. */
u_int td_dbg_sc_narg; /* (c) Syscall arg count to debugger.*/
#define td_endzero td_sigmask #define td_endzero td_sigmask
/* Copied during fork1() or create_thread(). */ /* Copied during fork1() or create_thread(). */
@ -979,7 +982,6 @@ void userret(struct thread *, struct trapframe *);
void cpu_exit(struct thread *); void cpu_exit(struct thread *);
void exit1(struct thread *, int, int) __dead2; void exit1(struct thread *, int, int) __dead2;
struct syscall_args;
int cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa); int cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
void cpu_fork(struct thread *, struct proc *, struct thread *, int); void cpu_fork(struct thread *, struct proc *, struct thread *, int);
void cpu_set_fork_handler(struct thread *, void (*)(void *), void *); void cpu_set_fork_handler(struct thread *, void (*)(void *), void *);

View File

@ -113,6 +113,8 @@ struct ptrace_lwpinfo {
struct __siginfo pl_siginfo; /* siginfo for signal */ struct __siginfo pl_siginfo; /* siginfo for signal */
char pl_tdname[MAXCOMLEN + 1]; /* LWP name */ char pl_tdname[MAXCOMLEN + 1]; /* LWP name */
int pl_child_pid; /* New child pid */ int pl_child_pid; /* New child pid */
u_int pl_syscall_code;
u_int pl_syscall_narg;
}; };
/* Argument structure for PT_VM_ENTRY. */ /* Argument structure for PT_VM_ENTRY. */