dtrace: Add a "regs" variable

This allows invop-based providers (i.e., fbt and kinst) to expose the
register file of the CPU at the point where the probe fired.  It does
not work for SDT providers because their probes are implemented as plain
function calls and so don't save registers.  It's not clear what
semantics "regs" should have for them anyway.

This is akin to "uregs", which nominally provides access to the
userspace registers.  In fact, DIF already had a DIF_VAR_REGS variable
defined, it was simply unimplemented.

Usage example: print the contents of %rdi upon each call to
amd64_syscall():

    fbt::amd64_syscall:entry {printf("%x", regs[R_RDI]);}

Note that the R_* constants are defined in /usr/lib/dtrace/regs_x86.d.
Currently there are no similar definitions for non-x86 platforms.

Reviewed by:	christos
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D36799
This commit is contained in:
Mark Johnston 2022-10-04 12:54:36 -04:00
parent cba2fa7c5b
commit bdd101c4d4
9 changed files with 65 additions and 55 deletions

View File

@ -416,6 +416,8 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_func, "void(int)" },
{ "rand", DT_IDENT_FUNC, 0, DIF_SUBR_RAND, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "int()" },
{ "regs", DT_IDENT_ARRAY, 0, DIF_VAR_REGS, DT_ATTR_STABCMN, DT_VERS_1_13,
&dt_idops_regs, NULL },
{ "rindex", DT_IDENT_FUNC, 0, DIF_SUBR_RINDEX, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "int(const char *, const char *, [int])" },
#ifdef illumos

View File

