changeset 491:cf5fd4822860 onnv_23

6320437 ::difo doesn't always properly align its output 6320438 helper tracing should trace detailed error information 6320439 aggregations with negative values are not properly sorted 6320440 quantizations with values in zero bucket are not properly sorted 6320443 linear quantizations with values beyond range aren't properly printed 6320445 need mechanism for ustack helpers to annotate frames 6320447 %d doesn't work properly for printa() of aggregation w/ negative values 6320449 helpers should be able to call string-related subroutines
author bmc
date Tue, 06 Sep 2005 21:35:51 -0700
parents 277f5c2e364f
children 0e64191f8bd0
files usr/src/cmd/mdb/common/modules/dtrace/dof.c usr/src/cmd/mdb/common/modules/dtrace/dtrace.c usr/src/lib/libdtrace/common/dt_aggregate.c usr/src/lib/libdtrace/common/dt_consume.c usr/src/lib/libdtrace/common/dt_impl.h usr/src/lib/libdtrace/common/dt_printf.c usr/src/uts/common/dtrace/dtrace.c usr/src/uts/common/sys/dtrace_impl.h
diffstat 8 files changed, 170 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/modules/dtrace/dof.c	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/cmd/mdb/common/modules/dtrace/dof.c	Tue Sep 06 21:35:51 2005 -0700
@@ -29,12 +29,6 @@
 #include <mdb/mdb_modapi.h>
 #include <dtrace.h>
 
-#ifdef _LP64
-#define	DIFO_ADDRWIDTH		11
-#else
-#define	DIFO_ADDRWIDTH		8
-#endif
-
 extern int dof_sec(uintptr_t, uint_t, int, const mdb_arg_t *);
 extern const char *dof_sec_name(uint32_t);
 
@@ -259,7 +253,7 @@
 	    name, type, DIF_INSTR_R2(instr), DIF_INSTR_RS(instr));
 
 	if (type < sizeof (tnames) / sizeof (tnames[0]))
-		mdb_printf("\t! %s", tnames[type]);
+		mdb_printf("\t\t! %s", tnames[type]);
 }
 
 /*ARGSUSED*/
@@ -402,7 +396,7 @@
 		opcode = 0; /* force invalid opcode message */
 
 	op = &optab[opcode];
-	mdb_printf("%0*p %08x ", DIFO_ADDRWIDTH, addr, instr);
+	mdb_printf("%0?p %08x ", addr, instr);
 	op->op_func(dp, op->op_name, instr);
 	mdb_printf("\n");
 	mdb_set_dot(addr + sizeof (dif_instr_t));
@@ -432,8 +426,7 @@
 
 	mdb_printf("%<u>DIF Object 0x%p%</u> (refcnt=%d)\n\n",
 	    addr, dp->dtdo_refcnt);
-	mdb_printf("%<b>%-*s %-8s %s%</b>\n", DIFO_ADDRWIDTH, "ADDR",
-	    "OPCODE", "INSTRUCTION");
+	mdb_printf("%<b>%-?s %-8s %s%</b>\n", "ADDR", "OPCODE", "INSTRUCTION");
 
 	mdb_set_dot((uintmax_t)(uintptr_t)dp->dtdo_buf);
 	limit = (uintptr_t)dp->dtdo_buf + dp->dtdo_len * sizeof (dif_instr_t);
