svn commit: r211608 - in head/sys: cddl/contrib/opensolaris/uts/common/dtrace cddl/contrib/opensolaris/uts/common/sys cddl/dev/dtrace cddl/dev/dtrace/amd64 cddl/dev/dtrace/i386 cddl/dev/systrace sys

Rui Paulo rpaulo at FreeBSD.org
Sun Aug 22 10:53:32 UTC 2010


Author: rpaulo
Date: Sun Aug 22 10:53:32 2010
New Revision: 211608
URL: http://svn.freebsd.org/changeset/base/211608

Log:
  Kernel DTrace support for:
  o uregs  (sson@)
  o ustack (sson@)
  o /dev/dtrace/helper device (needed for USDT probes)
  
  The work done by me was:
  Sponsored by:	The FreeBSD Foundation

Added:
  head/sys/cddl/dev/dtrace/amd64/regset.h   (contents, props changed)
  head/sys/cddl/dev/dtrace/i386/regset.h   (contents, props changed)
Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
  head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
  head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
  head/sys/cddl/dev/dtrace/dtrace_ioctl.c
  head/sys/cddl/dev/dtrace/dtrace_load.c
  head/sys/cddl/dev/dtrace/i386/dtrace_isa.c
  head/sys/cddl/dev/systrace/systrace.c
  head/sys/sys/sysent.h

Modified: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c	Sun Aug 22 10:40:15 2010	(r211607)
+++ head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c	Sun Aug 22 10:53:32 2010	(r211608)
@@ -551,20 +551,16 @@ static void dtrace_enabling_provide(dtra
 static int dtrace_enabling_match(dtrace_enabling_t *, int *);
 static void dtrace_enabling_matchall(void);
 static dtrace_state_t *dtrace_anon_grab(void);
-#if defined(sun)
 static uint64_t dtrace_helper(int, dtrace_mstate_t *,
     dtrace_state_t *, uint64_t, uint64_t);
 static dtrace_helpers_t *dtrace_helpers_create(proc_t *);
-#endif
 static void dtrace_buffer_drop(dtrace_buffer_t *);
 static intptr_t dtrace_buffer_reserve(dtrace_buffer_t *, size_t, size_t,
     dtrace_state_t *, dtrace_mstate_t *);
 static int dtrace_state_option(dtrace_state_t *, dtrace_optid_t,
     dtrace_optval_t);
 static int dtrace_ecb_create_enable(dtrace_probe_t *, void *);
-#if defined(sun)
 static void dtrace_helper_provider_destroy(dtrace_helper_provider_t *);
-#endif
 uint16_t dtrace_load16(uintptr_t);
 uint32_t dtrace_load32(uintptr_t);
 uint64_t dtrace_load64(uintptr_t);
@@ -2784,6 +2780,21 @@ dtrace_dif_variable(dtrace_mstate_t *mst
 		return (dtrace_getreg(lwp->lwp_regs, ndx));
 		return (0);
 	}
+#else
+	case DIF_VAR_UREGS: {
+		struct trapframe *tframe;
+
+		if (!dtrace_priv_proc(state))
+			return (0);
+
+		if ((tframe = curthread->td_frame) == NULL) {
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+			cpu_core[curcpu].cpuc_dtrace_illval = 0;
+			return (0);
+		}
+
+		return (dtrace_getreg(tframe, ndx));
+	}
 #endif
 
 	case DIF_VAR_CURTHREAD:
@@ -2839,7 +2850,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
 		}
 		return (mstate->dtms_stackdepth);
 
-#if defined(sun)
 	case DIF_VAR_USTACKDEPTH:
 		if (!dtrace_priv_proc(state))
 			return (0);
@@ -2859,7 +2869,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
 			mstate->dtms_present |= DTRACE_MSTATE_USTACKDEPTH;
 		}
 		return (mstate->dtms_ustackdepth);
-#endif
 
 	case DIF_VAR_CALLER:
 		if (!dtrace_priv_kernel(state))
@@ -2896,7 +2905,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
 		}
 		return (mstate->dtms_caller);
 
-#if defined(sun)
 	case DIF_VAR_UCALLER:
 		if (!dtrace_priv_proc(state))
 			return (0);
@@ -2920,7 +2928,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
 		}
 
 		return (mstate->dtms_ucaller);
-#endif
 
 	case DIF_VAR_PROBEPROV:
 		ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