@ -3360,30 +3360,19 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
return (mstate->dtms_arg[ndx]);
#ifdef illumos
case DIF_VAR_UREGS: {
klwp_t *lwp;
if (!dtrace_priv_proc(state))
return (0);
if ((lwp = curthread->t_lwp) == NULL) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
cpu_core[curcpu].cpuc_dtrace_illval = NULL;
return (0);
}
return (dtrace_getreg(lwp->lwp_regs, ndx));
return (0);
}
#else
case DIF_VAR_REGS:
case DIF_VAR_UREGS: {
struct trapframe *tframe;
if (!dtrace_priv_proc(state))
return (0);
if ((tframe = curthread->td_frame) == NULL) {
if (v == DIF_VAR_REGS)
tframe = curthread->t_dtrace_trapframe;
else
tframe = curthread->td_frame;
if (tframe == NULL) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
cpu_core[curcpu].cpuc_dtrace_illval = 0;
return (0);
@ -3391,7 +3380,6 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
return (dtrace_getreg(tframe, ndx));
}
#endif
case DIF_VAR_CURTHREAD:
if (!dtrace_priv_proc(state))

View File

@ -27,18 +27,16 @@
* Use is subject to license terms.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/dtrace_impl.h>
#include <sys/dtrace_bsd.h>
#include <cddl/dev/dtrace/dtrace_cddl.h>
#include <machine/armreg.h>
#include <machine/clock.h>
#include <machine/frame.h>
@ -65,17 +63,20 @@ dtrace_invop_hdlr_t *dtrace_invop_hdlr;
int
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
{
struct thread *td;
dtrace_invop_hdlr_t *hdlr;
int rval;
rval = 0;
td = curthread;
td->t_dtrace_trapframe = frame;
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
return (rval);
return (0);
break;
td->t_dtrace_trapframe = NULL;
return (rval);
}
void
dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
{

View File

@ -33,12 +33,13 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/dtrace_impl.h>
#include <sys/dtrace_bsd.h>
#include <cddl/dev/dtrace/dtrace_cddl.h>
#include <machine/clock.h>
#include <machine/cpufunc.h>
#include <machine/frame.h>
@ -65,15 +66,20 @@ dtrace_invop_hdlr_t *dtrace_invop_hdlr;
int
dtrace_invop(uintptr_t addr, struct trapframe *frame, void **scratch)
{
struct thread *td;
dtrace_invop_hdlr_t *hdlr;
int rval;
td = curthread;
td->t_dtrace_trapframe = frame;
rval = 0;
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next) {
rval = hdlr->dtih_func(addr, frame, (uintptr_t)scratch);
if (rval != 0)
return (rval);
break;
}
return (0);
td->t_dtrace_trapframe = NULL;
return (rval);
}
void

View File

@ -27,18 +27,16 @@
* Use is subject to license terms.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/dtrace_impl.h>
#include <sys/dtrace_bsd.h>
#include <cddl/dev/dtrace/dtrace_cddl.h>
#include <machine/armreg.h>
#include <machine/clock.h>
#include <machine/frame.h>
@ -70,14 +68,18 @@ dtrace_invop_hdlr_t *dtrace_invop_hdlr;
int
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
{
struct thread *td;
dtrace_invop_hdlr_t *hdlr;
int rval;
rval = 0;
td = curthread;
td->t_dtrace_trapframe = frame;
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
return (rval);
return (0);
break;
td->t_dtrace_trapframe = NULL;
return (rval);
}

View File

@ -87,6 +87,7 @@ typedef struct kdtrace_thread {
void *td_dtrace_sscr; /* Saved scratch space location. */
void *td_systrace_args; /* syscall probe arguments. */
uint64_t td_fasttrap_tp_gen; /* Tracepoint hash table gen. */
struct trapframe *td_dtrace_trapframe; /* Trap frame from invop. */
} kdtrace_thread_t;
/*
@ -115,6 +116,7 @@ typedef struct kdtrace_thread {
#define t_dtrace_sscr td_dtrace->td_dtrace_sscr
#define t_dtrace_systrace_args td_dtrace->td_systrace_args
#define t_fasttrap_tp_gen td_dtrace->td_fasttrap_tp_gen
#define t_dtrace_trapframe td_dtrace->td_dtrace_trapframe
#define p_dtrace_helpers p_dtrace->p_dtrace_helpers
#define p_dtrace_count p_dtrace->p_dtrace_count
#define p_dtrace_probes p_dtrace->p_dtrace_probes

View File

@ -33,14 +33,15 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/cpuset.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/dtrace_impl.h>
#include <sys/dtrace_bsd.h>
#include <cddl/dev/dtrace/dtrace_cddl.h>
#include <machine/clock.h>
#include <machine/cpufunc.h>
#include <machine/frame.h>
@ -68,14 +69,18 @@ dtrace_invop_hdlr_t *dtrace_invop_hdlr;
int
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
{
struct thread *td;
dtrace_invop_hdlr_t *hdlr;
int rval;
rval = 0;
td = curthread;
td->t_dtrace_trapframe = frame;
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
return (rval);
return (0);
break;
td->t_dtrace_trapframe = NULL;
return (rval);
}
void

View File

@ -27,18 +27,16 @@
* Use is subject to license terms.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/dtrace_impl.h>
#include <sys/dtrace_bsd.h>
#include <cddl/dev/dtrace/dtrace_cddl.h>
#include <machine/clock.h>
#include <machine/frame.h>
#include <machine/trap.h>
@ -65,14 +63,18 @@ dtrace_invop_hdlr_t *dtrace_invop_hdlr;
int
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t arg0)
{
struct thread *td;
dtrace_invop_hdlr_t *hdlr;
int rval;
rval = 0;
td = curthread;
td->t_dtrace_trapframe = frame;
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
if ((rval = hdlr->dtih_func(addr, frame, arg0)) != 0)
return (rval);
return (0);
break;
td->t_dtrace_trapframe = NULL;
return (rval);
}
void

View File

@ -29,18 +29,16 @@
* Use is subject to license terms.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/dtrace_impl.h>
#include <sys/dtrace_bsd.h>
#include <cddl/dev/dtrace/dtrace_cddl.h>
#include <machine/vmparam.h>
#include <machine/encoding.h>
#include <machine/riscvreg.h>
@ -68,14 +66,18 @@ dtrace_invop_hdlr_t *dtrace_invop_hdlr;
int
dtrace_invop(uintptr_t addr, struct trapframe *frame)
{
struct thread *td;
dtrace_invop_hdlr_t *hdlr;
int rval;
rval = 0;
td = curthread;
td->t_dtrace_trapframe = frame;
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
if ((rval = hdlr->dtih_func(addr, frame, 0)) != 0)
return (rval);
return (0);
break;
td->t_dtrace_trapframe = NULL;
return (rval);
}
void