Make the second argument of dtrace_invop() a trapframe pointer.
Currently this argument is a pointer into the stack which is used by FBT to fetch the first five probe arguments. On all non-x86 architectures it's simply the trapframe address, so this change has no functional impact. On amd64 it's a pointer into the trapframe such that stack[1 .. 5] gives the first five argument registers, which are deliberately grouped together in the amd64 trapframe definition. A trapframe argument simplifies the invop handlers on !x86 and makes the x86 FBT invop handler easier to understand. Moreover, it allows for invop handlers that may want to modify the register set of the interrupted thread.
This commit is contained in:
parent
2f359d8f3e
commit
b9677d1249
@ -2398,8 +2398,9 @@ extern int dtrace_instr_size(uchar_t *instr);
|
||||
extern int dtrace_instr_size_isa(uchar_t *, model_t, int *);
|
||||
extern void dtrace_invop_callsite(void);
|
||||
#endif
|
||||
extern void dtrace_invop_add(int (*)(uintptr_t, uintptr_t *, uintptr_t));
|
||||
extern void dtrace_invop_remove(int (*)(uintptr_t, uintptr_t *, uintptr_t));
|
||||
extern void dtrace_invop_add(int (*)(uintptr_t, struct trapframe *, uintptr_t));
|
||||
extern void dtrace_invop_remove(int (*)(uintptr_t, struct trapframe *,
|
||||
uintptr_t));
|
||||
|
||||
#ifdef __sparc
|
||||
extern int dtrace_blksuword32(uintptr_t, uint32_t *, int);
|
||||
@ -2427,7 +2428,9 @@ extern void dtrace_helpers_destroy(proc_t *);
|
||||
#if defined(__i386) || defined(__amd64)
|
||||
|
||||
#define DTRACE_INVOP_PUSHL_EBP 1
|
||||
#define DTRACE_INVOP_PUSHQ_RBP DTRACE_INVOP_PUSHL_EBP
|
||||
#define DTRACE_INVOP_POPL_EBP 2
|
||||
#define DTRACE_INVOP_POPQ_RBP DTRACE_INVOP_POPL_EBP
|
||||
#define DTRACE_INVOP_LEAVE 3
|
||||
#define DTRACE_INVOP_NOP 4
|
||||
#define DTRACE_INVOP_RET 5
|
||||
|
@ -49,25 +49,25 @@ extern dtrace_id_t dtrace_probeid_error;
|
||||
extern int (*dtrace_invop_jump_addr)(struct trapframe *);
|
||||
extern void dtrace_getnanotime(struct timespec *tsp);
|
||||
|
||||
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t);
|
||||
void dtrace_invop_init(void);
|
||||
void dtrace_invop_uninit(void);
|
||||
|
||||
typedef struct dtrace_invop_hdlr {
|
||||
int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t);
|
||||
struct dtrace_invop_hdlr *dtih_next;
|
||||
} dtrace_invop_hdlr_t;
|
||||
|
||||
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
|
||||
|
||||
int
|
||||
dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
|
||||
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
int rval;
|
||||
|
||||
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
|
||||
if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0)
|
||||
if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
|
||||
return (rval);
|
||||
|
||||
return (0);
|
||||
@ -75,7 +75,7 @@ dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
|
||||
|
||||
|
||||
void
|
||||
dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
|
||||
@ -86,7 +86,7 @@ dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr, *prev;
|
||||
|
||||
@ -240,7 +240,7 @@ dtrace_invop_start(struct trapframe *frame)
|
||||
int tmp;
|
||||
int i;
|
||||
|
||||
invop = dtrace_invop(frame->tf_elr, (uintptr_t *)frame, frame->tf_elr);
|
||||
invop = dtrace_invop(frame->tf_elr, frame, frame->tf_elr);
|
||||
|
||||
tmp = (invop & LDP_STP_MASK);
|
||||
if (tmp == STP_64 || tmp == LDP_64) {
|
||||
|
@ -69,13 +69,10 @@
|
||||
*/
|
||||
movq TF_RIP(%rsp), %rdi
|
||||
decq %rdi
|
||||
movq TF_RSP(%rsp), %rsi
|
||||
movq TF_RAX(%rsp), %rdx
|
||||
pushq (%rsi)
|
||||
movq %rsp, %rsi
|
||||
movq TF_RAX(%rsp), %rdx
|
||||
call dtrace_invop
|
||||
ALTENTRY(dtrace_invop_callsite)
|
||||
addq $8, %rsp
|
||||
cmpl $DTRACE_INVOP_PUSHL_EBP, %eax
|
||||
je bp_push
|
||||
cmpl $DTRACE_INVOP_LEAVE, %eax
|
||||
|
@ -382,11 +382,10 @@ dtrace_getarg(int arg, int aframes)
|
||||
* we'll pull the true stack pointer out of the saved
|
||||
* registers and decrement our argument by the number
|
||||
* of arguments passed in registers; if the argument
|
||||
* we're seeking is passed in regsiters, we can just
|
||||
* we're seeking is passed in registers, we can just
|
||||
* load it directly.
|
||||
*/
|
||||
struct trapframe *tf = (struct trapframe *)
|
||||
((uintptr_t)&fp[1] + sizeof(uintptr_t));
|
||||
struct trapframe *tf = (struct trapframe *)&fp[1];
|
||||
|
||||
if (arg <= inreg) {
|
||||
switch (arg) {
|
||||
|
@ -46,30 +46,30 @@
|
||||
|
||||
extern void dtrace_getnanotime(struct timespec *tsp);
|
||||
|
||||
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t);
|
||||
|
||||
typedef struct dtrace_invop_hdlr {
|
||||
int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t);
|
||||
struct dtrace_invop_hdlr *dtih_next;
|
||||
} dtrace_invop_hdlr_t;
|
||||
|
||||
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
|
||||
|
||||
int
|
||||
dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
|
||||
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
int rval;
|
||||
|
||||
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
|
||||
if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0)
|
||||
if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
|
||||
return (rval);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
|
||||
@ -80,7 +80,7 @@ dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
|
||||
|
||||
|
@ -55,25 +55,25 @@ extern dtrace_id_t dtrace_probeid_error;
|
||||
extern int (*dtrace_invop_jump_addr)(struct trapframe *);
|
||||
extern void dtrace_getnanotime(struct timespec *tsp);
|
||||
|
||||
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t);
|
||||
void dtrace_invop_init(void);
|
||||
void dtrace_invop_uninit(void);
|
||||
|
||||
typedef struct dtrace_invop_hdlr {
|
||||
int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t);
|
||||
struct dtrace_invop_hdlr *dtih_next;
|
||||
} dtrace_invop_hdlr_t;
|
||||
|
||||
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
|
||||
|
||||
int
|
||||
dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
|
||||
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
int rval;
|
||||
|
||||
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
|
||||
if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0)
|
||||
if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
|
||||
return (rval);
|
||||
|
||||
return (0);
|
||||
@ -81,7 +81,7 @@ dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
|
||||
|
||||
|
||||
void
|
||||
dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
|
||||
@ -92,7 +92,7 @@ dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
|
||||
|
||||
@ -237,7 +237,7 @@ dtrace_invop_start(struct trapframe *frame)
|
||||
register_t *r0, *sp;
|
||||
int data, invop, reg, update_sp;
|
||||
|
||||
invop = dtrace_invop(frame->tf_pc, (uintptr_t *)frame, frame->tf_pc);
|
||||
invop = dtrace_invop(frame->tf_pc, frame, frame->tf_pc);
|
||||
switch (invop & DTRACE_INVOP_MASK) {
|
||||
case DTRACE_INVOP_PUSHM:
|
||||
sp = (register_t *)frame->tf_svc_sp;
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
pushl %eax /* push %eax -- may be return value */
|
||||
pushl %esp /* push stack pointer */
|
||||
addl $48, (%esp) /* adjust to incoming args */
|
||||
subl $8, (%esp) /* skip first arg and segment regs */
|
||||
pushl 40(%esp) /* push calling EIP */
|
||||
|
||||
/*
|
||||
|
@ -423,9 +423,9 @@ dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
|
||||
uint64_t
|
||||
dtrace_getarg(int arg, int aframes)
|
||||
{
|
||||
uintptr_t val;
|
||||
struct trapframe *frame;
|
||||
struct i386_frame *fp = (struct i386_frame *)dtrace_getfp();
|
||||
uintptr_t *stack;
|
||||
uintptr_t *stack, val;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= aframes; i++) {
|
||||
@ -435,13 +435,18 @@ dtrace_getarg(int arg, int aframes)
|
||||
(long)dtrace_invop_callsite) {
|
||||
/*
|
||||
* If we pass through the invalid op handler, we will
|
||||
* use the pointer that it passed to the stack as the
|
||||
* second argument to dtrace_invop() as the pointer to
|
||||
* the stack. When using this stack, we must step
|
||||
* beyond the EIP/RIP that was pushed when the trap was
|
||||
* taken -- hence the "+ 1" below.
|
||||
* use the trap frame pointer that it pushed on the
|
||||
* stack as the second argument to dtrace_invop() as
|
||||
* the pointer to the stack. When using this stack, we
|
||||
* must skip the third argument to dtrace_invop(),
|
||||
* which is included in the i386_frame.
|
||||
*/
|
||||
stack = ((uintptr_t **)&fp[1])[0] + 1;
|
||||
frame = (struct trapframe *)(((uintptr_t **)&fp[1])[0]);
|
||||
/*
|
||||
* Skip the three hardware-saved registers and the
|
||||
* return address.
|
||||
*/
|
||||
stack = (uintptr_t *)frame->tf_isp + 4;
|
||||
goto load;
|
||||
}
|
||||
|
||||
|
@ -49,30 +49,30 @@ extern uintptr_t kernelbase;
|
||||
|
||||
extern void dtrace_getnanotime(struct timespec *tsp);
|
||||
|
||||
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t);
|
||||
|
||||
typedef struct dtrace_invop_hdlr {
|
||||
int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t);
|
||||
struct dtrace_invop_hdlr *dtih_next;
|
||||
} dtrace_invop_hdlr_t;
|
||||
|
||||
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
|
||||
|
||||
int
|
||||
dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
|
||||
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
int rval;
|
||||
|
||||
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
|
||||
if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0)
|
||||
if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0)
|
||||
return (rval);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
|
||||
@ -83,7 +83,7 @@ dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
|
||||
|
||||
|
@ -48,7 +48,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
extern dtrace_id_t dtrace_probeid_error;
|
||||
|
||||
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t);
|
||||
|
||||
typedef struct dtrace_invop_hdlr {
|
||||
int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
|
||||
@ -58,7 +58,7 @@ typedef struct dtrace_invop_hdlr {
|
||||
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
|
||||
|
||||
int
|
||||
dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
|
||||
dtrace_invop(uintptr_t addr, struct trapframe *stack, uintptr_t eax)
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
int rval;
|
||||
|
@ -51,32 +51,32 @@ extern int (*dtrace_invop_jump_addr)(struct trapframe *);
|
||||
|
||||
extern void dtrace_getnanotime(struct timespec *tsp);
|
||||
|
||||
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t);
|
||||
void dtrace_invop_init(void);
|
||||
void dtrace_invop_uninit(void);
|
||||
|
||||
typedef struct dtrace_invop_hdlr {
|
||||
int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t);
|
||||
struct dtrace_invop_hdlr *dtih_next;
|
||||
} dtrace_invop_hdlr_t;
|
||||
|
||||
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
|
||||
|
||||
int
|
||||
dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t arg0)
|
||||
dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t arg0)
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
int rval;
|
||||
|
||||
for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
|
||||
if ((rval = hdlr->dtih_func(addr, stack, arg0)) != 0)
|
||||
if ((rval = hdlr->dtih_func(addr, frame, arg0)) != 0)
|
||||
return (rval);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr;
|
||||
|
||||
@ -87,7 +87,7 @@ dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
}
|
||||
|
||||
void
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
|
||||
dtrace_invop_remove(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
|
||||
{
|
||||
dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
|
||||
|
||||
@ -326,7 +326,8 @@ dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
|
||||
static int
|
||||
dtrace_invop_start(struct trapframe *frame)
|
||||
{
|
||||
switch (dtrace_invop(frame->srr0, (uintptr_t *)frame, frame->fixreg[3])) {
|
||||
|
||||
switch (dtrace_invop(frame->srr0, frame, frame->fixreg[3])) {
|
||||
case DTRACE_INVOP_JUMP:
|
||||
break;
|
||||
case DTRACE_INVOP_BCTR:
|
||||
@ -341,9 +342,7 @@ dtrace_invop_start(struct trapframe *frame)
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -46,13 +46,11 @@
|
||||
#define FBT_RETURN "return"
|
||||
|
||||
int
|
||||
fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
|
||||
fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
|
||||
{
|
||||
struct trapframe *frame;
|
||||
solaris_cpu_t *cpu;
|
||||
fbt_probe_t *fbt;
|
||||
|
||||
frame = (struct trapframe *)stack;
|
||||
cpu = &solaris_cpu[curcpu];
|
||||
fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
|
||||
|
||||
|
@ -49,9 +49,8 @@
|
||||
#define FBT_RETURN "return"
|
||||
|
||||
int
|
||||
fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
|
||||
fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
|
||||
{
|
||||
struct trapframe *frame = (struct trapframe *)stack;
|
||||
solaris_cpu_t *cpu = &solaris_cpu[curcpu];
|
||||
fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
|
||||
register_t fifthparam;
|
||||
|
@ -51,8 +51,9 @@ typedef struct fbt_probe {
|
||||
|
||||
struct linker_file;
|
||||
struct linker_symval;
|
||||
struct trapframe;
|
||||
|
||||
int fbt_invop(uintptr_t, uintptr_t *, uintptr_t);
|
||||
int fbt_invop(uintptr_t, struct trapframe *, uintptr_t);
|
||||
void fbt_patch_tracepoint(fbt_probe_t *, fbt_patchval_t);
|
||||
int fbt_provide_module_function(struct linker_file *, int,
|
||||
struct linker_symval *, void *);
|
||||
|
@ -51,9 +51,8 @@
|
||||
#define FBT_AFRAMES 7
|
||||
|
||||
int
|
||||
fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
|
||||
fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
|
||||
{
|
||||
struct trapframe *frame = (struct trapframe *)stack;
|
||||
solaris_cpu_t *cpu = &solaris_cpu[curcpu];
|
||||
fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
|
||||
uintptr_t tmp;
|
||||
|
@ -58,16 +58,40 @@
|
||||
#define FBT_RETURN "return"
|
||||
|
||||
int
|
||||
fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
|
||||
fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
|
||||
{
|
||||
solaris_cpu_t *cpu = &solaris_cpu[curcpu];
|
||||
uintptr_t stack0, stack1, stack2, stack3, stack4;
|
||||
fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
|
||||
solaris_cpu_t *cpu;
|
||||
uintptr_t *stack;
|
||||
uintptr_t arg0, arg1, arg2, arg3, arg4;
|
||||
fbt_probe_t *fbt;
|
||||
|
||||
#ifdef __amd64__
|
||||
stack = (uintptr_t *)frame->tf_rsp;
|
||||
#else
|
||||
/* Skip hardware-saved registers. */
|
||||
stack = (uintptr_t *)frame->tf_isp + 3;
|
||||
#endif
|
||||
|
||||
cpu = &solaris_cpu[curcpu];
|
||||
fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
|
||||
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
|
||||
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
|
||||
if (fbt->fbtp_roffset == 0) {
|
||||
#ifdef __amd64__
|
||||
/* fbt->fbtp_rval == DTRACE_INVOP_PUSHQ_RBP */
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
cpu->cpu_dtrace_caller = stack[0];
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
|
||||
CPU_DTRACE_BADADDR);
|
||||
|
||||
arg0 = frame->tf_rdi;
|
||||
arg1 = frame->tf_rsi;
|
||||
arg2 = frame->tf_rdx;
|
||||
arg3 = frame->tf_rcx;
|
||||
arg4 = frame->tf_r8;
|
||||
#else
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* When accessing the arguments on the stack,
|
||||
* we must protect against accessing beyond
|
||||
@ -77,16 +101,17 @@ fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
|
||||
*/
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
cpu->cpu_dtrace_caller = stack[i++];
|
||||
stack0 = stack[i++];
|
||||
stack1 = stack[i++];
|
||||
stack2 = stack[i++];
|
||||
stack3 = stack[i++];
|
||||
stack4 = stack[i++];
|
||||
arg0 = stack[i++];
|
||||
arg1 = stack[i++];
|
||||
arg2 = stack[i++];
|
||||
arg3 = stack[i++];
|
||||
arg4 = stack[i++];
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
|
||||
CPU_DTRACE_BADADDR);
|
||||
#endif
|
||||
|
||||
dtrace_probe(fbt->fbtp_id, stack0, stack1,
|
||||
stack2, stack3, stack4);
|
||||
dtrace_probe(fbt->fbtp_id, arg0, arg1,
|
||||
arg2, arg3, arg4);
|
||||
|
||||
cpu->cpu_dtrace_caller = 0;
|
||||
} else {
|
||||
@ -94,7 +119,7 @@ fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
|
||||
/*
|
||||
* On amd64, we instrument the ret, not the
|
||||
* leave. We therefore need to set the caller
|
||||
* to assure that the top frame of a stack()
|
||||
* to ensure that the top frame of a stack()
|
||||
* action is correct.
|
||||
*/
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
|
Loading…
Reference in New Issue
Block a user