xref: /onnv-gate/usr/src/lib/libdtrace/common/dt_handle.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <stddef.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate #include <strings.h>
32*0Sstevel@tonic-gate #include <errno.h>
33*0Sstevel@tonic-gate #include <unistd.h>
34*0Sstevel@tonic-gate #include <dt_impl.h>
35*0Sstevel@tonic-gate #include <assert.h>
36*0Sstevel@tonic-gate #include <alloca.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate static const char _dt_errprog[] =
39*0Sstevel@tonic-gate "dtrace:::ERROR"
40*0Sstevel@tonic-gate "{"
41*0Sstevel@tonic-gate "	trace(arg1);"
42*0Sstevel@tonic-gate "	trace(arg2);"
43*0Sstevel@tonic-gate "	trace(arg3);"
44*0Sstevel@tonic-gate "	trace(arg4);"
45*0Sstevel@tonic-gate "	trace(arg5);"
46*0Sstevel@tonic-gate "}";
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate int
49*0Sstevel@tonic-gate dtrace_handle_err(dtrace_hdl_t *dtp, dtrace_handle_err_f *hdlr, void *arg)
50*0Sstevel@tonic-gate {
51*0Sstevel@tonic-gate 	dtrace_prog_t *pgp = NULL;
52*0Sstevel@tonic-gate 	dt_stmt_t *stp;
53*0Sstevel@tonic-gate 	dtrace_ecbdesc_t *edp;
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate 	/*
56*0Sstevel@tonic-gate 	 * We don't currently support multiple error handlers.
57*0Sstevel@tonic-gate 	 */
58*0Sstevel@tonic-gate 	if (dtp->dt_errhdlr != NULL)
59*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EALREADY));
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate 	/*
62*0Sstevel@tonic-gate 	 * If the DTRACEOPT_GRABANON is enabled, the anonymous enabling will
63*0Sstevel@tonic-gate 	 * already have a dtrace:::ERROR probe enabled; save 'hdlr' and 'arg'
64*0Sstevel@tonic-gate 	 * but do not bother compiling and enabling _dt_errprog.
65*0Sstevel@tonic-gate 	 */
66*0Sstevel@tonic-gate 	if (dtp->dt_options[DTRACEOPT_GRABANON] != DTRACEOPT_UNSET)
67*0Sstevel@tonic-gate 		goto out;
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	if ((pgp = dtrace_program_strcompile(dtp, _dt_errprog,
70*0Sstevel@tonic-gate 	    DTRACE_PROBESPEC_NAME, DTRACE_C_ZDEFS, 0, NULL)) == NULL)
71*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, dtrace_errno(dtp)));
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	stp = dt_list_next(&pgp->dp_stmts);
74*0Sstevel@tonic-gate 	assert(stp != NULL);
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	edp = stp->ds_desc->dtsd_ecbdesc;
77*0Sstevel@tonic-gate 	assert(edp != NULL);
78*0Sstevel@tonic-gate 	edp->dted_uarg = DT_ECB_ERROR;
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate out:
81*0Sstevel@tonic-gate 	dtp->dt_errhdlr = hdlr;
82*0Sstevel@tonic-gate 	dtp->dt_errarg = arg;
83*0Sstevel@tonic-gate 	dtp->dt_errprog = pgp;
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate 	return (0);
86*0Sstevel@tonic-gate }
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate int
89*0Sstevel@tonic-gate dtrace_handle_drop(dtrace_hdl_t *dtp, dtrace_handle_drop_f *hdlr, void *arg)
90*0Sstevel@tonic-gate {
91*0Sstevel@tonic-gate 	if (dtp->dt_drophdlr != NULL)
92*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EALREADY));
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	dtp->dt_drophdlr = hdlr;
95*0Sstevel@tonic-gate 	dtp->dt_droparg = arg;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	return (0);
98*0Sstevel@tonic-gate }
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate int
101*0Sstevel@tonic-gate dtrace_handle_proc(dtrace_hdl_t *dtp, dtrace_handle_proc_f *hdlr, void *arg)
102*0Sstevel@tonic-gate {
103*0Sstevel@tonic-gate 	if (dtp->dt_prochdlr != NULL)
104*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EALREADY));
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 	dtp->dt_prochdlr = hdlr;
107*0Sstevel@tonic-gate 	dtp->dt_procarg = arg;
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	return (0);
110*0Sstevel@tonic-gate }
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate int
113*0Sstevel@tonic-gate dtrace_handle_buffered(dtrace_hdl_t *dtp, dtrace_handle_buffered_f *hdlr,
114*0Sstevel@tonic-gate     void *arg)
115*0Sstevel@tonic-gate {
116*0Sstevel@tonic-gate 	if (dtp->dt_bufhdlr != NULL)
117*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EALREADY));
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	if (hdlr == NULL)
120*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EINVAL));
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	dtp->dt_bufhdlr = hdlr;
123*0Sstevel@tonic-gate 	dtp->dt_bufarg = arg;
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 	return (0);
126*0Sstevel@tonic-gate }
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate #define	DT_REC(type, ndx) *((type *)((uintptr_t)data->dtpda_data + \
129*0Sstevel@tonic-gate     epd->dtepd_rec[(ndx)].dtrd_offset))
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate static int
132*0Sstevel@tonic-gate dt_handle_err(dtrace_hdl_t *dtp, dtrace_probedata_t *data)
133*0Sstevel@tonic-gate {
134*0Sstevel@tonic-gate 	dtrace_eprobedesc_t *epd = data->dtpda_edesc, *errepd;
135*0Sstevel@tonic-gate 	dtrace_probedesc_t *pd = data->dtpda_pdesc, *errpd;
136*0Sstevel@tonic-gate 	dtrace_errdata_t err;
137*0Sstevel@tonic-gate 	dtrace_epid_t epid;
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	char where[30];
140*0Sstevel@tonic-gate 	char details[30];
141*0Sstevel@tonic-gate 	char offinfo[30];
142*0Sstevel@tonic-gate 	const int slop = 80;
143*0Sstevel@tonic-gate 	const char *faultstr;
144*0Sstevel@tonic-gate 	char *str;
145*0Sstevel@tonic-gate 	int len;
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	assert(epd->dtepd_uarg == DT_ECB_ERROR);
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	if (epd->dtepd_nrecs != 5 || strcmp(pd->dtpd_provider, "dtrace") != 0 ||
150*0Sstevel@tonic-gate 	    strcmp(pd->dtpd_name, "ERROR") != 0)
151*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADERROR));
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 	/*
154*0Sstevel@tonic-gate 	 * This is an error.  We have the following items here:  EPID,
155*0Sstevel@tonic-gate 	 * faulting action, DIF offset, fault code and faulting address.
156*0Sstevel@tonic-gate 	 */
157*0Sstevel@tonic-gate 	epid = (uint32_t)DT_REC(uint64_t, 0);
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 	if (dt_epid_lookup(dtp, epid, &errepd, &errpd) != 0)
160*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BADERROR));
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	err.dteda_edesc = errepd;
163*0Sstevel@tonic-gate 	err.dteda_pdesc = errpd;
164*0Sstevel@tonic-gate 	err.dteda_cpu = data->dtpda_cpu;
165*0Sstevel@tonic-gate 	err.dteda_action = (int)DT_REC(uint64_t, 1);
166*0Sstevel@tonic-gate 	err.dteda_offset = (int)DT_REC(uint64_t, 2);
167*0Sstevel@tonic-gate 	err.dteda_fault = (int)DT_REC(uint64_t, 3);
168*0Sstevel@tonic-gate 	err.dteda_addr = DT_REC(uint64_t, 4);
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	faultstr = dtrace_faultstr(dtp, err.dteda_fault);
171*0Sstevel@tonic-gate 	len = sizeof (where) + sizeof (offinfo) + strlen(faultstr) +
172*0Sstevel@tonic-gate 	    strlen(errpd->dtpd_provider) + strlen(errpd->dtpd_mod) +
173*0Sstevel@tonic-gate 	    strlen(errpd->dtpd_name) + strlen(errpd->dtpd_func) +
174*0Sstevel@tonic-gate 	    slop;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	str = (char *)alloca(len);
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	if (err.dteda_action == 0) {
179*0Sstevel@tonic-gate 		(void) sprintf(where, "predicate");
180*0Sstevel@tonic-gate 	} else {
181*0Sstevel@tonic-gate 		(void) sprintf(where, "action #%d", err.dteda_action);
182*0Sstevel@tonic-gate 	}
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	if (err.dteda_offset != -1) {
185*0Sstevel@tonic-gate 		(void) sprintf(offinfo, " at DIF offset %d", err.dteda_offset);
186*0Sstevel@tonic-gate 	} else {
187*0Sstevel@tonic-gate 		offinfo[0] = 0;
188*0Sstevel@tonic-gate 	}
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 	switch (err.dteda_fault) {
191*0Sstevel@tonic-gate 	case DTRACEFLT_BADADDR:
192*0Sstevel@tonic-gate 	case DTRACEFLT_BADALIGN:
193*0Sstevel@tonic-gate 		(void) sprintf(details, " (0x%llx)",
194*0Sstevel@tonic-gate 		    (u_longlong_t)err.dteda_addr);
195*0Sstevel@tonic-gate 		break;
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate 	default:
198*0Sstevel@tonic-gate 		details[0] = 0;
199*0Sstevel@tonic-gate 	}
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 	(void) snprintf(str, len, "error on enabled probe ID %u "
202*0Sstevel@tonic-gate 	    "(ID %u: %s:%s:%s:%s): %s%s in %s%s\n",
203*0Sstevel@tonic-gate 	    epid, errpd->dtpd_id, errpd->dtpd_provider,
204*0Sstevel@tonic-gate 	    errpd->dtpd_mod, errpd->dtpd_func,
205*0Sstevel@tonic-gate 	    errpd->dtpd_name, dtrace_faultstr(dtp, err.dteda_fault),
206*0Sstevel@tonic-gate 	    details, where, offinfo);
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 	err.dteda_msg = str;
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	if (dtp->dt_errhdlr == NULL)
211*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_ERRABORT));
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	if ((*dtp->dt_errhdlr)(&err, dtp->dt_errarg) == DTRACE_HANDLE_ABORT)
214*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_ERRABORT));
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	return (0);
217*0Sstevel@tonic-gate }
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate int
220*0Sstevel@tonic-gate dt_handle_liberr(dtrace_hdl_t *dtp, const dtrace_probedata_t *data,
221*0Sstevel@tonic-gate     const char *faultstr)
222*0Sstevel@tonic-gate {
223*0Sstevel@tonic-gate 	dtrace_probedesc_t *errpd = data->dtpda_pdesc;
224*0Sstevel@tonic-gate 	dtrace_errdata_t err;
225*0Sstevel@tonic-gate 	const int slop = 80;
226*0Sstevel@tonic-gate 	char *str;
227*0Sstevel@tonic-gate 	int len;
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	err.dteda_edesc = data->dtpda_edesc;
230*0Sstevel@tonic-gate 	err.dteda_pdesc = errpd;
231*0Sstevel@tonic-gate 	err.dteda_cpu = data->dtpda_cpu;
232*0Sstevel@tonic-gate 	err.dteda_action = -1;
233*0Sstevel@tonic-gate 	err.dteda_offset = -1;
234*0Sstevel@tonic-gate 	err.dteda_fault = DTRACEFLT_LIBRARY;
235*0Sstevel@tonic-gate 	err.dteda_addr = NULL;
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	len = strlen(faultstr) +
238*0Sstevel@tonic-gate 	    strlen(errpd->dtpd_provider) + strlen(errpd->dtpd_mod) +
239*0Sstevel@tonic-gate 	    strlen(errpd->dtpd_name) + strlen(errpd->dtpd_func) +
240*0Sstevel@tonic-gate 	    slop;
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	str = alloca(len);
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 	(void) snprintf(str, len, "error on enabled probe ID %u "
245*0Sstevel@tonic-gate 	    "(ID %u: %s:%s:%s:%s): %s\n",
246*0Sstevel@tonic-gate 	    data->dtpda_edesc->dtepd_epid,
247*0Sstevel@tonic-gate 	    errpd->dtpd_id, errpd->dtpd_provider,
248*0Sstevel@tonic-gate 	    errpd->dtpd_mod, errpd->dtpd_func,
249*0Sstevel@tonic-gate 	    errpd->dtpd_name, faultstr);
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	err.dteda_msg = str;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	if (dtp->dt_errhdlr == NULL)
254*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_ERRABORT));
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	if ((*dtp->dt_errhdlr)(&err, dtp->dt_errarg) == DTRACE_HANDLE_ABORT)
257*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_ERRABORT));
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 	return (0);
260*0Sstevel@tonic-gate }
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate int
263*0Sstevel@tonic-gate dt_handle_cpudrop(dtrace_hdl_t *dtp, processorid_t cpu,
264*0Sstevel@tonic-gate     dtrace_dropkind_t what, uint64_t howmany)
265*0Sstevel@tonic-gate {
266*0Sstevel@tonic-gate 	dtrace_dropdata_t drop;
267*0Sstevel@tonic-gate 	char str[80];
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 	assert(what == DTRACEDROP_PRINCIPAL || what == DTRACEDROP_AGGREGATION);
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	bzero(&drop, sizeof (drop));
272*0Sstevel@tonic-gate 	drop.dtdda_handle = dtp;
273*0Sstevel@tonic-gate 	drop.dtdda_cpu = cpu;
274*0Sstevel@tonic-gate 	drop.dtdda_kind = what;
275*0Sstevel@tonic-gate 	drop.dtdda_drops = howmany;
276*0Sstevel@tonic-gate 	drop.dtdda_msg = str;
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 	(void) snprintf(str, sizeof (str), "%llu %sdrop%s on CPU %d\n",
279*0Sstevel@tonic-gate 	    howmany, what == DTRACEDROP_PRINCIPAL ? "" : "aggregation ",
280*0Sstevel@tonic-gate 	    howmany > 1 ? "s" : "", cpu);
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	if (dtp->dt_drophdlr == NULL)
283*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_DROPABORT));
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 	if ((*dtp->dt_drophdlr)(&drop, dtp->dt_droparg) == DTRACE_HANDLE_ABORT)
286*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_DROPABORT));
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 	return (0);
289*0Sstevel@tonic-gate }
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate static const struct {
292*0Sstevel@tonic-gate 	dtrace_dropkind_t dtdrt_kind;
293*0Sstevel@tonic-gate 	uintptr_t dtdrt_offset;
294*0Sstevel@tonic-gate 	const char *dtdrt_str;
295*0Sstevel@tonic-gate 	const char *dtdrt_msg;
296*0Sstevel@tonic-gate } _dt_droptab[] = {
297*0Sstevel@tonic-gate 	{ DTRACEDROP_DYNAMIC,
298*0Sstevel@tonic-gate 	    offsetof(dtrace_status_t, dtst_dyndrops),
299*0Sstevel@tonic-gate 	    "dynamic variable drop" },
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate 	{ DTRACEDROP_DYNRINSE,
302*0Sstevel@tonic-gate 	    offsetof(dtrace_status_t, dtst_dyndrops_rinsing),
303*0Sstevel@tonic-gate 	    "dynamic variable drop", " with non-empty rinsing list" },
304*0Sstevel@tonic-gate 
305*0Sstevel@tonic-gate 	{ DTRACEDROP_DYNDIRTY,
306*0Sstevel@tonic-gate 	    offsetof(dtrace_status_t, dtst_dyndrops_dirty),
307*0Sstevel@tonic-gate 	    "dynamic variable drop", " with non-empty dirty list" },
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	{ DTRACEDROP_SPEC,
310*0Sstevel@tonic-gate 	    offsetof(dtrace_status_t, dtst_specdrops),
311*0Sstevel@tonic-gate 	    "speculative drop" },
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate 	{ DTRACEDROP_SPECBUSY,
314*0Sstevel@tonic-gate 	    offsetof(dtrace_status_t, dtst_specdrops_busy),
315*0Sstevel@tonic-gate 	    "failed speculation", " (available buffer(s) still busy)" },
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	{ DTRACEDROP_SPECUNAVAIL,
318*0Sstevel@tonic-gate 	    offsetof(dtrace_status_t, dtst_specdrops_unavail),
319*0Sstevel@tonic-gate 	    "failed speculation", " (no speculative buffer available)" },
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 	{ 0, 0, NULL }
322*0Sstevel@tonic-gate };
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate int
325*0Sstevel@tonic-gate dt_handle_status(dtrace_hdl_t *dtp, dtrace_status_t *old, dtrace_status_t *new)
326*0Sstevel@tonic-gate {
327*0Sstevel@tonic-gate 	dtrace_dropdata_t drop;
328*0Sstevel@tonic-gate 	char str[80];
329*0Sstevel@tonic-gate 	uintptr_t base = (uintptr_t)new, obase = (uintptr_t)old;
330*0Sstevel@tonic-gate 	int i;
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 	bzero(&drop, sizeof (drop));
333*0Sstevel@tonic-gate 	drop.dtdda_handle = dtp;
334*0Sstevel@tonic-gate 	drop.dtdda_cpu = DTRACE_CPUALL;
335*0Sstevel@tonic-gate 	drop.dtdda_msg = str;
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	/*
338*0Sstevel@tonic-gate 	 * First, check to see if we've been killed -- in which case we abort.
339*0Sstevel@tonic-gate 	 */
340*0Sstevel@tonic-gate 	if (new->dtst_killed && !old->dtst_killed)
341*0Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_BRICKED));
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	for (i = 0; _dt_droptab[i].dtdrt_str != NULL; i++) {
344*0Sstevel@tonic-gate 		uintptr_t naddr = base + _dt_droptab[i].dtdrt_offset;
345*0Sstevel@tonic-gate 		uintptr_t oaddr = obase + _dt_droptab[i].dtdrt_offset;
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 		uint64_t nval = *((uint64_t *)naddr);
348*0Sstevel@tonic-gate 		uint64_t oval = *((uint64_t *)oaddr);
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 		if (nval == oval)
351*0Sstevel@tonic-gate 			continue;
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 		(void) snprintf(str, sizeof (str), "%llu %s%s%s\n", nval - oval,
354*0Sstevel@tonic-gate 		    _dt_droptab[i].dtdrt_str, (nval - oval > 1) ? "s" : "",
355*0Sstevel@tonic-gate 		    _dt_droptab[i].dtdrt_msg != NULL ?
356*0Sstevel@tonic-gate 		    _dt_droptab[i].dtdrt_msg : "");
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate 		drop.dtdda_kind = _dt_droptab[i].dtdrt_kind;
359*0Sstevel@tonic-gate 		drop.dtdda_total = nval;
360*0Sstevel@tonic-gate 		drop.dtdda_drops = nval - oval;
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 		if (dtp->dt_drophdlr == NULL)
363*0Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_DROPABORT));
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 		if ((*dtp->dt_drophdlr)(&drop,
366*0Sstevel@tonic-gate 		    dtp->dt_droparg) == DTRACE_HANDLE_ABORT)
367*0Sstevel@tonic-gate 			return (dt_set_errno(dtp, EDT_DROPABORT));
368*0Sstevel@tonic-gate 	}
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	return (0);
371*0Sstevel@tonic-gate }
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate int
374*0Sstevel@tonic-gate dt_handle(dtrace_hdl_t *dtp, dtrace_probedata_t *data)
375*0Sstevel@tonic-gate {
376*0Sstevel@tonic-gate 	dtrace_eprobedesc_t *epd = data->dtpda_edesc;
377*0Sstevel@tonic-gate 	int rval;
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 	switch (epd->dtepd_uarg) {
380*0Sstevel@tonic-gate 	case DT_ECB_ERROR:
381*0Sstevel@tonic-gate 		rval = dt_handle_err(dtp, data);
382*0Sstevel@tonic-gate 		break;
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 	default:
385*0Sstevel@tonic-gate 		return (DTRACE_CONSUME_THIS);
386*0Sstevel@tonic-gate 	}
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 	if (rval == 0)
389*0Sstevel@tonic-gate 		return (DTRACE_CONSUME_NEXT);
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	return (DTRACE_CONSUME_ERROR);
392*0Sstevel@tonic-gate }
393