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