summaryrefslogtreecommitdiff
path: root/usr/src/uts/intel/dtrace/sdt.c
diff options
context:
space:
mode:
authorbrendan <none@none>2008-06-13 19:06:55 -0700
committerbrendan <none@none>2008-06-13 19:06:55 -0700
commit10e6dadfe63181edabc58c8f42e3c56a1cd9ec95 (patch)
tree95d4edf9068228f58a3abddd6b718c98d6f0b919 /usr/src/uts/intel/dtrace/sdt.c
parent90bcde942a3919300ffc73f98ea903b58386c395 (diff)
downloadillumos-joyent-10e6dadfe63181edabc58c8f42e3c56a1cd9ec95.tar.gz
PSARC 2008/302 DTrace IP Provider
6640019 DTrace IP Provider 6655707 sdt arguments are off-by-one past the 5th 6667364 /usr/demo/dtrace/index.html: URLs to dtrace guide chapters wrong --HG-- rename : usr/src/lib/libdtrace/common/net.d => deleted_files/usr/src/lib/libdtrace/common/net.d
Diffstat (limited to 'usr/src/uts/intel/dtrace/sdt.c')
-rw-r--r--usr/src/uts/intel/dtrace/sdt.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/usr/src/uts/intel/dtrace/sdt.c b/usr/src/uts/intel/dtrace/sdt.c
index aa31d84d14..55724b3d89 100644
--- a/usr/src/uts/intel/dtrace/sdt.c
+++ b/usr/src/uts/intel/dtrace/sdt.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,6 +33,11 @@
#include <sys/conf.h>
#include <vm/seg_kmem.h>
#include <sys/stack.h>
+#include <sys/frame.h>
+#include <sys/dtrace_impl.h>
+#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
+#include <sys/privregs.h>
#include <sys/sdt_impl.h>
#define SDT_PATCHVAL 0xf0
@@ -289,6 +294,72 @@ err:
;
}
+/*ARGSUSED*/
+uint64_t
+sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes)
+{
+ uintptr_t val;
+ struct frame *fp = (struct frame *)dtrace_getfp();
+ uintptr_t *stack;
+ int i;
+#if defined(__amd64)
+ /*
+ * A total of 6 arguments are passed via registers; any argument with
+ * index of 5 or lower is therefore in a register.
+ */
+ int inreg = 5;
+#endif
+
+ for (i = 1; i <= aframes; i++) {
+ fp = (struct frame *)(fp->fr_savfp);
+
+ if (fp->fr_savpc == (pc_t)dtrace_invop_callsite) {
+#if !defined(__amd64)
+ /*
+ * 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.
+ */
+ stack = ((uintptr_t **)&fp[1])[1];
+#else
+ /*
+ * In the case of amd64, we will use the pointer to the
+ * regs structure that was pushed when we took the
+ * trap. To get this structure, we must increment
+ * beyond the frame structure, and then again beyond
+ * the calling RIP stored in dtrace_invop(). If the
+ * argument that we're seeking is passed on the stack,
+ * 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
+ * load it directly.
+ */
+ struct regs *rp = (struct regs *)((uintptr_t)&fp[1] +
+ sizeof (uintptr_t));
+
+ if (argno <= inreg) {
+ stack = (uintptr_t *)&rp->r_rdi;
+ } else {
+ stack = (uintptr_t *)(rp->r_rsp);
+ argno -= inreg;
+ }
+#endif
+ goto load;
+ }
+ }
+
+load:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+ val = stack[argno];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+
+ return (val);
+}
+
static dtrace_pops_t sdt_pops = {
NULL,
sdt_provide_module,
@@ -297,7 +368,7 @@ static dtrace_pops_t sdt_pops = {
NULL,
NULL,
sdt_getargdesc,
- NULL,
+ sdt_getarg,
NULL,
sdt_destroy
};