--- a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c	Tue Sep 06 21:35:51 2005 -0700
@@ -1385,6 +1385,26 @@
 	if (opt_v) {
 		int i;
 
+		if (help.dtht_where == DTRACE_HELPTRACE_ERR) {
+			int f = help.dtht_fault;
+
+			mdb_printf("%?s| %?s %10s |\n", "", "", "");
+			mdb_printf("%?s| %?s %10s +->  fault: %s\n", "", "", "",
+			    f == DTRACEFLT_BADADDR ? "BADADDR" :
+			    f == DTRACEFLT_BADALIGN ? "BADALIGN" :
+			    f == DTRACEFLT_ILLOP ? "ILLOP" :
+			    f == DTRACEFLT_DIVZERO ? "DIVZERO" :
+			    f == DTRACEFLT_NOSCRATCH ? "NOSCRATCH" :
+			    f == DTRACEFLT_KPRIV ? "KPRIV" :
+			    f == DTRACEFLT_UPRIV ? "UPRIV" :
+			    f == DTRACEFLT_TUPOFLOW ? "TUPOFLOW" :
+			    "DTRACEFLT_UNKNOWN");
+			mdb_printf("%?s| %?s %12s     addr: 0x%x\n", "", "", "",
+			    help.dtht_illval);
+			mdb_printf("%?s| %?s %12s   offset: %d\n", "", "", "",
+			    help.dtht_fltoffs);
+		}
+
 		mdb_printf("%?s|\n%?s+--> %?s %4s %s\n", "", "",
 		    "ADDR", "NDX", "VALUE");
 		addr += sizeof (help) - sizeof (uint64_t);
--- a/usr/src/lib/libdtrace/common/dt_aggregate.c	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/lib/libdtrace/common/dt_aggregate.c	Tue Sep 06 21:35:51 2005 -0700
@@ -36,19 +36,19 @@
 #define	DTRACE_AHASHSIZE	32779		/* big 'ol prime */
 
 static void
-dt_aggregate_count(uint64_t *existing, uint64_t *new, size_t size)
+dt_aggregate_count(int64_t *existing, int64_t *new, size_t size)
 {
 	int i;
 
-	for (i = 0; i < size / sizeof (uint64_t); i++)
+	for (i = 0; i < size / sizeof (int64_t); i++)
 		existing[i] = existing[i] + new[i];
 }
 
 static int
-dt_aggregate_countcmp(uint64_t *lhs, uint64_t *rhs)
+dt_aggregate_countcmp(int64_t *lhs, int64_t *rhs)
 {
-	uint64_t lvar = *lhs;
-	uint64_t rvar = *rhs;
+	int64_t lvar = *lhs;
+	int64_t rvar = *rhs;
 
 	if (lvar > rvar)
 		return (1);
@@ -61,7 +61,7 @@
 
 /*ARGSUSED*/
 static void
-dt_aggregate_min(uint64_t *existing, uint64_t *new, size_t size)
+dt_aggregate_min(int64_t *existing, int64_t *new, size_t size)
 {
 	if (*new < *existing)
 		*existing = *new;
@@ -69,17 +69,17 @@
 
 /*ARGSUSED*/
 static void
-dt_aggregate_max(uint64_t *existing, uint64_t *new, size_t size)
+dt_aggregate_max(int64_t *existing, int64_t *new, size_t size)
 {
 	if (*new > *existing)
 		*existing = *new;
 }
 
 static int
-dt_aggregate_averagecmp(uint64_t *lhs, uint64_t *rhs)
+dt_aggregate_averagecmp(int64_t *lhs, int64_t *rhs)
 {
-	uint64_t lavg = lhs[0] ? (lhs[1] / lhs[0]) : 0;
-	uint64_t ravg = rhs[0] ? (rhs[1] / rhs[0]) : 0;
+	int64_t lavg = lhs[0] ? (lhs[1] / lhs[0]) : 0;
+	int64_t ravg = rhs[0] ? (rhs[1] / rhs[0]) : 0;
 
 	if (lavg > ravg)
 		return (1);
@@ -92,9 +92,9 @@
 
 /*ARGSUSED*/
 static void
-dt_aggregate_lquantize(uint64_t *existing, uint64_t *new, size_t size)
+dt_aggregate_lquantize(int64_t *existing, int64_t *new, size_t size)
 {
-	uint64_t arg = *existing++;
+	int64_t arg = *existing++;
 	uint16_t levels = DTRACE_LQUANTIZE_LEVELS(arg);
 	int i;
 
@@ -103,9 +103,9 @@
 }
 
 static long double
-dt_aggregate_lquantizedsum(uint64_t *lquanta)
+dt_aggregate_lquantizedsum(int64_t *lquanta)
 {
-	uint64_t arg = *lquanta++;
+	int64_t arg = *lquanta++;
 	int32_t base = DTRACE_LQUANTIZE_BASE(arg);
 	uint16_t step = DTRACE_LQUANTIZE_STEP(arg);
 	uint16_t levels = DTRACE_LQUANTIZE_LEVELS(arg), i;
@@ -118,11 +118,36 @@
 	    (long double)(base + 1));
 }
 
+static int64_t
+dt_aggregate_lquantizedzero(int64_t *lquanta)
+{
+	int64_t arg = *lquanta++;
+	int32_t base = DTRACE_LQUANTIZE_BASE(arg);
+	uint16_t step = DTRACE_LQUANTIZE_STEP(arg);
+	uint16_t levels = DTRACE_LQUANTIZE_LEVELS(arg), i;
+
+	if (base - 1 == 0)
+		return (lquanta[0]);
+
+	for (i = 0; i < levels; base += step, i++) {
+		if (base != 0)
+			continue;
+
+		return (lquanta[i + 1]);
+	}
+
+	if (base + 1 == 0)
+		return (lquanta[levels + 1]);
+
+	return (0);
+}
+
 static int
-dt_aggregate_lquantizedcmp(uint64_t *lhs, uint64_t *rhs)
+dt_aggregate_lquantizedcmp(int64_t *lhs, int64_t *rhs)
 {
 	long double lsum = dt_aggregate_lquantizedsum(lhs);
 	long double rsum = dt_aggregate_lquantizedsum(rhs);
+	int64_t lzero, rzero;
 
 	if (lsum > rsum)
 		return (1);
@@ -130,18 +155,39 @@
 	if (lsum < rsum)
 		return (-1);
 
+	/*
+	 * If they're both equal, then we will compare based on the weights at
+	 * zero.  If the weights at zero are equal (or if zero is not within
+	 * the range of the linear quantization), then this will be judged a
+	 * tie and will be resolved based on the key comparison.
+	 */
+	lzero = dt_aggregate_lquantizedzero(lhs);
+	rzero = dt_aggregate_lquantizedzero(rhs);
+
+	if (lzero > rzero)
+		return (1);
+
+	if (lzero < rzero)
+		return (-1);
+
 	return (0);
 }
 
 static int
-dt_aggregate_quantizedcmp(uint64_t *lhs, uint64_t *rhs)
+dt_aggregate_quantizedcmp(int64_t *lhs, int64_t *rhs)
 {
 	int nbuckets = DTRACE_QUANTIZE_NBUCKETS, i;
 	long double ltotal = 0, rtotal = 0;
+	int64_t lzero, rzero;
 
 	for (i = 0; i < nbuckets; i++) {
 		int64_t bucketval = DTRACE_QUANTIZE_BUCKETVAL(i);
 
+		if (bucketval == 0) {
+			lzero = lhs[i];
+			rzero = rhs[i];
+		}
+
 		ltotal += (long double)bucketval * (long double)lhs[i];
 		rtotal += (long double)bucketval * (long double)rhs[i];
 	}
@@ -152,6 +198,17 @@
 	if (ltotal < rtotal)
 		return (-1);
 
+	/*
+	 * If they're both equal, then we will compare based on the weights at
+	 * zero.  If the weights at zero are equal, then this will be judged a
+	 * tie and will be resolved based on the key comparison.
+	 */
+	if (lzero > rzero)
+		return (1);
+
+	if (lzero < rzero)
+		return (-1);
+
 	return (0);
 }
 
@@ -377,9 +434,9 @@
 			rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
 			roffs = rec->dtrd_offset;
 			/* LINTED - alignment */
-			h->dtahe_aggregate((uint64_t *)&data[roffs],
+			h->dtahe_aggregate((int64_t *)&data[roffs],
 			    /* LINTED - alignment */
-			    (uint64_t *)&addr[roffs], rec->dtrd_size);
+			    (int64_t *)&addr[roffs], rec->dtrd_size);
 
 			/*
 			 * If we're keeping per CPU data, apply the aggregating
@@ -389,9 +446,9 @@
 				data = aggdata->dtada_percpu[cpu];
 
 				/* LINTED - alignment */
-				h->dtahe_aggregate((uint64_t *)data,
+				h->dtahe_aggregate((int64_t *)data,
 				    /* LINTED - alignment */
-				    (uint64_t *)&addr[roffs], rec->dtrd_size);
+				    (int64_t *)&addr[roffs], rec->dtrd_size);
 			}
 
 			goto bufnext;
@@ -669,7 +726,7 @@
 	caddr_t ldata = lh->dtahe_data.dtada_data;
 	caddr_t rdata = rh->dtahe_data.dtada_data;
 	dtrace_recdesc_t *lrec, *rrec;
-	uint64_t *laddr, *raddr;
+	int64_t *laddr, *raddr;
 	int rval, i;
 
 	if ((rval = dt_aggregate_hashcmp(lhs, rhs)) != 0)
@@ -698,8 +755,8 @@
 			return (1);
 	}
 
-	laddr = (uint64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
-	raddr = (uint64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);
+	laddr = (int64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
+	raddr = (int64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);
 
 	switch (lrec->dtrd_action) {
 	case DTRACEAGG_AVG:
--- a/usr/src/lib/libdtrace/common/dt_consume.c	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/lib/libdtrace/common/dt_consume.c	Tue Sep 06 21:35:51 2005 -0700
@@ -306,10 +306,10 @@
 	if (size != sizeof (uint64_t) * (levels + 2))
 		return (dt_set_errno(dtp, EDT_DMISMATCH));
 
-	while (first_bin < levels + 1 && data[first_bin] == 0)
+	while (first_bin <= levels + 1 && data[first_bin] == 0)
 		first_bin++;
 
-	if (first_bin == levels + 1) {
+	if (first_bin > levels + 1) {
 		first_bin = 0;
 		last_bin = 2;
 	} else {
@@ -627,7 +627,7 @@
 				(void) snprintf(c, sizeof (c),
 				    "%s`%s", dt_basename(objname), name);
 			}
-		} else if (str != NULL && str[0] != '\0' &&
+		} else if (str != NULL && str[0] != '\0' && str[0] != '@' &&
 		    (P != NULL && ((map = Paddr_to_map(P, pc[i])) == NULL ||
 		    (map->pr_mflags & MA_WRITE)))) {
 			/*
@@ -661,6 +661,25 @@
 		if ((err = dt_printf(dtp, fp, "\n")) < 0)
 			break;
 
+		if (str != NULL && str[0] == '@') {
+			/*
+			 * If the first character of the string is an "at" sign,
+			 * then the string is inferred to be an annotation --
+			 * and it is printed out beneath the frame and offset
+			 * with brackets.
+			 */
+			if ((err = dt_printf(dtp, fp, "%*s", indent, "")) < 0)
+				break;
+
+			(void) snprintf(c, sizeof (c), "  [ %s ]", &str[1]);
+
+			if ((err = dt_printf(dtp, fp, format, c)) < 0)
+				break;
+
+			if ((err = dt_printf(dtp, fp, "\n")) < 0)
+				break;
+		}
+
 		if (str != NULL) {
 			str += strlen(str) + 1;
 			if (str - strbase >= strsize)
--- a/usr/src/lib/libdtrace/common/dt_impl.h	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/lib/libdtrace/common/dt_impl.h	Tue Sep 06 21:35:51 2005 -0700
@@ -147,7 +147,7 @@
 	uint64_t dtahe_hashval;			/* hash value */
 	size_t dtahe_size;			/* size of data */
 	dtrace_aggdata_t dtahe_data;		/* data */
-	void (*dtahe_aggregate)(uint64_t *, uint64_t *, size_t); /* function */
+	void (*dtahe_aggregate)(int64_t *, int64_t *, size_t); /* function */
 } dt_ahashent_t;
 
 typedef struct dt_ahash {
--- a/usr/src/lib/libdtrace/common/dt_printf.c	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/lib/libdtrace/common/dt_printf.c	Tue Sep 06 21:35:51 2005 -0700
@@ -979,10 +979,10 @@
 
 	/*
 	 * We fake up a parse node representing the type that can be used with
-	 * an aggregation result conversion.  For now we hardcode the signed
-	 * aggregations; this will be fixed later when sign issues are fixed.
+	 * an aggregation result conversion, which -- for all but count() --
+	 * is a signed quantity.
 	 */
-	if (kind == DTRACEAGG_QUANTIZE || kind == DTRACEAGG_LQUANTIZE)
+	if (kind != DTRACEAGG_COUNT)
 		aggtype = "int64_t";
 	else
 		aggtype = "uint64_t";
--- a/usr/src/uts/common/dtrace/dtrace.c	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/uts/common/dtrace/dtrace.c	Tue Sep 06 21:35:51 2005 -0700
@@ -396,6 +396,17 @@
 #define	DTRACE_ANCHORED(probe)	((probe)->dtpr_func[0] != '\0')
 #define	DTRACE_STATE_ALIGN	64
 
+#define	DTRACE_FLAGS2FLT(flags)						\
+	(((flags) & CPU_DTRACE_BADADDR) ? DTRACEFLT_BADADDR :		\
+	((flags) & CPU_DTRACE_ILLOP) ? DTRACEFLT_ILLOP :		\
+	((flags) & CPU_DTRACE_DIVZERO) ? DTRACEFLT_DIVZERO :		\
+	((flags) & CPU_DTRACE_KPRIV) ? DTRACEFLT_KPRIV :		\
+	((flags) & CPU_DTRACE_UPRIV) ? DTRACEFLT_UPRIV :		\
+	((flags) & CPU_DTRACE_TUPOFLOW) ?  DTRACEFLT_TUPOFLOW :		\
+	((flags) & CPU_DTRACE_BADALIGN) ?  DTRACEFLT_BADALIGN :		\
+	((flags) & CPU_DTRACE_NOSCRATCH) ?  DTRACEFLT_NOSCRATCH :	\
+	DTRACEFLT_UNKNOWN)
+
 static dtrace_probe_t *dtrace_probe_lookup_id(dtrace_id_t id);
 static void dtrace_enabling_provide(dtrace_provider_t *);
 static int dtrace_enabling_match(dtrace_enabling_t *, int *);
@@ -5044,18 +5055,7 @@
 
 			dtrace_probe_error(state, ecb->dte_epid, ndx,
 			    (mstate.dtms_present & DTRACE_MSTATE_FLTOFFS) ?
-			    mstate.dtms_fltoffs : -1,
-			    (*flags & CPU_DTRACE_BADADDR) ? DTRACEFLT_BADADDR :
-			    (*flags & CPU_DTRACE_ILLOP) ? DTRACEFLT_ILLOP :
-			    (*flags & CPU_DTRACE_DIVZERO) ? DTRACEFLT_DIVZERO :
-			    (*flags & CPU_DTRACE_KPRIV) ? DTRACEFLT_KPRIV :
-			    (*flags & CPU_DTRACE_UPRIV) ? DTRACEFLT_UPRIV :
-			    (*flags & CPU_DTRACE_TUPOFLOW) ?
-			    DTRACEFLT_TUPOFLOW :
-			    (*flags & CPU_DTRACE_BADALIGN) ?
-			    DTRACEFLT_BADALIGN :
-			    (*flags & CPU_DTRACE_NOSCRATCH) ?
-			    DTRACEFLT_NOSCRATCH : DTRACEFLT_UNKNOWN,
+			    mstate.dtms_fltoffs : -1, DTRACE_FLAGS2FLT(*flags),
 			    cpu_core[cpuid].cpuc_dtrace_illval);
 
 			continue;
@@ -7138,7 +7138,8 @@
  * are much more constrained than normal DIFOs.  Specifically, they may
  * not:
  *
- * 1. Make calls to subroutines other than copyin() or copyinstr().
+ * 1. Make calls to subroutines other than copyin(), copyinstr() or
+ *    miscellaneous string routines
  * 2. Access DTrace variables other than the args[] array, and the
  *    curthread, pid, tid and execname variables.
  * 3. Have thread-local variables.
@@ -7255,7 +7256,14 @@
 			    subr == DIF_SUBR_BCOPY ||
 			    subr == DIF_SUBR_COPYIN ||
 			    subr == DIF_SUBR_COPYINTO ||
-			    subr == DIF_SUBR_COPYINSTR)
+			    subr == DIF_SUBR_COPYINSTR ||
+			    subr == DIF_SUBR_INDEX ||
+			    subr == DIF_SUBR_LLTOSTR ||
+			    subr == DIF_SUBR_RINDEX ||
+			    subr == DIF_SUBR_STRCHR ||
+			    subr == DIF_SUBR_STRJOIN ||
+			    subr == DIF_SUBR_STRRCHR ||
+			    subr == DIF_SUBR_STRSTR)
 				break;
 
 			err += efunc(pc, "invalid subr %u\n", subr);
@@ -11731,11 +11739,12 @@
  * DTrace Helper Functions
  */
 static void
-dtrace_helper_trace(dtrace_helper_action_t *helper, dtrace_vstate_t *vstate,
-    int where)
+dtrace_helper_trace(dtrace_helper_action_t *helper,
+    dtrace_mstate_t *mstate, dtrace_vstate_t *vstate, int where)
 {
 	uint32_t size, next, nnext, i;
 	dtrace_helptrace_t *ent;
+	uint16_t flags = cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
 
 	if (!dtrace_helptrace_enabled)
 		return;
@@ -11773,6 +11782,11 @@
 	ent->dtht_where = where;
 	ent->dtht_nlocals = vstate->dtvs_nlocals;
 
+	ent->dtht_fltoffs = (mstate->dtms_present & DTRACE_MSTATE_FLTOFFS) ?
+	    mstate->dtms_fltoffs : -1;
+	ent->dtht_fault = DTRACE_FLAGS2FLT(flags);
+	ent->dtht_illval = cpu_core[CPU->cpu_id].cpuc_dtrace_illval;
+
 	for (i = 0; i < vstate->dtvs_nlocals; i++) {
 		dtrace_statvar_t *svar;
 
@@ -11823,7 +11837,7 @@
 	for (; helper != NULL; helper = helper->dthp_next) {
 		if ((pred = helper->dthp_predicate) != NULL) {
 			if (trace)
-				dtrace_helper_trace(helper, vstate, 0);
+				dtrace_helper_trace(helper, mstate, vstate, 0);
 
 			if (!dtrace_dif_emulate(pred, mstate, vstate, state))
 				goto next;
@@ -11834,7 +11848,8 @@
 
 		for (i = 0; i < helper->dthp_nactions; i++) {
 			if (trace)
-				dtrace_helper_trace(helper, vstate, i + 1);
+				dtrace_helper_trace(helper,
+				    mstate, vstate, i + 1);
 
 			rval = dtrace_dif_emulate(helper->dthp_actions[i],
 			    mstate, vstate, state);
@@ -11845,12 +11860,13 @@
 
 next:
 		if (trace)
-			dtrace_helper_trace(helper, vstate,
+			dtrace_helper_trace(helper, mstate, vstate,
 			    DTRACE_HELPTRACE_NEXT);
 	}
 
 	if (trace)
-		dtrace_helper_trace(helper, vstate, DTRACE_HELPTRACE_DONE);
+		dtrace_helper_trace(helper, mstate, vstate,
+		    DTRACE_HELPTRACE_DONE);
 
 	/*
 	 * Restore the arg0 that we saved upon entry.
@@ -11862,7 +11878,8 @@
 
 err:
 	if (trace)
-		dtrace_helper_trace(helper, vstate, DTRACE_HELPTRACE_ERR);
+		dtrace_helper_trace(helper, mstate, vstate,
+		    DTRACE_HELPTRACE_ERR);
 
 	/*
 	 * Restore the arg0 that we saved upon entry.
--- a/usr/src/uts/common/sys/dtrace_impl.h	Tue Sep 06 18:31:25 2005 -0700
+++ b/usr/src/uts/common/sys/dtrace_impl.h	Tue Sep 06 21:35:51 2005 -0700
@@ -1029,6 +1029,9 @@
 	dtrace_helper_action_t	*dtht_helper;	/* helper action */
 	int dtht_where;				/* where in helper action */
 	int dtht_nlocals;			/* number of locals */
+	int dtht_fault;				/* type of fault (if any) */
+	int dtht_fltoffs;			/* DIF offset */
+	uint64_t dtht_illval;			/* faulting value */
 	uint64_t dtht_locals[1];		/* local variables */
 } dtrace_helptrace_t;