111894Speter/* 211894Speter * CDDL HEADER START 39Sjkh * 49Sjkh * The contents of this file are subject to the terms of the 59Sjkh * Common Development and Distribution License (the "License"). 69Sjkh * You may not use this file except in compliance with the License. 79Sjkh * 89Sjkh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 911894Speter * or http://www.opensolaris.org/os/licensing. 1011894Speter * See the License for the specific language governing permissions 119Sjkh * and limitations under the License. 129Sjkh * 139Sjkh * When distributing Covered Code, include this CDDL HEADER in each 149Sjkh * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159Sjkh * If applicable, add the following below this CDDL HEADER, with the 169Sjkh * fields enclosed by brackets "[]" replaced with your own identifying 179Sjkh * information: Portions Copyright [yyyy] [name of copyright owner] 189Sjkh * 199Sjkh * CDDL HEADER END 209Sjkh */ 219Sjkh 229Sjkh/* 239Sjkh * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 249Sjkh * Use is subject to license terms. 259Sjkh */ 2611894Speter/* 2711894Speter * Copyright (c) 2013, Joyent, Inc. All rights reserved. 2811894Speter */ 299Sjkh 309Sjkh#include <sys/types.h> 319Sjkh#ifdef illumos 329Sjkh#include <sys/sysmacros.h> 339Sjkh#endif 349Sjkh 359Sjkh#include <assert.h> 369Sjkh#include <limits.h> 379Sjkh#include <strings.h> 389Sjkh#include <stdlib.h> 399Sjkh#ifdef illumos 4011894Speter#include <alloca.h> 4111894Speter#endif 4211894Speter#include <unistd.h> 4311894Speter#include <errno.h> 448858Srgrimes 4511894Speter#include <dt_provider.h> 4611894Speter#include <dt_module.h> 4711894Speter#include <dt_string.h> 4811894Speter#include <dt_list.h> 4911894Speter#include <dt_pid.h> 5011894Speter#include <dtrace.h> 5111894Speter 5211894Speterstatic dt_provider_t * 5311894Speterdt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h) 5411894Speter{ 5511894Speter dt_list_append(&dtp->dt_provlist, pvp); 5611894Speter 5711894Speter pvp->pv_next = dtp->dt_provs[h]; 5811894Speter dtp->dt_provs[h] = pvp; 599Sjkh dtp->dt_nprovs++; 609Sjkh 619Sjkh return (pvp); 629Sjkh} 639Sjkh 649Sjkhdt_provider_t * 659Sjkhdt_provider_lookup(dtrace_hdl_t *dtp, const char *name) 669Sjkh{ 679Sjkh uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_provbuckets; 689Sjkh dtrace_providerdesc_t desc; 699Sjkh dt_provider_t *pvp; 709Sjkh 719Sjkh for (pvp = dtp->dt_provs[h]; pvp != NULL; pvp = pvp->pv_next) { 729Sjkh if (strcmp(pvp->pv_desc.dtvd_name, name) == 0) 739Sjkh return (pvp); 749Sjkh } 759Sjkh 769Sjkh if (strisglob(name) || name[0] == '\0') { 779Sjkh (void) dt_set_errno(dtp, EDT_NOPROV); 789Sjkh return (NULL); 799Sjkh } 809Sjkh 819Sjkh bzero(&desc, sizeof (desc)); 829Sjkh (void) strlcpy(desc.dtvd_name, name, DTRACE_PROVNAMELEN); 839Sjkh 849Sjkh if (dt_ioctl(dtp, DTRACEIOC_PROVIDER, &desc) == -1) { 859Sjkh (void) dt_set_errno(dtp, errno == ESRCH ? EDT_NOPROV : errno); 869Sjkh return (NULL); 879Sjkh } 889Sjkh 899Sjkh if ((pvp = dt_provider_create(dtp, name)) == NULL) 908858Srgrimes return (NULL); /* dt_errno is set for us */ 919Sjkh 929Sjkh bcopy(&desc, &pvp->pv_desc, sizeof (desc)); 938858Srgrimes pvp->pv_flags |= DT_PROVIDER_IMPL; 949Sjkh return (pvp); 959Sjkh} 968858Srgrimes 979Sjkhdt_provider_t * 988858Srgrimesdt_provider_create(dtrace_hdl_t *dtp, const char *name) 999Sjkh{ 1008858Srgrimes dt_provider_t *pvp; 1019Sjkh 1029Sjkh if ((pvp = dt_zalloc(dtp, sizeof (dt_provider_t))) == NULL) 1038858Srgrimes return (NULL); 1049Sjkh 1059Sjkh (void) strlcpy(pvp->pv_desc.dtvd_name, name, DTRACE_PROVNAMELEN); 1069Sjkh pvp->pv_probes = dt_idhash_create(pvp->pv_desc.dtvd_name, NULL, 0, 0); 1078858Srgrimes pvp->pv_gen = dtp->dt_gen; 1089Sjkh pvp->pv_hdl = dtp; 1099Sjkh 1109Sjkh if (pvp->pv_probes == NULL) { 1119Sjkh dt_free(dtp, pvp); 1129Sjkh (void) dt_set_errno(dtp, EDT_NOMEM); 1139Sjkh return (NULL); 1149Sjkh } 1159Sjkh 1169Sjkh pvp->pv_desc.dtvd_attr.dtpa_provider = _dtrace_prvattr; 1179Sjkh pvp->pv_desc.dtvd_attr.dtpa_mod = _dtrace_prvattr; 1189Sjkh pvp->pv_desc.dtvd_attr.dtpa_func = _dtrace_prvattr; 1199Sjkh pvp->pv_desc.dtvd_attr.dtpa_name = _dtrace_prvattr; 1209Sjkh pvp->pv_desc.dtvd_attr.dtpa_args = _dtrace_prvattr; 1219Sjkh 12211894Speter return (dt_provider_insert(dtp, pvp, 1239Sjkh dt_strtab_hash(name, NULL) % dtp->dt_provbuckets)); 12411894Speter} 1259Sjkh 1269Sjkhvoid 1279Sjkhdt_provider_destroy(dtrace_hdl_t *dtp, dt_provider_t *pvp) 1289Sjkh{ 1299Sjkh dt_provider_t **pp; 1309Sjkh uint_t h; 1319Sjkh 1329Sjkh assert(pvp->pv_hdl == dtp); 1339Sjkh 1349Sjkh h = dt_strtab_hash(pvp->pv_desc.dtvd_name, NULL) % dtp->dt_provbuckets; 1359Sjkh pp = &dtp->dt_provs[h]; 13611894Speter 1379Sjkh while (*pp != NULL && *pp != pvp) 1389Sjkh pp = &(*pp)->pv_next; 1399Sjkh 1409Sjkh assert(*pp != NULL && *pp == pvp); 1419Sjkh *pp = pvp->pv_next; 14211894Speter 1439Sjkh dt_list_delete(&dtp->dt_provlist, pvp); 1449Sjkh dtp->dt_nprovs--; 14511894Speter 1469Sjkh if (pvp->pv_probes != NULL) 14711894Speter dt_idhash_destroy(pvp->pv_probes); 14811894Speter 1499Sjkh dt_node_link_free(&pvp->pv_nodes); 1509Sjkh dt_free(dtp, pvp->pv_xrefs); 1519Sjkh dt_free(dtp, pvp); 1529Sjkh} 15311894Speter 1549Sjkhint 1559Sjkhdt_provider_xref(dtrace_hdl_t *dtp, dt_provider_t *pvp, id_t id) 1569Sjkh{ 1579Sjkh size_t oldsize = BT_SIZEOFMAP(pvp->pv_xrmax); 1589Sjkh size_t newsize = BT_SIZEOFMAP(dtp->dt_xlatorid); 1599Sjkh 1609Sjkh assert(id >= 0 && id < dtp->dt_xlatorid); 1619Sjkh 1629Sjkh if (newsize > oldsize) { 1639Sjkh ulong_t *xrefs = dt_zalloc(dtp, newsize); 1649Sjkh 1659Sjkh if (xrefs == NULL) 1669Sjkh return (-1); 16711894Speter 1689Sjkh bcopy(pvp->pv_xrefs, xrefs, oldsize); 1699Sjkh dt_free(dtp, pvp->pv_xrefs); 1709Sjkh 1719Sjkh pvp->pv_xrefs = xrefs; 17211894Speter pvp->pv_xrmax = dtp->dt_xlatorid; 17311894Speter } 1749Sjkh 1759Sjkh BT_SET(pvp->pv_xrefs, id); 17611894Speter return (0); 1779Sjkh} 17811894Speter 1799Sjkhstatic uint8_t 1809Sjkhdt_probe_argmap(dt_node_t *xnp, dt_node_t *nnp) 1819Sjkh{ 1829Sjkh uint8_t i; 18311894Speter 18411894Speter for (i = 0; nnp != NULL; i++) { 1859Sjkh if (nnp->dn_string != NULL && 1869Sjkh strcmp(nnp->dn_string, xnp->dn_string) == 0) 1879Sjkh break; 1889Sjkh else 1899Sjkh nnp = nnp->dn_list; 1909Sjkh } 1919Sjkh 1929Sjkh return (i); 1939Sjkh} 1949Sjkh 19511894Speterstatic dt_node_t * 1969Sjkhdt_probe_alloc_args(dt_provider_t *pvp, int argc) 1979Sjkh{ 1989Sjkh dt_node_t *args = NULL, *pnp = NULL, *dnp; 1999Sjkh int i; 2009Sjkh 20111894Speter for (i = 0; i < argc; i++, pnp = dnp) { 20211894Speter if ((dnp = dt_node_xalloc(pvp->pv_hdl, DT_NODE_TYPE)) == NULL) 2039Sjkh return (NULL); 2049Sjkh 2059Sjkh dnp->dn_link = pvp->pv_nodes; 2069Sjkh pvp->pv_nodes = dnp; 2079Sjkh 2089Sjkh if (args == NULL) 20911894Speter args = dnp; 21011894Speter else 2119Sjkh pnp->dn_list = dnp; 2129Sjkh } 2139Sjkh 2149Sjkh return (args); 2159Sjkh} 2169Sjkh 2179Sjkhstatic size_t 2189Sjkhdt_probe_keylen(const dtrace_probedesc_t *pdp) 2199Sjkh{ 2209Sjkh return (strlen(pdp->dtpd_mod) + 1 + 2219Sjkh strlen(pdp->dtpd_func) + 1 + strlen(pdp->dtpd_name) + 1); 2229Sjkh} 2239Sjkh 2249Sjkhstatic char * 2259Sjkhdt_probe_key(const dtrace_probedesc_t *pdp, char *s) 2269Sjkh{ 2279Sjkh (void) snprintf(s, INT_MAX, "%s:%s:%s", 2289Sjkh pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name); 2299Sjkh return (s); 2309Sjkh} 2319Sjkh 2329Sjkh/* 2339Sjkh * If a probe was discovered from the kernel, ask dtrace(7D) for a description 2349Sjkh * of each of its arguments, including native and translated types. 2359Sjkh */ 2369Sjkhstatic dt_probe_t * 2379Sjkhdt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp) 2389Sjkh{ 2399Sjkh dtrace_hdl_t *dtp = pvp->pv_hdl; 2409Sjkh char *name = dt_probe_key(pdp, alloca(dt_probe_keylen(pdp))); 2419Sjkh 2429Sjkh dt_node_t *xargs, *nargs; 2439Sjkh dt_ident_t *idp; 2449Sjkh dt_probe_t *prp; 24511894Speter 24611894Speter dtrace_typeinfo_t dtt; 2479Sjkh int i, nc, xc; 2489Sjkh 2499Sjkh int adc = _dtrace_argmax; 2509Sjkh dtrace_argdesc_t *adv = alloca(sizeof (dtrace_argdesc_t) * adc); 2519Sjkh dtrace_argdesc_t *adp = adv; 2529Sjkh 2539Sjkh assert(strcmp(pvp->pv_desc.dtvd_name, pdp->dtpd_provider) == 0); 2549Sjkh assert(pdp->dtpd_id != DTRACE_IDNONE); 2559Sjkh 2569Sjkh dt_dprintf("discovering probe %s:%s id=%d\n", 2579Sjkh pvp->pv_desc.dtvd_name, name, pdp->dtpd_id); 2589Sjkh 2599Sjkh for (nc = -1, i = 0; i < adc; i++, adp++) { 2609Sjkh bzero(adp, sizeof (dtrace_argdesc_t)); 26111894Speter adp->dtargd_ndx = i; 26211894Speter adp->dtargd_id = pdp->dtpd_id; 2639Sjkh 2649Sjkh if (dt_ioctl(dtp, DTRACEIOC_PROBEARG, adp) != 0) { 2659Sjkh (void) dt_set_errno(dtp, errno); 2669Sjkh return (NULL); 2679Sjkh } 26811894Speter 2699Sjkh if (adp->dtargd_ndx == DTRACE_ARGNONE) 2709Sjkh break; /* all argument descs have been retrieved */ 2719Sjkh 2729Sjkh nc = MAX(nc, adp->dtargd_mapping); 27311894Speter } 27411894Speter 27511894Speter xc = i; 27611894Speter nc++; 27711894Speter 27811894Speter /* 27911894Speter * The pid provider believes in giving the kernel a break. No reason to 28011894Speter * give the kernel all the ctf containers that we're keeping ourselves 28111894Speter * just to get it back from it. So if we're coming from a pid provider 28211894Speter * probe and the kernel gave us no argument information we'll get some 28311894Speter * here. If for some crazy reason the kernel knows about our userland 28411894Speter * types then we just ignore this. 2859Sjkh */ 2869Sjkh if (xc == 0 && nc == 0 && 2879Sjkh strncmp(pvp->pv_desc.dtvd_name, "pid", 3) == 0) { 28811894Speter nc = adc; 2899Sjkh dt_pid_get_types(dtp, pdp, adv, &nc); 2909Sjkh xc = nc; 2919Sjkh } 2929Sjkh 29311894Speter /* 29411894Speter * Now that we have discovered the number of native and translated 29511894Speter * arguments from the argument descriptions, allocate a new probe ident 2969Sjkh * and corresponding dt_probe_t and hash it into the provider. 2979Sjkh */ 29811894Speter xargs = dt_probe_alloc_args(pvp, xc); 29911894Speter nargs = dt_probe_alloc_args(pvp, nc); 3009Sjkh 30111894Speter if ((xc != 0 && xargs == NULL) || (nc != 0 && nargs == NULL)) 3029Sjkh return (NULL); /* dt_errno is set for us */ 3039Sjkh 3049Sjkh idp = dt_ident_create(name, DT_IDENT_PROBE, 3059Sjkh DT_IDFLG_ORPHAN, pdp->dtpd_id, _dtrace_defattr, 0, 3069Sjkh &dt_idops_probe, NULL, dtp->dt_gen); 3079Sjkh 3089Sjkh if (idp == NULL) { 3099Sjkh (void) dt_set_errno(dtp, EDT_NOMEM); 3109Sjkh return (NULL); 3119Sjkh } 3129Sjkh 3139Sjkh if ((prp = dt_probe_create(dtp, idp, 2, 3149Sjkh nargs, nc, xargs, xc)) == NULL) { 3159Sjkh dt_ident_destroy(idp); 3169Sjkh return (NULL); 31711894Speter } 31811894Speter 31911894Speter dt_probe_declare(pvp, prp); 32011894Speter 3219Sjkh /* 3229Sjkh * Once our new dt_probe_t is fully constructed, iterate over the 3239Sjkh * cached argument descriptions and assign types to prp->pr_nargv[] 3249Sjkh * and prp->pr_xargv[] and assign mappings to prp->pr_mapping[]. 3259Sjkh */ 3269Sjkh for (adp = adv, i = 0; i < xc; i++, adp++) { 3279Sjkh if (dtrace_type_strcompile(dtp, 3289Sjkh adp->dtargd_native, &dtt) != 0) { 3299Sjkh dt_dprintf("failed to resolve input type %s " 3309Sjkh "for %s:%s arg #%d: %s\n", adp->dtargd_native, 3319Sjkh pvp->pv_desc.dtvd_name, name, i + 1, 3329Sjkh dtrace_errmsg(dtp, dtrace_errno(dtp))); 3339Sjkh 3349Sjkh dtt.dtt_object = NULL; 3359Sjkh dtt.dtt_ctfp = NULL; 3369Sjkh dtt.dtt_type = CTF_ERR; 3379Sjkh } else { 3389Sjkh dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping], 3399Sjkh dtt.dtt_ctfp, dtt.dtt_type, 3409Sjkh dtt.dtt_flags & DTT_FL_USER ? B_TRUE : B_FALSE); 3419Sjkh } 3429Sjkh 3439Sjkh if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' || 3449Sjkh strcmp(adp->dtargd_native, adp->dtargd_xlate) == 0)) { 3459Sjkh dt_node_type_propagate(prp->pr_nargv[ 3469Sjkh adp->dtargd_mapping], prp->pr_xargv[i]); 3479Sjkh } else if (dtrace_type_strcompile(dtp, 3489Sjkh adp->dtargd_xlate, &dtt) != 0) { 3499Sjkh dt_dprintf("failed to resolve output type %s " 3509Sjkh "for %s:%s arg #%d: %s\n", adp->dtargd_xlate, 3519Sjkh pvp->pv_desc.dtvd_name, name, i + 1, 3529Sjkh dtrace_errmsg(dtp, dtrace_errno(dtp))); 3539Sjkh 3549Sjkh dtt.dtt_object = NULL; 3559Sjkh dtt.dtt_ctfp = NULL; 356 dtt.dtt_type = CTF_ERR; 357 } else { 358 dt_node_type_assign(prp->pr_xargv[i], 359 dtt.dtt_ctfp, dtt.dtt_type, B_FALSE); 360 } 361 362 prp->pr_mapping[i] = adp->dtargd_mapping; 363 prp->pr_argv[i] = dtt; 364 } 365 366 return (prp); 367} 368 369/* 370 * Lookup a probe declaration based on a known provider and full or partially 371 * specified module, function, and name. If the probe is not known to us yet, 372 * ask dtrace(7D) to match the description and then cache any useful results. 373 */ 374dt_probe_t * 375dt_probe_lookup(dt_provider_t *pvp, const char *s) 376{ 377 dtrace_hdl_t *dtp = pvp->pv_hdl; 378 dtrace_probedesc_t pd; 379 dt_ident_t *idp; 380 size_t keylen; 381 char *key; 382 383 if (dtrace_str2desc(dtp, DTRACE_PROBESPEC_NAME, s, &pd) != 0) 384 return (NULL); /* dt_errno is set for us */ 385 386 keylen = dt_probe_keylen(&pd); 387 key = dt_probe_key(&pd, alloca(keylen)); 388 389 /* 390 * If the probe is already declared, then return the dt_probe_t from 391 * the existing identifier. This could come from a static declaration 392 * or it could have been cached from an earlier call to this function. 393 */ 394 if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL) 395 return (idp->di_data); 396 397 /* 398 * If the probe isn't known, use the probe description computed above 399 * to ask dtrace(7D) to find the first matching probe. 400 */ 401 if (dt_ioctl(dtp, DTRACEIOC_PROBEMATCH, &pd) == 0) 402 return (dt_probe_discover(pvp, &pd)); 403 404 if (errno == ESRCH || errno == EBADF) 405 (void) dt_set_errno(dtp, EDT_NOPROBE); 406 else 407 (void) dt_set_errno(dtp, errno); 408 409 return (NULL); 410} 411 412dt_probe_t * 413dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp, int protoc, 414 dt_node_t *nargs, uint_t nargc, dt_node_t *xargs, uint_t xargc) 415{ 416 dt_module_t *dmp; 417 dt_probe_t *prp; 418 const char *p; 419 uint_t i; 420 421 assert(idp->di_kind == DT_IDENT_PROBE); 422 assert(idp->di_data == NULL); 423 424 /* 425 * If only a single prototype is given, set xargc/s to nargc/s to 426 * simplify subsequent use. Note that we can have one or both of nargs 427 * and xargs be specified but set to NULL, indicating a void prototype. 428 */ 429 if (protoc < 2) { 430 assert(xargs == NULL); 431 assert(xargc == 0); 432 xargs = nargs; 433 xargc = nargc; 434 } 435 436 if ((prp = dt_alloc(dtp, sizeof (dt_probe_t))) == NULL) 437 return (NULL); 438 439 prp->pr_pvp = NULL; 440 prp->pr_ident = idp; 441 442 p = strrchr(idp->di_name, ':'); 443 assert(p != NULL); 444 prp->pr_name = p + 1; 445 446 prp->pr_nargs = nargs; 447 prp->pr_nargv = dt_alloc(dtp, sizeof (dt_node_t *) * nargc); 448 prp->pr_nargc = nargc; 449 prp->pr_xargs = xargs; 450 prp->pr_xargv = dt_alloc(dtp, sizeof (dt_node_t *) * xargc); 451 prp->pr_xargc = xargc; 452 prp->pr_mapping = dt_alloc(dtp, sizeof (uint8_t) * xargc); 453 prp->pr_inst = NULL; 454 prp->pr_argv = dt_alloc(dtp, sizeof (dtrace_typeinfo_t) * xargc); 455 prp->pr_argc = xargc; 456 457 if ((prp->pr_nargc != 0 && prp->pr_nargv == NULL) || 458 (prp->pr_xargc != 0 && prp->pr_xargv == NULL) || 459 (prp->pr_xargc != 0 && prp->pr_mapping == NULL) || 460 (prp->pr_argc != 0 && prp->pr_argv == NULL)) { 461 dt_probe_destroy(prp); 462 return (NULL); 463 } 464 465 for (i = 0; i < xargc; i++, xargs = xargs->dn_list) { 466 if (xargs->dn_string != NULL) 467 prp->pr_mapping[i] = dt_probe_argmap(xargs, nargs); 468 else 469 prp->pr_mapping[i] = i; 470 471 prp->pr_xargv[i] = xargs; 472 473 if ((dmp = dt_module_lookup_by_ctf(dtp, 474 xargs->dn_ctfp)) != NULL) 475 prp->pr_argv[i].dtt_object = dmp->dm_name; 476 else 477 prp->pr_argv[i].dtt_object = NULL; 478 479 prp->pr_argv[i].dtt_ctfp = xargs->dn_ctfp; 480 prp->pr_argv[i].dtt_type = xargs->dn_type; 481 } 482 483 for (i = 0; i < nargc; i++, nargs = nargs->dn_list) 484 prp->pr_nargv[i] = nargs; 485 486 idp->di_data = prp; 487 return (prp); 488} 489 490void 491dt_probe_declare(dt_provider_t *pvp, dt_probe_t *prp) 492{ 493 assert(prp->pr_ident->di_kind == DT_IDENT_PROBE); 494 assert(prp->pr_ident->di_data == prp); 495 assert(prp->pr_pvp == NULL); 496 497 if (prp->pr_xargs != prp->pr_nargs) 498 pvp->pv_flags &= ~DT_PROVIDER_INTF; 499 500 prp->pr_pvp = pvp; 501 dt_idhash_xinsert(pvp->pv_probes, prp->pr_ident); 502} 503 504void 505dt_probe_destroy(dt_probe_t *prp) 506{ 507 dt_probe_instance_t *pip, *pip_next; 508 dtrace_hdl_t *dtp; 509 510 if (prp->pr_pvp != NULL) 511 dtp = prp->pr_pvp->pv_hdl; 512 else 513 dtp = yypcb->pcb_hdl; 514 515 dt_node_list_free(&prp->pr_nargs); 516 dt_node_list_free(&prp->pr_xargs); 517 518 dt_free(dtp, prp->pr_nargv); 519 dt_free(dtp, prp->pr_xargv); 520 521 for (pip = prp->pr_inst; pip != NULL; pip = pip_next) { 522 pip_next = pip->pi_next; 523 dt_free(dtp, pip->pi_rname); 524 dt_free(dtp, pip->pi_fname); 525 dt_free(dtp, pip->pi_offs); 526 dt_free(dtp, pip->pi_enoffs); 527 dt_free(dtp, pip); 528 } 529 530 dt_free(dtp, prp->pr_mapping); 531 dt_free(dtp, prp->pr_argv); 532 dt_free(dtp, prp); 533} 534 535int 536dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp, 537 const char *fname, const char *rname, uint32_t offset, int isenabled) 538{ 539 dtrace_hdl_t *dtp = pvp->pv_hdl; 540 dt_probe_instance_t *pip; 541 uint32_t **offs; 542 uint_t *noffs, *maxoffs; 543 544 assert(fname != NULL); 545 546 for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { 547 if (strcmp(pip->pi_fname, fname) == 0 && 548 strcmp(pip->pi_rname, rname) == 0) 549 break; 550 } 551 552 if (pip == NULL) { 553 if ((pip = dt_zalloc(dtp, sizeof (*pip))) == NULL) 554 return (-1); 555 556 if ((pip->pi_offs = dt_zalloc(dtp, sizeof (uint32_t))) == NULL) 557 goto nomem; 558 559 if ((pip->pi_enoffs = dt_zalloc(dtp, 560 sizeof (uint32_t))) == NULL) 561 goto nomem; 562 563 if ((pip->pi_fname = strdup(fname)) == NULL) 564 goto nomem; 565 566 if ((pip->pi_rname = strdup(rname)) == NULL) 567 goto nomem; 568 569 pip->pi_noffs = 0; 570 pip->pi_maxoffs = 1; 571 pip->pi_nenoffs = 0; 572 pip->pi_maxenoffs = 1; 573 574 pip->pi_next = prp->pr_inst; 575 576 prp->pr_inst = pip; 577 } 578 579 if (isenabled) { 580 offs = &pip->pi_enoffs; 581 noffs = &pip->pi_nenoffs; 582 maxoffs = &pip->pi_maxenoffs; 583 } else { 584 offs = &pip->pi_offs; 585 noffs = &pip->pi_noffs; 586 maxoffs = &pip->pi_maxoffs; 587 } 588 589 if (*noffs == *maxoffs) { 590 uint_t new_max = *maxoffs * 2; 591 uint32_t *new_offs = dt_alloc(dtp, sizeof (uint32_t) * new_max); 592 593 if (new_offs == NULL) 594 return (-1); 595 596 bcopy(*offs, new_offs, sizeof (uint32_t) * *maxoffs); 597 598 dt_free(dtp, *offs); 599 *maxoffs = new_max; 600 *offs = new_offs; 601 } 602 603 dt_dprintf("defined probe %s %s:%s %s() +0x%x (%s)\n", 604 isenabled ? "(is-enabled)" : "", 605 pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, fname, offset, 606 rname); 607 608 assert(*noffs < *maxoffs); 609 (*offs)[(*noffs)++] = offset; 610 611 return (0); 612 613nomem: 614 dt_free(dtp, pip->pi_fname); 615 dt_free(dtp, pip->pi_enoffs); 616 dt_free(dtp, pip->pi_offs); 617 dt_free(dtp, pip); 618 return (dt_set_errno(dtp, EDT_NOMEM)); 619} 620 621/* 622 * Lookup the dynamic translator type tag for the specified probe argument and 623 * assign the type to the specified node. If the type is not yet defined, add 624 * it to the "D" module's type container as a typedef for an unknown type. 625 */ 626dt_node_t * 627dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp) 628{ 629 dtrace_hdl_t *dtp = prp->pr_pvp->pv_hdl; 630 dtrace_typeinfo_t dtt; 631 size_t len; 632 char *tag; 633 634 len = snprintf(NULL, 0, "__dtrace_%s___%s_arg%u", 635 prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn); 636 637 tag = alloca(len + 1); 638 639 (void) snprintf(tag, len + 1, "__dtrace_%s___%s_arg%u", 640 prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn); 641 642 if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_DDEFS, tag, &dtt) != 0) { 643 dtt.dtt_object = DTRACE_OBJ_DDEFS; 644 dtt.dtt_ctfp = DT_DYN_CTFP(dtp); 645 dtt.dtt_type = ctf_add_typedef(DT_DYN_CTFP(dtp), 646 CTF_ADD_ROOT, tag, DT_DYN_TYPE(dtp)); 647 648 if (dtt.dtt_type == CTF_ERR || 649 ctf_update(dtt.dtt_ctfp) == CTF_ERR) { 650 xyerror(D_UNKNOWN, "cannot define type %s: %s\n", 651 tag, ctf_errmsg(ctf_errno(dtt.dtt_ctfp))); 652 } 653 } 654 655 bzero(dnp, sizeof (dt_node_t)); 656 dnp->dn_kind = DT_NODE_TYPE; 657 658 dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE); 659 dt_node_attr_assign(dnp, _dtrace_defattr); 660 661 return (dnp); 662} 663 664/*ARGSUSED*/ 665static int 666dt_probe_desc(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *arg) 667{ 668 if (((dtrace_probedesc_t *)arg)->dtpd_id == DTRACE_IDNONE) { 669 bcopy(pdp, arg, sizeof (dtrace_probedesc_t)); 670 return (0); 671 } 672 673 return (1); 674} 675 676dt_probe_t * 677dt_probe_info(dtrace_hdl_t *dtp, 678 const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip) 679{ 680 int m_is_glob = pdp->dtpd_mod[0] == '\0' || strisglob(pdp->dtpd_mod); 681 int f_is_glob = pdp->dtpd_func[0] == '\0' || strisglob(pdp->dtpd_func); 682 int n_is_glob = pdp->dtpd_name[0] == '\0' || strisglob(pdp->dtpd_name); 683 684 dt_probe_t *prp = NULL; 685 const dtrace_pattr_t *pap; 686 dt_provider_t *pvp; 687 dt_ident_t *idp; 688 689 /* 690 * Attempt to lookup the probe in our existing cache for this provider. 691 * If none is found and an explicit probe ID was specified, discover 692 * that specific probe and cache its description and arguments. 693 */ 694 if ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) != NULL) { 695 size_t keylen = dt_probe_keylen(pdp); 696 char *key = dt_probe_key(pdp, alloca(keylen)); 697 698 if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL) 699 prp = idp->di_data; 700 else if (pdp->dtpd_id != DTRACE_IDNONE) 701 prp = dt_probe_discover(pvp, pdp); 702 } 703 704 /* 705 * If no probe was found in our cache, convert the caller's partial 706 * probe description into a fully-formed matching probe description by 707 * iterating over up to at most two probes that match 'pdp'. We then 708 * call dt_probe_discover() on the resulting probe identifier. 709 */ 710 if (prp == NULL) { 711 dtrace_probedesc_t pd; 712 int m; 713 714 bzero(&pd, sizeof (pd)); 715 pd.dtpd_id = DTRACE_IDNONE; 716 717 /* 718 * Call dtrace_probe_iter() to find matching probes. Our 719 * dt_probe_desc() callback will produce the following results: 720 * 721 * m < 0 dtrace_probe_iter() found zero matches (or failed). 722 * m > 0 dtrace_probe_iter() found more than one match. 723 * m = 0 dtrace_probe_iter() found exactly one match. 724 */ 725 if ((m = dtrace_probe_iter(dtp, pdp, dt_probe_desc, &pd)) < 0) 726 return (NULL); /* dt_errno is set for us */ 727 728 if ((pvp = dt_provider_lookup(dtp, pd.dtpd_provider)) == NULL) 729 return (NULL); /* dt_errno is set for us */ 730 731 /* 732 * If more than one probe was matched, then do not report probe 733 * information if either of the following conditions is true: 734 * 735 * (a) The Arguments Data stability of the matched provider is 736 * less than Evolving. 737 * 738 * (b) Any description component that is at least Evolving is 739 * empty or is specified using a globbing expression. 740 * 741 * These conditions imply that providers that provide Evolving 742 * or better Arguments Data stability must guarantee that all 743 * probes with identical field names in a field of Evolving or 744 * better Name stability have identical argument signatures. 745 */ 746 if (m > 0) { 747 if (pvp->pv_desc.dtvd_attr.dtpa_args.dtat_data < 748 DTRACE_STABILITY_EVOLVING) { 749 (void) dt_set_errno(dtp, EDT_UNSTABLE); 750 return (NULL); 751 } 752 753 754 if (pvp->pv_desc.dtvd_attr.dtpa_mod.dtat_name >= 755 DTRACE_STABILITY_EVOLVING && m_is_glob) { 756 (void) dt_set_errno(dtp, EDT_UNSTABLE); 757 return (NULL); 758 } 759 760 if (pvp->pv_desc.dtvd_attr.dtpa_func.dtat_name >= 761 DTRACE_STABILITY_EVOLVING && f_is_glob) { 762 (void) dt_set_errno(dtp, EDT_UNSTABLE); 763 return (NULL); 764 } 765 766 if (pvp->pv_desc.dtvd_attr.dtpa_name.dtat_name >= 767 DTRACE_STABILITY_EVOLVING && n_is_glob) { 768 (void) dt_set_errno(dtp, EDT_UNSTABLE); 769 return (NULL); 770 } 771 } 772 773 /* 774 * If we matched a probe exported by dtrace(7D), then discover 775 * the real attributes. Otherwise grab the static declaration. 776 */ 777 if (pd.dtpd_id != DTRACE_IDNONE) 778 prp = dt_probe_discover(pvp, &pd); 779 else 780 prp = dt_probe_lookup(pvp, pd.dtpd_name); 781 782 if (prp == NULL) 783 return (NULL); /* dt_errno is set for us */ 784 } 785 786 assert(pvp != NULL && prp != NULL); 787 788 /* 789 * Compute the probe description attributes by taking the minimum of 790 * the attributes of the specified fields. If no provider is specified 791 * or a glob pattern is used for the provider, use Unstable attributes. 792 */ 793 if (pdp->dtpd_provider[0] == '\0' || strisglob(pdp->dtpd_provider)) 794 pap = &_dtrace_prvdesc; 795 else 796 pap = &pvp->pv_desc.dtvd_attr; 797 798 pip->dtp_attr = pap->dtpa_provider; 799 800 if (!m_is_glob) 801 pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_mod); 802 if (!f_is_glob) 803 pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_func); 804 if (!n_is_glob) 805 pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_name); 806 807 pip->dtp_arga = pap->dtpa_args; 808 pip->dtp_argv = prp->pr_argv; 809 pip->dtp_argc = prp->pr_argc; 810 811 return (prp); 812} 813 814int 815dtrace_probe_info(dtrace_hdl_t *dtp, 816 const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip) 817{ 818 return (dt_probe_info(dtp, pdp, pip) != NULL ? 0 : -1); 819} 820 821/*ARGSUSED*/ 822static int 823dt_probe_iter(dt_idhash_t *ihp, dt_ident_t *idp, dt_probe_iter_t *pit) 824{ 825 const dt_probe_t *prp = idp->di_data; 826 827 if (!dt_gmatch(prp->pr_name, pit->pit_pat)) 828 return (0); /* continue on and examine next probe in hash */ 829 830 (void) strlcpy(pit->pit_desc.dtpd_name, prp->pr_name, DTRACE_NAMELEN); 831 pit->pit_desc.dtpd_id = idp->di_id; 832 pit->pit_matches++; 833 834 return (pit->pit_func(pit->pit_hdl, &pit->pit_desc, pit->pit_arg)); 835} 836 837int 838dtrace_probe_iter(dtrace_hdl_t *dtp, 839 const dtrace_probedesc_t *pdp, dtrace_probe_f *func, void *arg) 840{ 841 const char *provider = pdp ? pdp->dtpd_provider : NULL; 842 dtrace_id_t id = DTRACE_IDNONE; 843 844 dtrace_probedesc_t pd; 845 dt_probe_iter_t pit; 846 int cmd, rv; 847 848 bzero(&pit, sizeof (pit)); 849 pit.pit_hdl = dtp; 850 pit.pit_func = func; 851 pit.pit_arg = arg; 852 pit.pit_pat = pdp ? pdp->dtpd_name : NULL; 853 854 for (pit.pit_pvp = dt_list_next(&dtp->dt_provlist); 855 pit.pit_pvp != NULL; pit.pit_pvp = dt_list_next(pit.pit_pvp)) { 856 857 if (pit.pit_pvp->pv_flags & DT_PROVIDER_IMPL) 858 continue; /* we'll get these later using dt_ioctl() */ 859 860 if (!dt_gmatch(pit.pit_pvp->pv_desc.dtvd_name, provider)) 861 continue; 862 863 (void) strlcpy(pit.pit_desc.dtpd_provider, 864 pit.pit_pvp->pv_desc.dtvd_name, DTRACE_PROVNAMELEN); 865 866 if ((rv = dt_idhash_iter(pit.pit_pvp->pv_probes, 867 (dt_idhash_f *)dt_probe_iter, &pit)) != 0) 868 return (rv); 869 } 870 871 if (pdp != NULL) 872 cmd = DTRACEIOC_PROBEMATCH; 873 else 874 cmd = DTRACEIOC_PROBES; 875 876 for (;;) { 877 if (pdp != NULL) 878 bcopy(pdp, &pd, sizeof (pd)); 879 880 pd.dtpd_id = id; 881 882 if (dt_ioctl(dtp, cmd, &pd) != 0) 883 break; 884 else if ((rv = func(dtp, &pd, arg)) != 0) 885 return (rv); 886 887 pit.pit_matches++; 888 id = pd.dtpd_id + 1; 889 } 890 891 switch (errno) { 892 case ESRCH: 893 case EBADF: 894 return (pit.pit_matches ? 0 : dt_set_errno(dtp, EDT_NOPROBE)); 895 case EINVAL: 896 return (dt_set_errno(dtp, EDT_BADPGLOB)); 897 default: 898 return (dt_set_errno(dtp, errno)); 899 } 900} 901