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