@@ -5736,7 +5743,6 @@ dtrace_action_chill(dtrace_mstate_t *mst
 	cpu->cpu_dtrace_chilled += val;
 }
 
-#if defined(sun)
 static void
 dtrace_action_ustack(dtrace_mstate_t *mstate, dtrace_state_t *state,
     uint64_t *buf, uint64_t arg)
@@ -5849,7 +5855,6 @@ dtrace_action_ustack(dtrace_mstate_t *ms
 out:
 	mstate->dtms_scratch_ptr = old;
 }
-#endif
 
 /*
  * If you're looking for the epicenter of DTrace, you just found it.  This
@@ -6172,7 +6177,6 @@ dtrace_probe(dtrace_id_t id, uintptr_t a
 				    (uint32_t *)arg0);
 				continue;
 
-#if defined(sun)
 			case DTRACEACT_JSTACK:
 			case DTRACEACT_USTACK:
 				if (!dtrace_priv_proc(state))
@@ -6214,7 +6218,6 @@ dtrace_probe(dtrace_id_t id, uintptr_t a
 				    DTRACE_USTACK_NFRAMES(rec->dtrd_arg) + 1);
 				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 				continue;
-#endif
 
 			default:
 				break;
@@ -8141,7 +8144,6 @@ dtrace_helper_provide(dof_helper_t *dhp,
 	dtrace_enabling_matchall();
 }
 
-#if defined(sun)
 static void
 dtrace_helper_provider_remove_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid)
 {
@@ -8189,7 +8191,6 @@ dtrace_helper_provider_remove(dof_helper
 		dtrace_helper_provider_remove_one(dhp, sec, pid);
 	}
 }
-#endif
 
 /*
  * DTrace Meta Provider-to-Framework API Functions
@@ -8729,7 +8730,6 @@ dtrace_difo_validate(dtrace_difo_t *dp, 
 	return (err);
 }
 
-#if defined(sun)
 /*
  * Validate a DTrace DIF object that it is to be used as a helper.  Helpers
  * are much more constrained than normal DIFOs.  Specifically, they may
@@ -8887,7 +8887,6 @@ dtrace_difo_validate_helper(dtrace_difo_
 
 	return (err);
 }
-#endif
 
 /*
  * Returns 1 if the expression in the DIF object can be cached on a per-thread
@@ -13791,7 +13790,6 @@ dtrace_anon_property(void)
 	}
 }
 
-#if defined(sun)
 /*
  * DTrace Helper Functions
  */
@@ -13855,9 +13853,7 @@ dtrace_helper_trace(dtrace_helper_action
 		    ((uint64_t *)(uintptr_t)svar->dtsv_data)[curcpu];
 	}
 }
-#endif
 
-#if defined(sun)
 static uint64_t
 dtrace_helper(int which, dtrace_mstate_t *mstate,
     dtrace_state_t *state, uint64_t arg0, uint64_t arg1)
@@ -13865,7 +13861,7 @@ dtrace_helper(int which, dtrace_mstate_t
 	uint16_t *flags = &cpu_core[curcpu].cpuc_dtrace_flags;
 	uint64_t sarg0 = mstate->dtms_arg[0];
 	uint64_t sarg1 = mstate->dtms_arg[1];
-	uint64_t rval;
+	uint64_t rval = 0;
 	dtrace_helpers_t *helpers = curproc->p_dtrace_helpers;
 	dtrace_helper_action_t *helper;
 	dtrace_vstate_t *vstate;
@@ -14056,9 +14052,7 @@ dtrace_helper_destroygen(int gen)
 
 	return (0);
 }
-#endif
 
