summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2014-08-05 01:53:15 +0000
committermarkj <markj@FreeBSD.org>2014-08-05 01:53:15 +0000
commitf50ec1f79f9ae8ff85a176d544e21283367f96f5 (patch)
tree9ff67f5aeee3c92448948fcec9dc58a82016454b
parent7e5599557db7c93bc578adef4acdfa84baf887b2 (diff)
downloadFreeBSD-src-f50ec1f79f9ae8ff85a176d544e21283367f96f5.zip
FreeBSD-src-f50ec1f79f9ae8ff85a176d544e21283367f96f5.tar.gz
MFC r267759, r267761
r267759: Fix a couple of bugs on amd64 when fetching probe arguments beyond the first five for probes entered through a UD fault (i.e. FBT probes). Specifically, handle the fact that dtrace_invop_callsite must be 16 byte-aligned and thus may not immediately follow the call to dtrace_invop() in dtrace_invop_start(). Also fetch register arguments and the stack pointer through a struct trapframe instead of a struct reg. r267761: Fix some bugs when fetching probe arguments in i386. Firstly ensure that the 4 byte-aligned dtrace_invop_callsite can be found and that it immediately follows the call to dtrace_invop(). Secondly, fix some pointer arithmetic to account for differences between struct i386_frame and illumos' struct frame. Finally, ensure that dtrace_getarg() isn't inlined. It works by following a fixed number of frame pointers to the probe site, so inlining breaks it. PR: 191260
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h4
-rw-r--r--sys/cddl/dev/dtrace/amd64/dtrace_isa.c21
-rw-r--r--sys/cddl/dev/dtrace/i386/dtrace_asm.S8
-rw-r--r--sys/cddl/dev/dtrace/i386/dtrace_isa.c7
4 files changed, 20 insertions, 20 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
index 1577a80..f9e9689 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
@@ -1270,7 +1270,11 @@ typedef struct dtrace_toxrange {
uintptr_t dtt_limit; /* limit of toxic range */
} dtrace_toxrange_t;
+#if defined(sun)
extern uint64_t dtrace_getarg(int, int);
+#else
+extern uint64_t __noinline dtrace_getarg(int, int);
+#endif
extern greg_t dtrace_getfp(void);
extern int dtrace_getipl(void);
extern uintptr_t dtrace_caller(int);
diff --git a/sys/cddl/dev/dtrace/amd64/dtrace_isa.c b/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
index 3d3c43c..3bb7a4c 100644
--- a/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
@@ -349,7 +349,8 @@ dtrace_getarg(int arg, int aframes)
for (i = 1; i <= aframes; i++) {
fp = fp->f_frame;
- if (fp->f_retaddr == (long)dtrace_invop_callsite) {
+ if (P2ROUNDUP(fp->f_retaddr, 16) ==
+ (long)dtrace_invop_callsite) {
/*
* In the case of amd64, we will use the pointer to the
* regs structure that was pushed when we took the
@@ -363,33 +364,33 @@ dtrace_getarg(int arg, int aframes)
* we're seeking is passed in regsiters, we can just
* load it directly.
*/
- struct reg *rp = (struct reg *)((uintptr_t)&fp[1] +
- sizeof (uintptr_t));
+ struct trapframe *tf =
+ (struct trapframe *)((uintptr_t)&fp[1]);
if (arg <= inreg) {
switch (arg) {
case 0:
- stack = (uintptr_t *)&rp->r_rdi;
+ stack = (uintptr_t *)&tf->tf_rdi;
break;
case 1:
- stack = (uintptr_t *)&rp->r_rsi;
+ stack = (uintptr_t *)&tf->tf_rsi;
break;
case 2:
- stack = (uintptr_t *)&rp->r_rdx;
+ stack = (uintptr_t *)&tf->tf_rdx;
break;
case 3:
- stack = (uintptr_t *)&rp->r_rcx;
+ stack = (uintptr_t *)&tf->tf_rcx;
break;
case 4:
- stack = (uintptr_t *)&rp->r_r8;
+ stack = (uintptr_t *)&tf->tf_r8;
break;
case 5:
- stack = (uintptr_t *)&rp->r_r9;
+ stack = (uintptr_t *)&tf->tf_r9;
break;
}
arg = 0;
} else {
- stack = (uintptr_t *)(rp->r_rsp);
+ stack = (uintptr_t *)(tf->tf_rsp);
arg -= inreg;
}
goto load;
diff --git a/sys/cddl/dev/dtrace/i386/dtrace_asm.S b/sys/cddl/dev/dtrace/i386/dtrace_asm.S
index 1a92818..6338719 100644
--- a/sys/cddl/dev/dtrace/i386/dtrace_asm.S
+++ b/sys/cddl/dev/dtrace/i386/dtrace_asm.S
@@ -49,14 +49,8 @@
* dtrace_invop wants us to do.
*/
call dtrace_invop
-
- /*
- * We pushed 3 times for the arguments to dtrace_invop,
- * so we need to increment the stack pointer to get rid of
- * those values.
- */
- addl $12, %esp
ALTENTRY(dtrace_invop_callsite)
+ addl $12, %esp
cmpl $DTRACE_INVOP_PUSHL_EBP, %eax
je invop_push
cmpl $DTRACE_INVOP_POPL_EBP, %eax
diff --git a/sys/cddl/dev/dtrace/i386/dtrace_isa.c b/sys/cddl/dev/dtrace/i386/dtrace_isa.c
index 3f73a50..21a8154 100644
--- a/sys/cddl/dev/dtrace/i386/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/i386/dtrace_isa.c
@@ -413,7 +413,8 @@ dtrace_getarg(int arg, int aframes)
for (i = 1; i <= aframes; i++) {
fp = fp->f_frame;
- if (fp->f_retaddr == (long)dtrace_invop_callsite) {
+ if (P2ROUNDUP(fp->f_retaddr, 4) ==
+ (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
@@ -422,7 +423,7 @@ dtrace_getarg(int arg, int aframes)
* beyond the EIP/RIP that was pushed when the trap was
* taken -- hence the "+ 1" below.
*/
- stack = ((uintptr_t **)&fp[1])[1] + 1;
+ stack = ((uintptr_t **)&fp[1])[0] + 1;
goto load;
}
@@ -438,7 +439,7 @@ dtrace_getarg(int arg, int aframes)
*/
arg++;
- stack = (uintptr_t *)&fp[1];
+ stack = (uintptr_t *)fp + 2;
load:
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
OpenPOWER on IntegriCloud