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 <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/sysmacros.h> 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate #include <assert.h> 33*0Sstevel@tonic-gate #include <limits.h> 34*0Sstevel@tonic-gate #include <strings.h> 35*0Sstevel@tonic-gate #include <stdlib.h> 36*0Sstevel@tonic-gate #include <alloca.h> 37*0Sstevel@tonic-gate #include <unistd.h> 38*0Sstevel@tonic-gate #include <errno.h> 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #include <dt_provider.h> 41*0Sstevel@tonic-gate #include <dt_module.h> 42*0Sstevel@tonic-gate #include <dt_string.h> 43*0Sstevel@tonic-gate #include <dt_list.h> 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate static dt_provider_t * 46*0Sstevel@tonic-gate dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h) 47*0Sstevel@tonic-gate { 48*0Sstevel@tonic-gate dt_list_append(&dtp->dt_provlist, pvp); 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate pvp->pv_next = dtp->dt_provs[h]; 51*0Sstevel@tonic-gate dtp->dt_provs[h] = pvp; 52*0Sstevel@tonic-gate dtp->dt_nprovs++; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate return (pvp); 55*0Sstevel@tonic-gate } 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate dt_provider_t * 58*0Sstevel@tonic-gate dt_provider_lookup(dtrace_hdl_t *dtp, const char *name) 59*0Sstevel@tonic-gate { 60*0Sstevel@tonic-gate uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_provbuckets; 61*0Sstevel@tonic-gate dt_provider_t *pvp; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate for (pvp = dtp->dt_provs[h]; pvp != NULL; pvp = pvp->pv_next) { 64*0Sstevel@tonic-gate if (strcmp(pvp->pv_desc.dtvd_name, name) == 0) 65*0Sstevel@tonic-gate return (pvp); 66*0Sstevel@tonic-gate } 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate if (strisglob(name) || name[0] == '\0') { 69*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOPROV); 70*0Sstevel@tonic-gate return (NULL); 71*0Sstevel@tonic-gate } 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate if ((pvp = dt_provider_create(dtp, name)) == NULL) 74*0Sstevel@tonic-gate return (NULL); /* dt_errno is set for us */ 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate if (dt_ioctl(dtp, DTRACEIOC_PROVIDER, &pvp->pv_desc) == -1) { 77*0Sstevel@tonic-gate (void) dt_set_errno(dtp, errno == ESRCH ? EDT_NOPROV : errno); 78*0Sstevel@tonic-gate dt_provider_destroy(dtp, pvp); 79*0Sstevel@tonic-gate return (NULL); 80*0Sstevel@tonic-gate } 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate pvp->pv_flags |= DT_PROVIDER_IMPL; 83*0Sstevel@tonic-gate return (pvp); 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate dt_provider_t * 87*0Sstevel@tonic-gate dt_provider_create(dtrace_hdl_t *dtp, const char *name) 88*0Sstevel@tonic-gate { 89*0Sstevel@tonic-gate dt_provider_t *pvp; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate if ((pvp = dt_zalloc(dtp, sizeof (dt_provider_t))) == NULL) 92*0Sstevel@tonic-gate return (NULL); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate (void) strlcpy(pvp->pv_desc.dtvd_name, name, DTRACE_PROVNAMELEN); 95*0Sstevel@tonic-gate pvp->pv_probes = dt_idhash_create(pvp->pv_desc.dtvd_name, NULL, 0, 0); 96*0Sstevel@tonic-gate pvp->pv_gen = dtp->dt_gen; 97*0Sstevel@tonic-gate pvp->pv_hdl = dtp; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate if (pvp->pv_probes == NULL) { 100*0Sstevel@tonic-gate dt_free(dtp, pvp); 101*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 102*0Sstevel@tonic-gate return (NULL); 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate pvp->pv_desc.dtvd_attr.dtpa_provider = _dtrace_prvattr; 106*0Sstevel@tonic-gate pvp->pv_desc.dtvd_attr.dtpa_mod = _dtrace_prvattr; 107*0Sstevel@tonic-gate pvp->pv_desc.dtvd_attr.dtpa_func = _dtrace_prvattr; 108*0Sstevel@tonic-gate pvp->pv_desc.dtvd_attr.dtpa_name = _dtrace_prvattr; 109*0Sstevel@tonic-gate pvp->pv_desc.dtvd_attr.dtpa_args = _dtrace_prvattr; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate return (dt_provider_insert(dtp, pvp, 112*0Sstevel@tonic-gate dt_strtab_hash(name, NULL) % dtp->dt_provbuckets)); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate void 116*0Sstevel@tonic-gate dt_provider_destroy(dtrace_hdl_t *dtp, dt_provider_t *pvp) 117*0Sstevel@tonic-gate { 118*0Sstevel@tonic-gate dt_provider_t **pp; 119*0Sstevel@tonic-gate uint_t h; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate assert(pvp->pv_hdl == dtp); 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate h = dt_strtab_hash(pvp->pv_desc.dtvd_name, NULL) % dtp->dt_provbuckets; 124*0Sstevel@tonic-gate pp = &dtp->dt_provs[h]; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate while (*pp != NULL && *pp != pvp) 127*0Sstevel@tonic-gate pp = &(*pp)->pv_next; 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate assert(*pp != NULL && *pp == pvp); 130*0Sstevel@tonic-gate *pp = pvp->pv_next; 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate dt_list_delete(&dtp->dt_provlist, pvp); 133*0Sstevel@tonic-gate dtp->dt_nprovs--; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate if (pvp->pv_probes != NULL) 136*0Sstevel@tonic-gate dt_idhash_destroy(pvp->pv_probes); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate dt_node_link_free(&pvp->pv_nodes); 139*0Sstevel@tonic-gate dt_free(dtp, pvp); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate static uint8_t 143*0Sstevel@tonic-gate dt_probe_argmap(dt_node_t *xnp, dt_node_t *nnp) 144*0Sstevel@tonic-gate { 145*0Sstevel@tonic-gate uint8_t i; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate for (i = 0; nnp != NULL; i++) { 148*0Sstevel@tonic-gate if (nnp->dn_string != NULL && 149*0Sstevel@tonic-gate strcmp(nnp->dn_string, xnp->dn_string) == 0) 150*0Sstevel@tonic-gate break; 151*0Sstevel@tonic-gate else 152*0Sstevel@tonic-gate nnp = nnp->dn_list; 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate return (i); 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate static dt_node_t * 159*0Sstevel@tonic-gate dt_probe_alloc_args(dt_provider_t *pvp, int argc) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate dt_node_t *args = NULL, *pnp = NULL, *dnp; 162*0Sstevel@tonic-gate int i; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate for (i = 0; i < argc; i++, pnp = dnp) { 165*0Sstevel@tonic-gate if ((dnp = dt_node_xalloc(pvp->pv_hdl, DT_NODE_TYPE)) == NULL) 166*0Sstevel@tonic-gate return (NULL); 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate dnp->dn_link = pvp->pv_nodes; 169*0Sstevel@tonic-gate pvp->pv_nodes = dnp; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate if (args == NULL) 172*0Sstevel@tonic-gate args = dnp; 173*0Sstevel@tonic-gate else 174*0Sstevel@tonic-gate pnp->dn_list = dnp; 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate return (args); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate static size_t 181*0Sstevel@tonic-gate dt_probe_keylen(const dtrace_probedesc_t *pdp) 182*0Sstevel@tonic-gate { 183*0Sstevel@tonic-gate return (strlen(pdp->dtpd_mod) + 1 + 184*0Sstevel@tonic-gate strlen(pdp->dtpd_func) + 1 + strlen(pdp->dtpd_name) + 1); 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate static char * 188*0Sstevel@tonic-gate dt_probe_key(const dtrace_probedesc_t *pdp, char *s) 189*0Sstevel@tonic-gate { 190*0Sstevel@tonic-gate (void) snprintf(s, INT_MAX, "%s:%s:%s", 191*0Sstevel@tonic-gate pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name); 192*0Sstevel@tonic-gate return (s); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate /* 196*0Sstevel@tonic-gate * If a probe was discovered from the kernel, ask dtrace(7D) for a description 197*0Sstevel@tonic-gate * of each of its arguments, including native and translated types. 198*0Sstevel@tonic-gate */ 199*0Sstevel@tonic-gate static dt_probe_t * 200*0Sstevel@tonic-gate dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp) 201*0Sstevel@tonic-gate { 202*0Sstevel@tonic-gate dtrace_hdl_t *dtp = pvp->pv_hdl; 203*0Sstevel@tonic-gate char *name = dt_probe_key(pdp, alloca(dt_probe_keylen(pdp))); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate dt_node_t *xargs, *nargs; 206*0Sstevel@tonic-gate dt_ident_t *idp; 207*0Sstevel@tonic-gate dt_probe_t *prp; 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate dtrace_typeinfo_t dtt; 210*0Sstevel@tonic-gate int i, nc, xc; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate int adc = _dtrace_argmax; 213*0Sstevel@tonic-gate dtrace_argdesc_t *adv = alloca(sizeof (dtrace_argdesc_t) * adc); 214*0Sstevel@tonic-gate dtrace_argdesc_t *adp = adv; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate assert(strcmp(pvp->pv_desc.dtvd_name, pdp->dtpd_provider) == 0); 217*0Sstevel@tonic-gate assert(pdp->dtpd_id != DTRACE_IDNONE); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate dt_dprintf("discovering probe %s:%s id=%d\n", 220*0Sstevel@tonic-gate pvp->pv_desc.dtvd_name, name, pdp->dtpd_id); 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate for (nc = -1, i = 0; i < adc; i++, adp++) { 223*0Sstevel@tonic-gate bzero(adp, sizeof (dtrace_argdesc_t)); 224*0Sstevel@tonic-gate adp->dtargd_ndx = i; 225*0Sstevel@tonic-gate adp->dtargd_id = pdp->dtpd_id; 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate if (dt_ioctl(dtp, DTRACEIOC_PROBEARG, adp) != 0) { 228*0Sstevel@tonic-gate (void) dt_set_errno(dtp, errno); 229*0Sstevel@tonic-gate return (NULL); 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate if (adp->dtargd_ndx == DTRACE_ARGNONE) 233*0Sstevel@tonic-gate break; /* all argument descs have been retrieved */ 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate nc = MAX(nc, adp->dtargd_mapping); 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate xc = i; 239*0Sstevel@tonic-gate nc++; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate /* 242*0Sstevel@tonic-gate * Now that we have discovered the number of native and translated 243*0Sstevel@tonic-gate * arguments from the argument descriptions, allocate a new probe ident 244*0Sstevel@tonic-gate * and corresponding dt_probe_t and hash it into the provider. 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate xargs = dt_probe_alloc_args(pvp, xc); 247*0Sstevel@tonic-gate nargs = dt_probe_alloc_args(pvp, nc); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if ((xc != 0 && xargs == NULL) || (nc != 0 && nargs == NULL)) 250*0Sstevel@tonic-gate return (NULL); /* dt_errno is set for us */ 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate idp = dt_ident_create(name, DT_IDENT_PROBE, 253*0Sstevel@tonic-gate DT_IDFLG_ORPHAN, pdp->dtpd_id, _dtrace_defattr, 0, 254*0Sstevel@tonic-gate &dt_idops_probe, NULL, dtp->dt_gen); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate if (idp == NULL) { 257*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 258*0Sstevel@tonic-gate return (NULL); 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate if ((prp = dt_probe_create(dtp, idp, nargs, nc, xargs, xc)) == NULL) { 262*0Sstevel@tonic-gate dt_ident_destroy(idp); 263*0Sstevel@tonic-gate return (NULL); 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate dt_probe_declare(pvp, prp); 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * Once our new dt_probe_t is fully constructed, iterate over the 270*0Sstevel@tonic-gate * cached argument descriptions and assign types to prp->pr_nargv[] 271*0Sstevel@tonic-gate * and prp->pr_xargv[] and assign mappings to prp->pr_mapping[]. 272*0Sstevel@tonic-gate */ 273*0Sstevel@tonic-gate for (adp = adv, i = 0; i < xc; i++, adp++) { 274*0Sstevel@tonic-gate if (dtrace_type_strcompile(dtp, 275*0Sstevel@tonic-gate adp->dtargd_native, &dtt) != 0) { 276*0Sstevel@tonic-gate dt_dprintf("failed to resolve input type %s " 277*0Sstevel@tonic-gate "for %s:%s arg #%d: %s\n", adp->dtargd_native, 278*0Sstevel@tonic-gate pvp->pv_desc.dtvd_name, name, i + 1, 279*0Sstevel@tonic-gate dtrace_errmsg(dtp, dtrace_errno(dtp))); 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate dtt.dtt_object = NULL; 282*0Sstevel@tonic-gate dtt.dtt_ctfp = NULL; 283*0Sstevel@tonic-gate dtt.dtt_type = CTF_ERR; 284*0Sstevel@tonic-gate } else { 285*0Sstevel@tonic-gate dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping], 286*0Sstevel@tonic-gate dtt.dtt_ctfp, dtt.dtt_type); 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' || 290*0Sstevel@tonic-gate strcmp(adp->dtargd_native, adp->dtargd_xlate) == 0)) { 291*0Sstevel@tonic-gate dt_node_type_propagate(prp->pr_nargv[ 292*0Sstevel@tonic-gate adp->dtargd_mapping], prp->pr_xargv[i]); 293*0Sstevel@tonic-gate } else if (dtrace_type_strcompile(dtp, 294*0Sstevel@tonic-gate adp->dtargd_xlate, &dtt) != 0) { 295*0Sstevel@tonic-gate dt_dprintf("failed to resolve output type %s " 296*0Sstevel@tonic-gate "for %s:%s arg #%d: %s\n", adp->dtargd_xlate, 297*0Sstevel@tonic-gate pvp->pv_desc.dtvd_name, name, i + 1, 298*0Sstevel@tonic-gate dtrace_errmsg(dtp, dtrace_errno(dtp))); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate dtt.dtt_object = NULL; 301*0Sstevel@tonic-gate dtt.dtt_ctfp = NULL; 302*0Sstevel@tonic-gate dtt.dtt_type = CTF_ERR; 303*0Sstevel@tonic-gate } else { 304*0Sstevel@tonic-gate dt_node_type_assign(prp->pr_xargv[i], 305*0Sstevel@tonic-gate dtt.dtt_ctfp, dtt.dtt_type); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate prp->pr_mapping[i] = adp->dtargd_mapping; 309*0Sstevel@tonic-gate prp->pr_argv[i] = dtt; 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate return (prp); 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate /* 316*0Sstevel@tonic-gate * Lookup a probe declaration based on a known provider and full or partially 317*0Sstevel@tonic-gate * specified module, function, and name. If the probe is not known to us yet, 318*0Sstevel@tonic-gate * ask dtrace(7D) to match the description and then cache any useful results. 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate dt_probe_t * 321*0Sstevel@tonic-gate dt_probe_lookup(dt_provider_t *pvp, const char *s) 322*0Sstevel@tonic-gate { 323*0Sstevel@tonic-gate dtrace_hdl_t *dtp = pvp->pv_hdl; 324*0Sstevel@tonic-gate dtrace_probedesc_t pd; 325*0Sstevel@tonic-gate dt_ident_t *idp; 326*0Sstevel@tonic-gate size_t keylen; 327*0Sstevel@tonic-gate char *key; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate if (dtrace_str2desc(dtp, DTRACE_PROBESPEC_NAME, s, &pd) != 0) 330*0Sstevel@tonic-gate return (NULL); /* dt_errno is set for us */ 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate keylen = dt_probe_keylen(&pd); 333*0Sstevel@tonic-gate key = dt_probe_key(&pd, alloca(keylen)); 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * If the probe is already declared, then return the dt_probe_t from 337*0Sstevel@tonic-gate * the existing identifier. This could come from a static declaration 338*0Sstevel@tonic-gate * or it could have been cached from an earlier call to this function. 339*0Sstevel@tonic-gate */ 340*0Sstevel@tonic-gate if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL) 341*0Sstevel@tonic-gate return (idp->di_data); 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate /* 344*0Sstevel@tonic-gate * If the probe isn't known, use the probe description computed above 345*0Sstevel@tonic-gate * to ask dtrace(7D) to find the first matching probe. 346*0Sstevel@tonic-gate */ 347*0Sstevel@tonic-gate if (dt_ioctl(dtp, DTRACEIOC_PROBEMATCH, &pd) == 0) 348*0Sstevel@tonic-gate return (dt_probe_discover(pvp, &pd)); 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate if (errno == ESRCH || errno == EBADF) 351*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOPROBE); 352*0Sstevel@tonic-gate else 353*0Sstevel@tonic-gate (void) dt_set_errno(dtp, errno); 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate return (NULL); 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate dt_probe_t * 359*0Sstevel@tonic-gate dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp, 360*0Sstevel@tonic-gate dt_node_t *nargs, uint_t nargc, dt_node_t *xargs, uint_t xargc) 361*0Sstevel@tonic-gate { 362*0Sstevel@tonic-gate dt_module_t *dmp; 363*0Sstevel@tonic-gate dt_probe_t *prp; 364*0Sstevel@tonic-gate const char *p; 365*0Sstevel@tonic-gate uint_t i; 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate assert(idp->di_kind == DT_IDENT_PROBE); 368*0Sstevel@tonic-gate assert(idp->di_data == NULL); 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate if (xargs == NULL) { 371*0Sstevel@tonic-gate xargs = nargs; 372*0Sstevel@tonic-gate xargc = nargc; 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate if ((prp = dt_alloc(dtp, sizeof (dt_probe_t))) == NULL) 376*0Sstevel@tonic-gate return (NULL); 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate prp->pr_pvp = NULL; 379*0Sstevel@tonic-gate prp->pr_ident = idp; 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate p = strrchr(idp->di_name, ':'); 382*0Sstevel@tonic-gate assert(p != NULL); 383*0Sstevel@tonic-gate prp->pr_name = p + 1; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate prp->pr_nargs = nargs; 386*0Sstevel@tonic-gate prp->pr_nargv = dt_alloc(dtp, sizeof (dt_node_t *) * nargc); 387*0Sstevel@tonic-gate prp->pr_nargc = nargc; 388*0Sstevel@tonic-gate prp->pr_xargs = xargs; 389*0Sstevel@tonic-gate prp->pr_xargv = dt_alloc(dtp, sizeof (dt_node_t *) * xargc); 390*0Sstevel@tonic-gate prp->pr_xargc = xargc; 391*0Sstevel@tonic-gate prp->pr_mapping = dt_alloc(dtp, sizeof (uint8_t) * xargc); 392*0Sstevel@tonic-gate prp->pr_inst = NULL; 393*0Sstevel@tonic-gate prp->pr_argv = dt_alloc(dtp, sizeof (dtrace_typeinfo_t) * xargc); 394*0Sstevel@tonic-gate prp->pr_argc = xargc; 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate if ((prp->pr_nargc != 0 && prp->pr_nargv == NULL) || 397*0Sstevel@tonic-gate (prp->pr_xargc != 0 && prp->pr_xargv == NULL) || 398*0Sstevel@tonic-gate (prp->pr_xargc != 0 && prp->pr_mapping == NULL) || 399*0Sstevel@tonic-gate (prp->pr_argc != 0 && prp->pr_argv == NULL)) { 400*0Sstevel@tonic-gate dt_probe_destroy(prp); 401*0Sstevel@tonic-gate return (NULL); 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate for (i = 0; i < xargc; i++, xargs = xargs->dn_list) { 405*0Sstevel@tonic-gate if (xargs->dn_string != NULL) 406*0Sstevel@tonic-gate prp->pr_mapping[i] = dt_probe_argmap(xargs, nargs); 407*0Sstevel@tonic-gate else 408*0Sstevel@tonic-gate prp->pr_mapping[i] = i; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate prp->pr_xargv[i] = xargs; 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate if ((dmp = dt_module_lookup_by_ctf(dtp, 413*0Sstevel@tonic-gate xargs->dn_ctfp)) != NULL) 414*0Sstevel@tonic-gate prp->pr_argv[i].dtt_object = dmp->dm_name; 415*0Sstevel@tonic-gate else 416*0Sstevel@tonic-gate prp->pr_argv[i].dtt_object = NULL; 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate prp->pr_argv[i].dtt_ctfp = xargs->dn_ctfp; 419*0Sstevel@tonic-gate prp->pr_argv[i].dtt_type = xargs->dn_type; 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate for (i = 0; i < nargc; i++, nargs = nargs->dn_list) 423*0Sstevel@tonic-gate prp->pr_nargv[i] = nargs; 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate idp->di_data = prp; 426*0Sstevel@tonic-gate return (prp); 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate void 430*0Sstevel@tonic-gate dt_probe_declare(dt_provider_t *pvp, dt_probe_t *prp) 431*0Sstevel@tonic-gate { 432*0Sstevel@tonic-gate assert(prp->pr_ident->di_kind == DT_IDENT_PROBE); 433*0Sstevel@tonic-gate assert(prp->pr_ident->di_data == prp); 434*0Sstevel@tonic-gate assert(prp->pr_pvp == NULL); 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate if (prp->pr_xargs != prp->pr_nargs) 437*0Sstevel@tonic-gate pvp->pv_flags &= ~DT_PROVIDER_INTF; 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate prp->pr_pvp = pvp; 440*0Sstevel@tonic-gate dt_idhash_xinsert(pvp->pv_probes, prp->pr_ident); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate void 444*0Sstevel@tonic-gate dt_probe_destroy(dt_probe_t *prp) 445*0Sstevel@tonic-gate { 446*0Sstevel@tonic-gate dt_probe_instance_t *pip, *pip_next; 447*0Sstevel@tonic-gate dtrace_hdl_t *dtp; 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate if (prp->pr_pvp != NULL) 450*0Sstevel@tonic-gate dtp = prp->pr_pvp->pv_hdl; 451*0Sstevel@tonic-gate else 452*0Sstevel@tonic-gate dtp = yypcb->pcb_hdl; 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate dt_node_list_free(&prp->pr_nargs); 455*0Sstevel@tonic-gate dt_node_list_free(&prp->pr_xargs); 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate dt_free(dtp, prp->pr_nargv); 458*0Sstevel@tonic-gate dt_free(dtp, prp->pr_xargv); 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate for (pip = prp->pr_inst; pip != NULL; pip = pip_next) { 461*0Sstevel@tonic-gate pip_next = pip->pi_next; 462*0Sstevel@tonic-gate dt_free(dtp, pip->pi_offs); 463*0Sstevel@tonic-gate dt_free(dtp, pip); 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate dt_free(dtp, prp->pr_mapping); 467*0Sstevel@tonic-gate dt_free(dtp, prp->pr_argv); 468*0Sstevel@tonic-gate dt_free(dtp, prp); 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate int 472*0Sstevel@tonic-gate dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp, 473*0Sstevel@tonic-gate const char *fname, uint32_t offset) 474*0Sstevel@tonic-gate { 475*0Sstevel@tonic-gate dtrace_hdl_t *dtp = pvp->pv_hdl; 476*0Sstevel@tonic-gate dt_probe_instance_t *pip; 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { 479*0Sstevel@tonic-gate if (strcmp(pip->pi_fname, fname) == 0) 480*0Sstevel@tonic-gate break; 481*0Sstevel@tonic-gate } 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate if (pip == NULL) { 484*0Sstevel@tonic-gate if ((pip = dt_alloc(dtp, sizeof (*pip))) == NULL || 485*0Sstevel@tonic-gate (pip->pi_offs = dt_alloc(dtp, sizeof (uint32_t))) == NULL) { 486*0Sstevel@tonic-gate dt_free(dtp, pip); 487*0Sstevel@tonic-gate return (-1); 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate (void) strlcpy(pip->pi_fname, fname, sizeof (pip->pi_fname)); 491*0Sstevel@tonic-gate pip->pi_noffs = 0; 492*0Sstevel@tonic-gate pip->pi_maxoffs = 1; 493*0Sstevel@tonic-gate pip->pi_next = prp->pr_inst; 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate prp->pr_inst = pip; 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate if (pip->pi_noffs == pip->pi_maxoffs) { 499*0Sstevel@tonic-gate uint_t new_max = pip->pi_maxoffs * 2; 500*0Sstevel@tonic-gate uint32_t *new_offs = dt_alloc(dtp, sizeof (uint32_t) * new_max); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate if (new_offs == NULL) 503*0Sstevel@tonic-gate return (-1); 504*0Sstevel@tonic-gate 505*0Sstevel@tonic-gate bcopy(pip->pi_offs, new_offs, 506*0Sstevel@tonic-gate sizeof (uint32_t) * pip->pi_maxoffs); 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate dt_free(dtp, pip->pi_offs); 509*0Sstevel@tonic-gate pip->pi_maxoffs = new_max; 510*0Sstevel@tonic-gate pip->pi_offs = new_offs; 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate dt_dprintf("defined probe %s:%s %s() +0x%x\n", 514*0Sstevel@tonic-gate pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, fname, offset); 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate assert(pip->pi_noffs < pip->pi_maxoffs); 517*0Sstevel@tonic-gate pip->pi_offs[pip->pi_noffs++] = offset; 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate return (0); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate /*ARGSUSED*/ 523*0Sstevel@tonic-gate static int 524*0Sstevel@tonic-gate dt_probe_desc(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *arg) 525*0Sstevel@tonic-gate { 526*0Sstevel@tonic-gate if (((dtrace_probedesc_t *)arg)->dtpd_id == DTRACE_IDNONE) { 527*0Sstevel@tonic-gate bcopy(pdp, arg, sizeof (dtrace_probedesc_t)); 528*0Sstevel@tonic-gate return (0); 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate return (1); 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate dt_probe_t * 535*0Sstevel@tonic-gate dt_probe_info(dtrace_hdl_t *dtp, 536*0Sstevel@tonic-gate const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip) 537*0Sstevel@tonic-gate { 538*0Sstevel@tonic-gate int m_is_glob = pdp->dtpd_mod[0] == '\0' || strisglob(pdp->dtpd_mod); 539*0Sstevel@tonic-gate int f_is_glob = pdp->dtpd_func[0] == '\0' || strisglob(pdp->dtpd_func); 540*0Sstevel@tonic-gate int n_is_glob = pdp->dtpd_name[0] == '\0' || strisglob(pdp->dtpd_name); 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate dt_probe_t *prp = NULL; 543*0Sstevel@tonic-gate const dtrace_pattr_t *pap; 544*0Sstevel@tonic-gate dt_provider_t *pvp; 545*0Sstevel@tonic-gate dt_ident_t *idp; 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate /* 548*0Sstevel@tonic-gate * Attempt to lookup the probe in our existing cache for this provider. 549*0Sstevel@tonic-gate * If none is found and an explicit probe ID was specified, discover 550*0Sstevel@tonic-gate * that specific probe and cache its description and arguments. 551*0Sstevel@tonic-gate */ 552*0Sstevel@tonic-gate if ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) != NULL) { 553*0Sstevel@tonic-gate size_t keylen = dt_probe_keylen(pdp); 554*0Sstevel@tonic-gate char *key = dt_probe_key(pdp, alloca(keylen)); 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL) 557*0Sstevel@tonic-gate prp = idp->di_data; 558*0Sstevel@tonic-gate else if (pdp->dtpd_id != DTRACE_IDNONE) 559*0Sstevel@tonic-gate prp = dt_probe_discover(pvp, pdp); 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate /* 563*0Sstevel@tonic-gate * If no probe was found in our cache, convert the caller's partial 564*0Sstevel@tonic-gate * probe description into a fully-formed matching probe description by 565*0Sstevel@tonic-gate * iterating over up to at most two probes that match 'pdp'. We then 566*0Sstevel@tonic-gate * call dt_probe_discover() on the resulting probe identifier. 567*0Sstevel@tonic-gate */ 568*0Sstevel@tonic-gate if (prp == NULL) { 569*0Sstevel@tonic-gate dtrace_probedesc_t pd; 570*0Sstevel@tonic-gate int m; 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate bzero(&pd, sizeof (pd)); 573*0Sstevel@tonic-gate pd.dtpd_id = DTRACE_IDNONE; 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate /* 576*0Sstevel@tonic-gate * Call dtrace_probe_iter() to find matching probes. Our 577*0Sstevel@tonic-gate * dt_probe_desc() callback will produce the following results: 578*0Sstevel@tonic-gate * 579*0Sstevel@tonic-gate * m < 0 dtrace_probe_iter() found zero matches (or failed). 580*0Sstevel@tonic-gate * m > 0 dtrace_probe_iter() found more than one match. 581*0Sstevel@tonic-gate * m = 0 dtrace_probe_iter() found exactly one match. 582*0Sstevel@tonic-gate */ 583*0Sstevel@tonic-gate if ((m = dtrace_probe_iter(dtp, pdp, dt_probe_desc, &pd)) < 0) 584*0Sstevel@tonic-gate return (NULL); /* dt_errno is set for us */ 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate if ((pvp = dt_provider_lookup(dtp, pd.dtpd_provider)) == NULL) 587*0Sstevel@tonic-gate return (NULL); /* dt_errno is set for us */ 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* 590*0Sstevel@tonic-gate * If more than one probe was matched, then do not report probe 591*0Sstevel@tonic-gate * information if either of the following conditions is true: 592*0Sstevel@tonic-gate * 593*0Sstevel@tonic-gate * (a) The Arguments Data stability of the matched provider is 594*0Sstevel@tonic-gate * less than Evolving. 595*0Sstevel@tonic-gate * 596*0Sstevel@tonic-gate * (b) Any description component that is at least Evolving is 597*0Sstevel@tonic-gate * empty or is specified using a globbing expression. 598*0Sstevel@tonic-gate * 599*0Sstevel@tonic-gate * These conditions imply that providers that provide Evolving 600*0Sstevel@tonic-gate * or better Arguments Data stability must guarantee that all 601*0Sstevel@tonic-gate * probes with identical field names in a field of Evolving or 602*0Sstevel@tonic-gate * better Name stability have identical argument signatures. 603*0Sstevel@tonic-gate */ 604*0Sstevel@tonic-gate if (m > 0) { 605*0Sstevel@tonic-gate if (pvp->pv_desc.dtvd_attr.dtpa_args.dtat_data < 606*0Sstevel@tonic-gate DTRACE_STABILITY_EVOLVING) { 607*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_UNSTABLE); 608*0Sstevel@tonic-gate return (NULL); 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate if (pvp->pv_desc.dtvd_attr.dtpa_mod.dtat_name >= 613*0Sstevel@tonic-gate DTRACE_STABILITY_EVOLVING && m_is_glob) { 614*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_UNSTABLE); 615*0Sstevel@tonic-gate return (NULL); 616*0Sstevel@tonic-gate } 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate if (pvp->pv_desc.dtvd_attr.dtpa_func.dtat_name >= 619*0Sstevel@tonic-gate DTRACE_STABILITY_EVOLVING && f_is_glob) { 620*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_UNSTABLE); 621*0Sstevel@tonic-gate return (NULL); 622*0Sstevel@tonic-gate } 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate if (pvp->pv_desc.dtvd_attr.dtpa_name.dtat_name >= 625*0Sstevel@tonic-gate DTRACE_STABILITY_EVOLVING && n_is_glob) { 626*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_UNSTABLE); 627*0Sstevel@tonic-gate return (NULL); 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate } 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate if ((prp = dt_probe_discover(pvp, &pd)) == NULL) 632*0Sstevel@tonic-gate return (NULL); /* dt_errno is set for us */ 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate assert(pvp != NULL && prp != NULL); 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* 638*0Sstevel@tonic-gate * Compute the probe description attributes by taking the minimum of 639*0Sstevel@tonic-gate * the attributes of the specified fields. If no provider is specified 640*0Sstevel@tonic-gate * or a glob pattern is used for the provider, use Unstable attributes. 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate if (pdp->dtpd_provider[0] == '\0' || strisglob(pdp->dtpd_provider)) 643*0Sstevel@tonic-gate pap = &_dtrace_prvdesc; 644*0Sstevel@tonic-gate else 645*0Sstevel@tonic-gate pap = &pvp->pv_desc.dtvd_attr; 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate pip->dtp_attr = pap->dtpa_provider; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate if (!m_is_glob) 650*0Sstevel@tonic-gate pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_mod); 651*0Sstevel@tonic-gate if (!f_is_glob) 652*0Sstevel@tonic-gate pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_func); 653*0Sstevel@tonic-gate if (!n_is_glob) 654*0Sstevel@tonic-gate pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_name); 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate pip->dtp_arga = pap->dtpa_args; 657*0Sstevel@tonic-gate pip->dtp_argv = prp->pr_argv; 658*0Sstevel@tonic-gate pip->dtp_argc = prp->pr_argc; 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate return (prp); 661*0Sstevel@tonic-gate } 662*0Sstevel@tonic-gate 663*0Sstevel@tonic-gate int 664*0Sstevel@tonic-gate dtrace_probe_info(dtrace_hdl_t *dtp, 665*0Sstevel@tonic-gate const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip) 666*0Sstevel@tonic-gate { 667*0Sstevel@tonic-gate return (dt_probe_info(dtp, pdp, pip) != NULL ? 0 : -1); 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate /*ARGSUSED*/ 671*0Sstevel@tonic-gate static int 672*0Sstevel@tonic-gate dt_probe_iter(dt_idhash_t *ihp, dt_ident_t *idp, dt_probe_iter_t *pit) 673*0Sstevel@tonic-gate { 674*0Sstevel@tonic-gate const dt_probe_t *prp = idp->di_data; 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate if (!dt_gmatch(prp->pr_name, pit->pit_pat)) 677*0Sstevel@tonic-gate return (0); /* continue on and examine next probe in hash */ 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate (void) strlcpy(pit->pit_desc.dtpd_name, prp->pr_name, DTRACE_NAMELEN); 680*0Sstevel@tonic-gate pit->pit_desc.dtpd_id = idp->di_id; 681*0Sstevel@tonic-gate pit->pit_matches++; 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate return (pit->pit_func(pit->pit_hdl, &pit->pit_desc, pit->pit_arg)); 684*0Sstevel@tonic-gate } 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate int 687*0Sstevel@tonic-gate dtrace_probe_iter(dtrace_hdl_t *dtp, 688*0Sstevel@tonic-gate const dtrace_probedesc_t *pdp, dtrace_probe_f *func, void *arg) 689*0Sstevel@tonic-gate { 690*0Sstevel@tonic-gate const char *provider = pdp ? pdp->dtpd_provider : NULL; 691*0Sstevel@tonic-gate dtrace_id_t id = DTRACE_IDNONE; 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate dtrace_probedesc_t pd; 694*0Sstevel@tonic-gate dt_probe_iter_t pit; 695*0Sstevel@tonic-gate int cmd, rv; 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate bzero(&pit, sizeof (pit)); 698*0Sstevel@tonic-gate pit.pit_hdl = dtp; 699*0Sstevel@tonic-gate pit.pit_func = func; 700*0Sstevel@tonic-gate pit.pit_arg = arg; 701*0Sstevel@tonic-gate pit.pit_pat = pdp ? pdp->dtpd_name : NULL; 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate for (pit.pit_pvp = dt_list_next(&dtp->dt_provlist); 704*0Sstevel@tonic-gate pit.pit_pvp != NULL; pit.pit_pvp = dt_list_next(pit.pit_pvp)) { 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate if (pit.pit_pvp->pv_flags & DT_PROVIDER_IMPL) 707*0Sstevel@tonic-gate continue; /* we'll get these later using dt_ioctl() */ 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate if (!dt_gmatch(pit.pit_pvp->pv_desc.dtvd_name, provider)) 710*0Sstevel@tonic-gate continue; 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate (void) strlcpy(pit.pit_desc.dtpd_provider, 713*0Sstevel@tonic-gate pit.pit_pvp->pv_desc.dtvd_name, DTRACE_PROVNAMELEN); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate if ((rv = dt_idhash_iter(pit.pit_pvp->pv_probes, 716*0Sstevel@tonic-gate (dt_idhash_f *)dt_probe_iter, &pit)) != 0) 717*0Sstevel@tonic-gate return (rv); 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate if (pdp != NULL) 721*0Sstevel@tonic-gate cmd = DTRACEIOC_PROBEMATCH; 722*0Sstevel@tonic-gate else 723*0Sstevel@tonic-gate cmd = DTRACEIOC_PROBES; 724*0Sstevel@tonic-gate 725*0Sstevel@tonic-gate for (;;) { 726*0Sstevel@tonic-gate if (pdp != NULL) 727*0Sstevel@tonic-gate bcopy(pdp, &pd, sizeof (pd)); 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate pd.dtpd_id = id; 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate if (dt_ioctl(dtp, cmd, &pd) != 0) 732*0Sstevel@tonic-gate break; 733*0Sstevel@tonic-gate else if ((rv = func(dtp, &pd, arg)) != 0) 734*0Sstevel@tonic-gate return (rv); 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate pit.pit_matches++; 737*0Sstevel@tonic-gate id = pd.dtpd_id + 1; 738*0Sstevel@tonic-gate } 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate switch (errno) { 741*0Sstevel@tonic-gate case ESRCH: 742*0Sstevel@tonic-gate case EBADF: 743*0Sstevel@tonic-gate return (pit.pit_matches ? 0 : dt_set_errno(dtp, EDT_NOPROBE)); 744*0Sstevel@tonic-gate case EINVAL: 745*0Sstevel@tonic-gate return (dt_set_errno(dtp, EDT_BADPGLOB)); 746*0Sstevel@tonic-gate default: 747*0Sstevel@tonic-gate return (dt_set_errno(dtp, errno)); 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate } 750