-#if defined(sun)
 static int
 dtrace_helper_validate(dtrace_helper_action_t *helper)
 {
@@ -14073,9 +14067,7 @@ dtrace_helper_validate(dtrace_helper_act
 
 	return (err == 0);
 }
-#endif
 
-#if defined(sun)
 static int
 dtrace_helper_action_add(int which, dtrace_ecbdesc_t *ep)
 {
@@ -14622,6 +14614,7 @@ dtrace_helpers_create(proc_t *p)
 	return (help);
 }
 
+#if defined(sun)
 static void
 dtrace_helpers_destroy(void)
 {
@@ -16466,6 +16459,7 @@ _fini(void)
 #else
 
 static d_ioctl_t	dtrace_ioctl;
+static d_ioctl_t	dtrace_ioctl_helper;
 static void		dtrace_load(void *);
 static int		dtrace_unload(void);
 #if __FreeBSD_version < 800039
@@ -16474,6 +16468,7 @@ static struct clonedevs	*dtrace_clones;	
 static eventhandler_tag	eh_tag;			/* Event handler tag. */
 #else
 static struct cdev	*dtrace_dev;
+static struct cdev	*helper_dev;
 #endif
 
 void dtrace_invop_init(void);
@@ -16488,6 +16483,13 @@ static struct cdevsw dtrace_cdevsw = {
 	.d_name		= "dtrace",
 };
 
+static struct cdevsw helper_cdevsw = {
+	.d_version	= D_VERSION,
+	.d_flags	= D_TRACKCLOSE | D_NEEDMINOR,
+	.d_ioctl	= dtrace_ioctl_helper,
+	.d_name		= "helper",
+};
+
 #include <dtrace_anon.c>
 #if __FreeBSD_version < 800039
 #include <dtrace_clone.c>

Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h	Sun Aug 22 10:40:15 2010	(r211607)
+++ head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h	Sun Aug 22 10:53:32 2010	(r211608)
@@ -1268,7 +1268,7 @@ extern void dtrace_copyout(uintptr_t, ui
 extern void dtrace_copyoutstr(uintptr_t, uintptr_t, size_t,
     volatile uint16_t *);
 extern void dtrace_getpcstack(pc_t *, int, int, uint32_t *);
-extern ulong_t dtrace_getreg(struct regs *, uint_t);
+extern ulong_t dtrace_getreg(struct trapframe *, uint_t);
 extern int dtrace_getstackdepth(int);
 extern void dtrace_getupcstack(uint64_t *, int);
 extern void dtrace_getufpstack(uint64_t *, uint64_t *, int);

Modified: head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c	Sun Aug 22 10:40:15 2010	(r211607)
+++ head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c	Sun Aug 22 10:53:32 2010	(r211608)
@@ -42,6 +42,7 @@
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
+#include "regset.h"
 
 uint8_t dtrace_fuword8_nocheck(void *);
 uint16_t dtrace_fuword16_nocheck(void *);
@@ -103,12 +104,11 @@ dtrace_getustack_common(uint64_t *pcstac
 {
 	volatile uint16_t *flags =
 	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
-	struct amd64_frame *frame;
 	int ret = 0;
 
 	ASSERT(pcstack == NULL || pcstack_limit > 0);
 
-	while (pc != 0 && sp != 0) {
+	while (pc != 0) {
 		ret++;
 		if (pcstack != NULL) {
 			*pcstack++ = (uint64_t)pc;
@@ -117,10 +117,12 @@ dtrace_getustack_common(uint64_t *pcstac
 				break;
 		}
 
-		frame = (struct amd64_frame *) sp;
+		if (sp == 0)
+			break;
 
-		pc = dtrace_fulword(&frame->f_retaddr);
-		sp = dtrace_fulword(&frame->f_frame);
+		pc = dtrace_fuword64((void *)(sp +
+			offsetof(struct amd64_frame, f_retaddr)));
+		sp = dtrace_fuword64((void *)sp);
 
 		/*
 		 * This is totally bogus:  if we faulted, we're going to clear
@@ -141,7 +143,7 @@ dtrace_getupcstack(uint64_t *pcstack, in
 {
 	proc_t *p = curproc;
 	struct trapframe *tf;
-	uintptr_t pc, sp;
+	uintptr_t pc, sp, fp;
 	volatile uint16_t *flags =
 	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
 	int n;
@@ -165,18 +167,28 @@ dtrace_getupcstack(uint64_t *pcstack, in
 		return;
 
 	pc = tf->tf_rip;
+	fp = tf->tf_rbp;
 	sp = tf->tf_rsp;
 
 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		/* 
+		 * In an entry probe.  The frame pointer has not yet been
+		 * pushed (that happens in the function prologue).  The
+		 * best approach is to add the current pc as a missing top
+		 * of stack and back the pc up to the caller, which is stored
+		 * at the current stack pointer address since the call 
+		 * instruction puts it there right before the branch.
+		 */
+
 		*pcstack++ = (uint64_t)pc;
 		pcstack_limit--;
 		if (pcstack_limit <= 0)
 			return;
 
-		pc = dtrace_fulword((void *) sp);
+		pc = dtrace_fuword64((void *) sp);
 	}
 
-	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
+	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp);
 	ASSERT(n >= 0);
 	ASSERT(n <= pcstack_limit);
 
@@ -193,7 +205,7 @@ dtrace_getustackdepth(void)
 {
 	proc_t *p = curproc;
 	struct trapframe *tf;
-	uintptr_t pc, sp;
+	uintptr_t pc, fp, sp;
 	int n = 0;
 
 	if (p == NULL || (tf = curthread->td_frame) == NULL)
@@ -203,30 +215,40 @@ dtrace_getustackdepth(void)
 		return (-1);
 
 	pc = tf->tf_rip;
+	fp = tf->tf_rbp;
 	sp = tf->tf_rsp;
 
 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
-		n++;
+		/* 
+		 * In an entry probe.  The frame pointer has not yet been
+		 * pushed (that happens in the function prologue).  The
+		 * best approach is to add the current pc as a missing top
+		 * of stack and back the pc up to the caller, which is stored
+		 * at the current stack pointer address since the call 
+		 * instruction puts it there right before the branch.
+		 */
 
-		pc = dtrace_fulword((void *) sp);
+		pc = dtrace_fuword64((void *) sp);
+		n++;
 	}
 
-	n += dtrace_getustack_common(NULL, 0, pc, sp);
+	n += dtrace_getustack_common(NULL, 0, pc, fp);
 
 	return (n);
 }
 
-#ifdef notyet
 void
 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
 {
-	klwp_t *lwp = ttolwp(curthread);
 	proc_t *p = curproc;
-	struct regs *rp;
-	uintptr_t pc, sp, oldcontext;
+	struct trapframe *tf;
+	uintptr_t pc, sp, fp;
 	volatile uint16_t *flags =
 	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
+#ifdef notyet	/* XXX signal stack */
+	uintptr_t oldcontext;
 	size_t s1, s2;
+#endif
 
 	if (*flags & CPU_DTRACE_FAULT)
 		return;
@@ -237,7 +259,7 @@ dtrace_getufpstack(uint64_t *pcstack, ui
 	/*
 	 * If there's no user context we still need to zero the stack.
 	 */
-	if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
+	if (p == NULL || (tf = curthread->td_frame) == NULL)
 		goto zero;
 
 	*pcstack++ = (uint64_t)p->p_pid;
@@ -246,12 +268,15 @@ dtrace_getufpstack(uint64_t *pcstack, ui
 	if (pcstack_limit <= 0)
 		return;
 
-	pc = rp->r_pc;
-	sp = rp->r_fp;
-	oldcontext = lwp->lwp_oldcontext;
+	pc = tf->tf_rip;
+	sp = tf->tf_rsp;
+	fp = tf->tf_rbp;
 
+#ifdef notyet /* XXX signal stack */
+	oldcontext = lwp->lwp_oldcontext;
 	s1 = sizeof (struct xframe) + 2 * sizeof (long);
 	s2 = s1 + sizeof (siginfo_t);
+#endif
 
 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
 		*pcstack++ = (uint64_t)pc;
@@ -260,19 +285,20 @@ dtrace_getufpstack(uint64_t *pcstack, ui
 		if (pcstack_limit <= 0)
 			return;
 
-		if (p->p_model == DATAMODEL_NATIVE)
-			pc = dtrace_fulword((void *)rp->r_sp);
-		else
-			pc = dtrace_fuword32((void *)rp->r_sp);
+		pc = dtrace_fuword64((void *)sp);
 	}
 
-	while (pc != 0 && sp != 0) {
+	while (pc != 0) {
 		*pcstack++ = (uint64_t)pc;
-		*fpstack++ = sp;
+		*fpstack++ = fp;
 		pcstack_limit--;
 		if (pcstack_limit <= 0)
 			break;
 
+		if (fp == 0)
+			break;
+
+#ifdef notyet /* XXX signal stack */
 		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
 			ucontext_t *ucp = (ucontext_t *)oldcontext;
 			greg_t *gregs = ucp->uc_mcontext.gregs;
@@ -281,11 +307,12 @@ dtrace_getufpstack(uint64_t *pcstack, ui
 			pc = dtrace_fulword(&gregs[REG_PC]);
 
 			oldcontext = dtrace_fulword(&ucp->uc_link);
-		} else {
-			struct xframe *fr = (struct xframe *)sp;
-
-			pc = dtrace_fulword(&fr->fr_savpc);
-			sp = dtrace_fulword(&fr->fr_savfp);
+		} else
+#endif /* XXX */
+		{
+			pc = dtrace_fuword64((void *)(fp +
+				offsetof(struct amd64_frame, f_retaddr)));
+			fp = dtrace_fuword64((void *)fp);
 		}
 
 		/*
@@ -301,9 +328,8 @@ dtrace_getufpstack(uint64_t *pcstack, ui
 
 zero:
 	while (pcstack_limit-- > 0)
-		*pcstack++ = NULL;
+		*pcstack++ = 0;
 }
-#endif
 
 /*ARGSUSED*/
 uint64_t
@@ -412,31 +438,30 @@ dtrace_getstackdepth(int aframes)
 		return depth - aframes;
 }
 
-#ifdef notyet
 ulong_t
-dtrace_getreg(struct regs *rp, uint_t reg)
+dtrace_getreg(struct trapframe *rp, uint_t reg)
 {
-#if defined(__amd64)
+	/* This table is dependent on reg.d. */
 	int regmap[] = {
-		REG_GS,		/* GS */
-		REG_FS,		/* FS */
-		REG_ES,		/* ES */
-		REG_DS,		/* DS */
-		REG_RDI,	/* EDI */
-		REG_RSI,	/* ESI */
-		REG_RBP,	/* EBP */
-		REG_RSP,	/* ESP */
-		REG_RBX,	/* EBX */
-		REG_RDX,	/* EDX */
-		REG_RCX,	/* ECX */
-		REG_RAX,	/* EAX */
-		REG_TRAPNO,	/* TRAPNO */
-		REG_ERR,	/* ERR */
-		REG_RIP,	/* EIP */
-		REG_CS,		/* CS */
-		REG_RFL,	/* EFL */
-		REG_RSP,	/* UESP */
-		REG_SS		/* SS */
+		REG_GS,		/* 0  GS */
+		REG_FS,		/* 1  FS */
+		REG_ES,		/* 2  ES */
+		REG_DS,		/* 3  DS */
+		REG_RDI,	/* 4  EDI */
+		REG_RSI,	/* 5  ESI */
+		REG_RBP,	/* 6  EBP, REG_FP */
+		REG_RSP,	/* 7  ESP */
+		REG_RBX,	/* 8  EBX, REG_R1 */
+		REG_RDX,	/* 9  EDX */
+		REG_RCX,	/* 10 ECX */
+		REG_RAX,	/* 11 EAX, REG_R0 */
+		REG_TRAPNO,	/* 12 TRAPNO */
+		REG_ERR,	/* 13 ERR */
+		REG_RIP,	/* 14 EIP, REG_PC */
+		REG_CS,		/* 15 CS */
+		REG_RFL,	/* 16 EFL, REG_PS */
+		REG_RSP,	/* 17 UESP, REG_SP */
+		REG_SS		/* 18 SS */
 	};
 
 	if (reg <= SS) {
@@ -447,77 +472,68 @@ dtrace_getreg(struct regs *rp, uint_t re
 
 		reg = regmap[reg];
 	} else {
+		/* This is dependent on reg.d. */
 		reg -= SS + 1;
 	}
 
 	switch (reg) {
 	case REG_RDI:
-		return (rp->r_rdi);
+		return (rp->tf_rdi);
 	case REG_RSI:
-		return (rp->r_rsi);
+		return (rp->tf_rsi);
 	case REG_RDX:
-		return (rp->r_rdx);
+		return (rp->tf_rdx);
 	case REG_RCX:
-		return (rp->r_rcx);
+		return (rp->tf_rcx);
 	case REG_R8:
-		return (rp->r_r8);
+		return (rp->tf_r8);
 	case REG_R9:
-		return (rp->r_r9);
+		return (rp->tf_r9);
 	case REG_RAX:
-		return (rp->r_rax);
+		return (rp->tf_rax);
 	case REG_RBX:
-		return (rp->r_rbx);
+		return (rp->tf_rbx);
 	case REG_RBP:
-		return (rp->r_rbp);
+		return (rp->tf_rbp);
 	case REG_R10:
-		return (rp->r_r10);
+		return (rp->tf_r10);
 	case REG_R11:
-		return (rp->r_r11);
+		return (rp->tf_r11);
 	case REG_R12:
-		return (rp->r_r12);
+		return (rp->tf_r12);
 	case REG_R13:
-		return (rp->r_r13);
+		return (rp->tf_r13);
 	case REG_R14:
-		return (rp->r_r14);
+		return (rp->tf_r14);
 	case REG_R15:
-		return (rp->r_r15);
+		return (rp->tf_r15);
 	case REG_DS:
-		return (rp->r_ds);
+		return (rp->tf_ds);
 	case REG_ES:
-		return (rp->r_es);
+		return (rp->tf_es);
 	case REG_FS:
-		return (rp->r_fs);
+		return (rp->tf_fs);
 	case REG_GS:
-		return (rp->r_gs);
+		return (rp->tf_gs);
 	case REG_TRAPNO:
-		return (rp->r_trapno);
+		return (rp->tf_trapno);
 	case REG_ERR:
-		return (rp->r_err);
+		return (rp->tf_err);
 	case REG_RIP:
-		return (rp->r_rip);
+		return (rp->tf_rip);
 	case REG_CS:
-		return (rp->r_cs);
+		return (rp->tf_cs);
 	case REG_SS:
-		return (rp->r_ss);
+		return (rp->tf_ss);
 	case REG_RFL:
-		return (rp->r_rfl);
+		return (rp->tf_rflags);
 	case REG_RSP:
-		return (rp->r_rsp);
+		return (rp->tf_rsp);
 	default:
 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
 		return (0);
 	}
-
-#else
-	if (reg > SS) {
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-		return (0);
-	}
-
-	return ((&rp->r_gs)[reg]);
-#endif
 }
-#endif
 
 static int
 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)

Added: head/sys/cddl/dev/dtrace/amd64/regset.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/cddl/dev/dtrace/amd64/regset.h	Sun Aug 22 10:53:32 2010	(r211608)
@@ -0,0 +1,127 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD$ 
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
+
+/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T		*/
+/*	All Rights Reserved	*/
+
+#ifndef	_REGSET_H
+#define	_REGSET_H
+
+/*
+ * #pragma ident	"@(#)regset.h	1.11	05/06/08 SMI"
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The names and offsets defined here should be specified by the
+ * AMD64 ABI suppl.
+ *
+ * We make fsbase and gsbase part of the lwp context (since they're
+ * the only way to access the full 64-bit address range via the segment
+ * registers) and thus belong here too.  However we treat them as
+ * read-only; if %fs or %gs are updated, the results of the descriptor
+ * table lookup that those updates implicitly cause will be reflected
+ * in the corresponding fsbase and/or gsbase values the next time the
+ * context can be inspected.  However it is NOT possible to override
+ * the fsbase/gsbase settings via this interface.
+ *
+ * Direct modification of the base registers (thus overriding the
+ * descriptor table base address) can be achieved with _lwp_setprivate.
+ */
+
+#define	REG_GSBASE	27
+#define	REG_FSBASE	26
+#define	REG_DS		25
+#define	REG_ES		24
+
+#define	REG_GS		23
+#define	REG_FS		22
+#define	REG_SS		21
+#define	REG_RSP		20
+#define	REG_RFL		19
+#define	REG_CS		18
+#define	REG_RIP		17
+#define	REG_ERR		16
+#define	REG_TRAPNO	15
+#define	REG_RAX		14
+#define	REG_RCX		13
+#define	REG_RDX		12
+#define	REG_RBX		11
+#define	REG_RBP		10
+#define	REG_RSI		9
+#define	REG_RDI		8
+#define	REG_R8		7
+#define	REG_R9		6
+#define	REG_R10		5
+#define	REG_R11		4
+#define	REG_R12		3
+#define	REG_R13		2
+#define	REG_R14		1
+#define	REG_R15		0
+
+/*
+ * The names and offsets defined here are specified by i386 ABI suppl.
+ */
+
+#define	SS		18	/* only stored on a privilege transition */
+#define	UESP		17	/* only stored on a privilege transition */
+#define	EFL		16
+#define	CS		15
+#define	EIP		14
+#define	ERR		13
+#define	TRAPNO		12
+#define	EAX		11
+#define	ECX		10
+#define	EDX		9
+#define	EBX		8
+#define	ESP		7
+#define	EBP		6
+#define	ESI		5
+#define	EDI		4
+#define	DS		3
+#define	ES		2
+#define	FS		1
+#define	GS		0
+
+#define REG_PC  EIP
+#define REG_FP  EBP
+#define REG_SP  UESP
+#define REG_PS  EFL
+#define REG_R0  EAX
+#define REG_R1  EDX
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _REGSET_H */

Modified: head/sys/cddl/dev/dtrace/dtrace_ioctl.c
==============================================================================
--- head/sys/cddl/dev/dtrace/dtrace_ioctl.c	Sun Aug 22 10:40:15 2010	(r211607)
+++ head/sys/cddl/dev/dtrace/dtrace_ioctl.c	Sun Aug 22 10:53:32 2010	(r211608)
@@ -27,6 +27,55 @@ SYSCTL_INT(_debug_dtrace, OID_AUTO, verb
 
 #define DTRACE_IOCTL_PRINTF(fmt, ...)	if (dtrace_verbose_ioctl) printf(fmt, ## __VA_ARGS__ )
 
+static int
+dtrace_ioctl_helper(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
+    struct thread *td)
+{
+	int rval;
+	dof_helper_t *dhp = NULL;
+	dof_hdr_t *dof = NULL;
+
+	switch (cmd) {
+	case DTRACEHIOC_ADDDOF:
+		dhp = (dof_helper_t *)addr;
+		/* XXX all because dofhp_dof is 64 bit */
+#ifdef __i386
+		addr = (caddr_t)(uint32_t)dhp->dofhp_dof;
+#else
+		addr = (caddr_t)dhp->dofhp_dof;
+#endif
+		/* FALLTHROUGH */
+	case DTRACEHIOC_ADD:
+		dof = dtrace_dof_copyin((intptr_t)addr, &rval);
+
+		if (dof == NULL)
+			return (rval);
+
+		mutex_enter(&dtrace_lock);
+		if ((rval = dtrace_helper_slurp((dof_hdr_t *)dof, dhp)) != -1) {
+			if (dhp) {
+				dhp->gen = rval;
+				copyout(dhp, addr, sizeof(*dhp));
+			}
+			rval = 0;
+		} else {
+			rval = EINVAL;
+		}
+		mutex_exit(&dtrace_lock);
+		return (rval);
+	case DTRACEHIOC_REMOVE:
+		mutex_enter(&dtrace_lock);
+		rval = dtrace_helper_destroygen((int)*addr);
+		mutex_exit(&dtrace_lock);
+
+		return (rval);
+	default:
+		break;
+	}
+
+	return (ENOTTY);
+}
+
 /* ARGSUSED */
 static int
 dtrace_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,

Modified: head/sys/cddl/dev/dtrace/dtrace_load.c
==============================================================================
--- head/sys/cddl/dev/dtrace/dtrace_load.c	Sun Aug 22 10:40:15 2010	(r211607)
+++ head/sys/cddl/dev/dtrace/dtrace_load.c	Sun Aug 22 10:53:32 2010	(r211608)
@@ -161,7 +161,10 @@ dtrace_load(void *dummy)
 	/* Setup device cloning events. */
 	eh_tag = EVENTHANDLER_REGISTER(dev_clone, dtrace_clone, 0, 1000);
 #else
-	dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "dtrace/dtrace");
+	dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
+	    "dtrace/dtrace");
+	helper_dev = make_dev(&helper_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
+	    "dtrace/helper");
 #endif
 
 	return;

Modified: head/sys/cddl/dev/dtrace/i386/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/i386/dtrace_isa.c	Sun Aug 22 10:40:15 2010	(r211607)
+++ head/sys/cddl/dev/dtrace/i386/dtrace_isa.c	Sun Aug 22 10:53:32 2010	(r211608)
@@ -33,13 +33,17 @@
 #include <sys/stack.h>
 #include <sys/pcpu.h>
 
+#include <machine/frame.h>
 #include <machine/md_var.h>
+#include <machine/pcb.h>
 #include <machine/stack.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
+#include "regset.h"
+
 extern uintptr_t kernbase;
 uintptr_t kernelbase = (uintptr_t) &kernbase;
 
@@ -100,21 +104,22 @@ dtrace_getpcstack(pc_t *pcstack, int pcs
 	}
 }
 
-#ifdef notyet
 static int
 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
     uintptr_t sp)
 {
-	klwp_t *lwp = ttolwp(curthread);
+#ifdef notyet
 	proc_t *p = curproc;
-	uintptr_t oldcontext = lwp->lwp_oldcontext;
+	uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
+	size_t s1, s2;
+#endif
 	volatile uint16_t *flags =
 	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
-	size_t s1, s2;
 	int ret = 0;
 
 	ASSERT(pcstack == NULL || pcstack_limit > 0);
 
+#ifdef notyet /* XXX signal stack. */
 	if (p->p_model == DATAMODEL_NATIVE) {
 		s1 = sizeof (struct frame) + 2 * sizeof (long);
 		s2 = s1 + sizeof (siginfo_t);
@@ -122,8 +127,9 @@ dtrace_getustack_common(uint64_t *pcstac
 		s1 = sizeof (struct frame32) + 3 * sizeof (int);
 		s2 = s1 + sizeof (siginfo32_t);
 	}
+#endif
 
-	while (pc != 0 && sp != 0) {
+	while (pc != 0) {
 		ret++;
 		if (pcstack != NULL) {
 			*pcstack++ = (uint64_t)pc;
@@ -132,6 +138,10 @@ dtrace_getustack_common(uint64_t *pcstac
 				break;
 		}
 
+		if (sp == 0)
+			break;
+
+#ifdef notyet /* XXX signal stack. */ 
 		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
 			if (p->p_model == DATAMODEL_NATIVE) {
 				ucontext_t *ucp = (ucontext_t *)oldcontext;
@@ -163,6 +173,11 @@ dtrace_getustack_common(uint64_t *pcstac
 				sp = dtrace_fuword32(&fr->fr_savfp);
 			}
 		}
+#else
+		pc = dtrace_fuword32((void *)(sp +
+			offsetof(struct i386_frame, f_retaddr)));
+		sp = dtrace_fuword32((void *)sp);
+#endif /* ! notyet */
 
 		/*
 		 * This is totally bogus:  if we faulted, we're going to clear
@@ -181,10 +196,9 @@ dtrace_getustack_common(uint64_t *pcstac
 void
 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
 {
-	klwp_t *lwp = ttolwp(curthread);
 	proc_t *p = curproc;
-	struct regs *rp;
-	uintptr_t pc, sp;
+	struct trapframe *tf;
+	uintptr_t pc, sp, fp;
 	volatile uint16_t *flags =
 	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
 	int n;
@@ -198,7 +212,7 @@ dtrace_getupcstack(uint64_t *pcstack, in
 	/*
 	 * If there's no user context we still need to zero the stack.
 	 */
-	if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
+	if (p == NULL || (tf = curthread->td_frame) == NULL)
 		goto zero;
 
 	*pcstack++ = (uint64_t)p->p_pid;
@@ -207,19 +221,26 @@ dtrace_getupcstack(uint64_t *pcstack, in
 	if (pcstack_limit <= 0)
 		return;
 
-	pc = rp->r_pc;
-	sp = rp->r_fp;
+	pc = tf->tf_eip;
+	fp = tf->tf_ebp;
+	sp = tf->tf_esp;
 
 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		/*
+		 * In an entry probe.  The frame pointer has not yet been
+		 * pushed (that happens in the function prologue).  The
+		 * best approach is to add the current pc as a missing top
+		 * of stack and back the pc up to the caller, which is stored
+		 * at the current stack pointer address since the call 
+		 * instruction puts it there right before the branch.
+		 */
+
 		*pcstack++ = (uint64_t)pc;
 		pcstack_limit--;
 		if (pcstack_limit <= 0)
 			return;
 
-		if (p->p_model == DATAMODEL_NATIVE)
-			pc = dtrace_fulword((void *)rp->r_sp);
-		else
-			pc = dtrace_fuword32((void *)rp->r_sp);
+		pc = dtrace_fuword32((void *) sp);
 	}
 
 	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
@@ -231,24 +252,58 @@ dtrace_getupcstack(uint64_t *pcstack, in
 
 zero:
 	while (pcstack_limit-- > 0)
-		*pcstack++ = NULL;
+		*pcstack++ = 0;
 }
 
 int
 dtrace_getustackdepth(void)
 {
+	proc_t *p = curproc;
+	struct trapframe *tf;
+	uintptr_t pc, fp, sp;
+	int n = 0;
+
+	if (p == NULL || (tf = curthread->td_frame) == NULL)
+		return (0);
+
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
+		return (-1);
+
+	pc = tf->tf_eip;
+	fp = tf->tf_ebp;
+	sp = tf->tf_esp;
+
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		/*
+		 * In an entry probe.  The frame pointer has not yet been
+		 * pushed (that happens in the function prologue).  The
+		 * best approach is to add the current pc as a missing top
+		 * of stack and back the pc up to the caller, which is stored
+		 * at the current stack pointer address since the call 
+		 * instruction puts it there right before the branch.
+		 */
+
+		pc = dtrace_fuword32((void *) sp);
+		n++;
+	}
+
+	n += dtrace_getustack_common(NULL, 0, pc, fp);
+
+	return (n);
 }
 
 void

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list