10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 22*1399Sahl 230Sstevel@tonic-gate /* 24*1399Sahl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 250Sstevel@tonic-gate * Use is subject to license terms. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <unistd.h> 310Sstevel@tonic-gate #include <strings.h> 320Sstevel@tonic-gate #include <stdlib.h> 330Sstevel@tonic-gate #include <errno.h> 340Sstevel@tonic-gate #include <assert.h> 35*1399Sahl #include <ctype.h> 36*1399Sahl #include <alloca.h> 370Sstevel@tonic-gate 380Sstevel@tonic-gate #include <dt_impl.h> 39265Smws #include <dt_program.h> 400Sstevel@tonic-gate #include <dt_printf.h> 41*1399Sahl #include <dt_provider.h> 420Sstevel@tonic-gate 430Sstevel@tonic-gate dtrace_prog_t * 44265Smws dt_program_create(dtrace_hdl_t *dtp) 450Sstevel@tonic-gate { 46265Smws dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t)); 470Sstevel@tonic-gate 480Sstevel@tonic-gate if (pgp != NULL) 490Sstevel@tonic-gate dt_list_append(&dtp->dt_programs, pgp); 500Sstevel@tonic-gate else 510Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 520Sstevel@tonic-gate 530Sstevel@tonic-gate return (pgp); 540Sstevel@tonic-gate } 550Sstevel@tonic-gate 560Sstevel@tonic-gate void 57265Smws dt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) 580Sstevel@tonic-gate { 590Sstevel@tonic-gate dt_stmt_t *stp, *next; 60265Smws uint_t i; 610Sstevel@tonic-gate 620Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 630Sstevel@tonic-gate next = dt_list_next(stp); 64265Smws dtrace_stmt_destroy(dtp, stp->ds_desc); 65265Smws dt_free(dtp, stp); 660Sstevel@tonic-gate } 670Sstevel@tonic-gate 68265Smws for (i = 0; i < pgp->dp_xrefslen; i++) 69265Smws dt_free(dtp, pgp->dp_xrefs[i]); 70265Smws 71265Smws dt_free(dtp, pgp->dp_xrefs); 720Sstevel@tonic-gate dt_list_delete(&dtp->dt_programs, pgp); 73265Smws dt_free(dtp, pgp); 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate /*ARGSUSED*/ 770Sstevel@tonic-gate void 780Sstevel@tonic-gate dtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 790Sstevel@tonic-gate dtrace_proginfo_t *pip) 800Sstevel@tonic-gate { 810Sstevel@tonic-gate dt_stmt_t *stp; 820Sstevel@tonic-gate dtrace_actdesc_t *ap; 830Sstevel@tonic-gate dtrace_ecbdesc_t *last = NULL; 840Sstevel@tonic-gate 850Sstevel@tonic-gate if (pip == NULL) 860Sstevel@tonic-gate return; 870Sstevel@tonic-gate 880Sstevel@tonic-gate bzero(pip, sizeof (dtrace_proginfo_t)); 890Sstevel@tonic-gate 900Sstevel@tonic-gate if (dt_list_next(&pgp->dp_stmts) != NULL) { 910Sstevel@tonic-gate pip->dpi_descattr = _dtrace_maxattr; 920Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_maxattr; 930Sstevel@tonic-gate } else { 940Sstevel@tonic-gate pip->dpi_descattr = _dtrace_defattr; 950Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_defattr; 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) { 990Sstevel@tonic-gate dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate if (edp == last) 1020Sstevel@tonic-gate continue; 1030Sstevel@tonic-gate last = edp; 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate pip->dpi_descattr = 1060Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr); 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate pip->dpi_stmtattr = 1090Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr); 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* 1120Sstevel@tonic-gate * If there aren't any actions, account for the fact that 1130Sstevel@tonic-gate * recording the epid will generate a record. 1140Sstevel@tonic-gate */ 1150Sstevel@tonic-gate if (edp->dted_action == NULL) 1160Sstevel@tonic-gate pip->dpi_recgens++; 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 1190Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_SPECULATE) { 1200Sstevel@tonic-gate pip->dpi_speculations++; 1210Sstevel@tonic-gate continue; 1220Sstevel@tonic-gate } 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate if (DTRACEACT_ISAGG(ap->dtad_kind)) { 1250Sstevel@tonic-gate pip->dpi_recgens -= ap->dtad_arg; 1260Sstevel@tonic-gate pip->dpi_aggregates++; 1270Sstevel@tonic-gate continue; 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind)) 1310Sstevel@tonic-gate continue; 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_DIFEXPR && 1340Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_kind == 1350Sstevel@tonic-gate DIF_TYPE_CTF && 1360Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_size == 0) 1370Sstevel@tonic-gate continue; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate pip->dpi_recgens++; 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate int 1450Sstevel@tonic-gate dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 1460Sstevel@tonic-gate dtrace_proginfo_t *pip) 1470Sstevel@tonic-gate { 1480Sstevel@tonic-gate void *dof; 1490Sstevel@tonic-gate int n, err; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate dtrace_program_info(dtp, pgp, pip); 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL) 1540Sstevel@tonic-gate return (-1); 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate n = dt_ioctl(dtp, DTRACEIOC_ENABLE, dof); 1570Sstevel@tonic-gate dtrace_dof_destroy(dtp, dof); 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate if (n == -1) { 1600Sstevel@tonic-gate switch (errno) { 1610Sstevel@tonic-gate case EINVAL: 1620Sstevel@tonic-gate err = EDT_DIFINVAL; 1630Sstevel@tonic-gate break; 1640Sstevel@tonic-gate case EFAULT: 1650Sstevel@tonic-gate err = EDT_DIFFAULT; 1660Sstevel@tonic-gate break; 1670Sstevel@tonic-gate case E2BIG: 1680Sstevel@tonic-gate err = EDT_DIFSIZE; 1690Sstevel@tonic-gate break; 1700Sstevel@tonic-gate default: 1710Sstevel@tonic-gate err = errno; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate return (dt_set_errno(dtp, err)); 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate if (pip != NULL) 1780Sstevel@tonic-gate pip->dpi_matches += n; 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate return (0); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 183265Smws static void 184265Smws dt_ecbdesc_hold(dtrace_ecbdesc_t *edp) 1850Sstevel@tonic-gate { 1860Sstevel@tonic-gate edp->dted_refcnt++; 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate void 190265Smws dt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 1910Sstevel@tonic-gate { 1920Sstevel@tonic-gate if (--edp->dted_refcnt > 0) 1930Sstevel@tonic-gate return; 1940Sstevel@tonic-gate 195265Smws dt_difo_free(dtp, edp->dted_pred.dtpdd_difo); 1960Sstevel@tonic-gate assert(edp->dted_action == NULL); 197265Smws dt_free(dtp, edp); 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate dtrace_ecbdesc_t * 201265Smws dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp) 2020Sstevel@tonic-gate { 2030Sstevel@tonic-gate dtrace_ecbdesc_t *edp; 2040Sstevel@tonic-gate 205265Smws if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) { 2060Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 2070Sstevel@tonic-gate return (NULL); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate edp->dted_probe = *pdp; 211265Smws dt_ecbdesc_hold(edp); 2120Sstevel@tonic-gate return (edp); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate dtrace_stmtdesc_t * 2160Sstevel@tonic-gate dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 2170Sstevel@tonic-gate { 2180Sstevel@tonic-gate dtrace_stmtdesc_t *sdp; 2190Sstevel@tonic-gate 220265Smws if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL) 2210Sstevel@tonic-gate return (NULL); 2220Sstevel@tonic-gate 223265Smws dt_ecbdesc_hold(edp); 2240Sstevel@tonic-gate sdp->dtsd_ecbdesc = edp; 2250Sstevel@tonic-gate sdp->dtsd_descattr = _dtrace_defattr; 2260Sstevel@tonic-gate sdp->dtsd_stmtattr = _dtrace_defattr; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate return (sdp); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate dtrace_actdesc_t * 2320Sstevel@tonic-gate dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 2330Sstevel@tonic-gate { 2340Sstevel@tonic-gate dtrace_actdesc_t *new; 2350Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 2360Sstevel@tonic-gate 237265Smws if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL) 2380Sstevel@tonic-gate return (NULL); 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate if (sdp->dtsd_action_last != NULL) { 2410Sstevel@tonic-gate assert(sdp->dtsd_action != NULL); 2420Sstevel@tonic-gate assert(sdp->dtsd_action_last->dtad_next == NULL); 2430Sstevel@tonic-gate sdp->dtsd_action_last->dtad_next = new; 2440Sstevel@tonic-gate } else { 2450Sstevel@tonic-gate dtrace_actdesc_t *ap = edp->dted_action; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate assert(sdp->dtsd_action == NULL); 2480Sstevel@tonic-gate sdp->dtsd_action = new; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate while (ap != NULL && ap->dtad_next != NULL) 2510Sstevel@tonic-gate ap = ap->dtad_next; 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate if (ap == NULL) 2540Sstevel@tonic-gate edp->dted_action = new; 2550Sstevel@tonic-gate else 2560Sstevel@tonic-gate ap->dtad_next = new; 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate sdp->dtsd_action_last = new; 2600Sstevel@tonic-gate bzero(new, sizeof (dtrace_actdesc_t)); 2610Sstevel@tonic-gate new->dtad_uarg = (uintptr_t)sdp; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate return (new); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate int 2670Sstevel@tonic-gate dtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp) 2680Sstevel@tonic-gate { 269265Smws dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t)); 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate if (stp == NULL) 272265Smws return (-1); /* errno is set for us */ 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate dt_list_append(&pgp->dp_stmts, stp); 2750Sstevel@tonic-gate stp->ds_desc = sdp; 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate return (0); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate int 2810Sstevel@tonic-gate dtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 2820Sstevel@tonic-gate dtrace_stmt_f *func, void *data) 2830Sstevel@tonic-gate { 2840Sstevel@tonic-gate dt_stmt_t *stp, *next; 2850Sstevel@tonic-gate int status = 0; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 2880Sstevel@tonic-gate next = dt_list_next(stp); 2890Sstevel@tonic-gate if ((status = func(dtp, pgp, stp->ds_desc, data)) != 0) 2900Sstevel@tonic-gate break; 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate return (status); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate void 297265Smws dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 2980Sstevel@tonic-gate { 2990Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate /* 3020Sstevel@tonic-gate * We need to remove any actions that we have on this ECB, and 3030Sstevel@tonic-gate * remove our hold on the ECB itself. 3040Sstevel@tonic-gate */ 3050Sstevel@tonic-gate if (sdp->dtsd_action != NULL) { 3060Sstevel@tonic-gate dtrace_actdesc_t *last = sdp->dtsd_action_last; 3070Sstevel@tonic-gate dtrace_actdesc_t *ap, *next; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate assert(last != NULL); 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 3120Sstevel@tonic-gate if (ap == sdp->dtsd_action) 3130Sstevel@tonic-gate break; 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate if (ap->dtad_next == sdp->dtsd_action) 3160Sstevel@tonic-gate break; 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate assert(ap != NULL); 3200Sstevel@tonic-gate 321265Smws if (ap == edp->dted_action) 3220Sstevel@tonic-gate edp->dted_action = last->dtad_next; 323265Smws else 3240Sstevel@tonic-gate ap->dtad_next = last->dtad_next; 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /* 3270Sstevel@tonic-gate * We have now removed our action list from its ECB; we can 3280Sstevel@tonic-gate * safely destroy the list. 3290Sstevel@tonic-gate */ 3300Sstevel@tonic-gate last->dtad_next = NULL; 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate for (ap = sdp->dtsd_action; ap != NULL; ap = next) { 3330Sstevel@tonic-gate assert(ap->dtad_uarg == (uintptr_t)sdp); 334265Smws dt_difo_free(dtp, ap->dtad_difo); 3350Sstevel@tonic-gate next = ap->dtad_next; 336265Smws dt_free(dtp, ap); 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL) 3410Sstevel@tonic-gate dt_printf_destroy(sdp->dtsd_fmtdata); 3420Sstevel@tonic-gate 343265Smws dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc); 344265Smws dt_free(dtp, sdp); 3450Sstevel@tonic-gate } 346*1399Sahl 347*1399Sahl typedef struct dt_header_info { 348*1399Sahl dtrace_hdl_t *dthi_dtp; /* consumer handle */ 349*1399Sahl FILE *dthi_out; /* output file */ 350*1399Sahl char *dthi_pmname; /* provider macro name */ 351*1399Sahl char *dthi_pfname; /* provider function name */ 352*1399Sahl } dt_header_info_t; 353*1399Sahl 354*1399Sahl 355*1399Sahl static void 356*1399Sahl dt_header_fmt_macro(char *buf, const char *str) 357*1399Sahl { 358*1399Sahl for (;;) { 359*1399Sahl if (islower(*str)) { 360*1399Sahl *buf++ = *str++ + 'A' - 'a'; 361*1399Sahl } else if (*str == '-') { 362*1399Sahl *buf++ = '_'; 363*1399Sahl str++; 364*1399Sahl } else if (*str == '.') { 365*1399Sahl *buf++ = '_'; 366*1399Sahl str++; 367*1399Sahl } else if ((*buf++ = *str++) == '\0') { 368*1399Sahl break; 369*1399Sahl } 370*1399Sahl } 371*1399Sahl } 372*1399Sahl 373*1399Sahl static void 374*1399Sahl dt_header_fmt_func(char *buf, const char *str) 375*1399Sahl { 376*1399Sahl for (;;) { 377*1399Sahl if (*str == '-') { 378*1399Sahl *buf++ = '_'; 379*1399Sahl *buf++ = '_'; 380*1399Sahl str++; 381*1399Sahl } else if ((*buf++ = *str++) == '\0') { 382*1399Sahl break; 383*1399Sahl } 384*1399Sahl } 385*1399Sahl } 386*1399Sahl 387*1399Sahl /*ARGSUSED*/ 388*1399Sahl static int 389*1399Sahl dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 390*1399Sahl { 391*1399Sahl dt_header_info_t *infop = data; 392*1399Sahl dtrace_hdl_t *dtp = infop->dthi_dtp; 393*1399Sahl dt_probe_t *prp = idp->di_data; 394*1399Sahl dt_node_t *dnp; 395*1399Sahl char buf[DT_TYPE_NAMELEN]; 396*1399Sahl char *fname; 397*1399Sahl const char *p; 398*1399Sahl int i; 399*1399Sahl 400*1399Sahl p = prp->pr_name; 401*1399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 402*1399Sahl p++; 403*1399Sahl 404*1399Sahl fname = alloca(strlen(prp->pr_name) + 1 + i); 405*1399Sahl dt_header_fmt_func(fname, prp->pr_name); 406*1399Sahl 407*1399Sahl if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(", 408*1399Sahl infop->dthi_pfname, fname) < 0) 409*1399Sahl return (dt_set_errno(dtp, errno)); 410*1399Sahl 411*1399Sahl for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) { 412*1399Sahl if (fprintf(infop->dthi_out, "%s", 413*1399Sahl ctf_type_name(dnp->dn_ctfp, dnp->dn_type, 414*1399Sahl buf, sizeof (buf))) < 0) 415*1399Sahl return (dt_set_errno(dtp, errno)); 416*1399Sahl 417*1399Sahl if (i + 1 != prp->pr_nargc && 418*1399Sahl fprintf(infop->dthi_out, ", ") < 0) 419*1399Sahl return (dt_set_errno(dtp, errno)); 420*1399Sahl } 421*1399Sahl 422*1399Sahl if (i == 0 && fprintf(infop->dthi_out, "void") < 0) 423*1399Sahl return (dt_set_errno(dtp, errno)); 424*1399Sahl 425*1399Sahl if (fprintf(infop->dthi_out, ");\n") < 0) 426*1399Sahl return (dt_set_errno(dtp, errno)); 427*1399Sahl 428*1399Sahl return (0); 429*1399Sahl } 430*1399Sahl 431*1399Sahl /*ARGSUSED*/ 432*1399Sahl static int 433*1399Sahl dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 434*1399Sahl { 435*1399Sahl dt_header_info_t *infop = data; 436*1399Sahl dtrace_hdl_t *dtp = infop->dthi_dtp; 437*1399Sahl dt_probe_t *prp = idp->di_data; 438*1399Sahl char *mname, *fname; 439*1399Sahl const char *p; 440*1399Sahl int i; 441*1399Sahl 442*1399Sahl p = prp->pr_name; 443*1399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 444*1399Sahl p++; 445*1399Sahl 446*1399Sahl mname = alloca(strlen(prp->pr_name) + 1); 447*1399Sahl dt_header_fmt_macro(mname, prp->pr_name); 448*1399Sahl 449*1399Sahl fname = alloca(strlen(prp->pr_name) + 1 + i); 450*1399Sahl dt_header_fmt_func(fname, prp->pr_name); 451*1399Sahl 452*1399Sahl if (fprintf(infop->dthi_out, "#define\t%s_%s(", 453*1399Sahl infop->dthi_pmname, mname) < 0) 454*1399Sahl return (dt_set_errno(dtp, errno)); 455*1399Sahl 456*1399Sahl for (i = 0; i < prp->pr_nargc; i++) { 457*1399Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0) 458*1399Sahl return (dt_set_errno(dtp, errno)); 459*1399Sahl 460*1399Sahl if (i + 1 != prp->pr_nargc && 461*1399Sahl fprintf(infop->dthi_out, ", ") < 0) 462*1399Sahl return (dt_set_errno(dtp, errno)); 463*1399Sahl } 464*1399Sahl 465*1399Sahl if (fprintf(infop->dthi_out, ") \\\n\t") < 0) 466*1399Sahl return (dt_set_errno(dtp, errno)); 467*1399Sahl 468*1399Sahl if (fprintf(infop->dthi_out, "__dtrace_%s___%s(", 469*1399Sahl infop->dthi_pfname, fname) < 0) 470*1399Sahl return (dt_set_errno(dtp, errno)); 471*1399Sahl 472*1399Sahl for (i = 0; i < prp->pr_nargc; i++) { 473*1399Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0) 474*1399Sahl return (dt_set_errno(dtp, errno)); 475*1399Sahl 476*1399Sahl if (i + 1 != prp->pr_nargc && 477*1399Sahl fprintf(infop->dthi_out, ", ") < 0) 478*1399Sahl return (dt_set_errno(dtp, errno)); 479*1399Sahl } 480*1399Sahl 481*1399Sahl if (fprintf(infop->dthi_out, ")\n") < 0) 482*1399Sahl return (dt_set_errno(dtp, errno)); 483*1399Sahl 484*1399Sahl return (0); 485*1399Sahl } 486*1399Sahl 487*1399Sahl static int 488*1399Sahl dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out) 489*1399Sahl { 490*1399Sahl dt_header_info_t info; 491*1399Sahl const char *p; 492*1399Sahl int i; 493*1399Sahl 494*1399Sahl if (pvp->pv_flags & DT_PROVIDER_IMPL) 495*1399Sahl return (0); 496*1399Sahl 497*1399Sahl p = pvp->pv_desc.dtvd_name; 498*1399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 499*1399Sahl p++; 500*1399Sahl 501*1399Sahl info.dthi_dtp = dtp; 502*1399Sahl info.dthi_out = out; 503*1399Sahl 504*1399Sahl info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1); 505*1399Sahl dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name); 506*1399Sahl 507*1399Sahl info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i); 508*1399Sahl dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name); 509*1399Sahl 510*1399Sahl 511*1399Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 512*1399Sahl return (-1); /* dt_errno is set for us */ 513*1399Sahl if (fprintf(out, "\n\n") < 0) 514*1399Sahl return (dt_set_errno(dtp, errno)); 515*1399Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0) 516*1399Sahl return (-1); /* dt_errno is set for us */ 517*1399Sahl 518*1399Sahl return (0); 519*1399Sahl } 520*1399Sahl 521*1399Sahl int 522*1399Sahl dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname) 523*1399Sahl { 524*1399Sahl dt_provider_t *pvp; 525*1399Sahl char *mfname, *p; 526*1399Sahl 527*1399Sahl if (fname != NULL) { 528*1399Sahl if ((p = strrchr(fname, '/')) != NULL) 529*1399Sahl fname = p + 1; 530*1399Sahl 531*1399Sahl mfname = alloca(strlen(fname) + 1); 532*1399Sahl dt_header_fmt_macro(mfname, fname); 533*1399Sahl if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n", 534*1399Sahl mfname, mfname) < 0) 535*1399Sahl return (dt_set_errno(dtp, errno)); 536*1399Sahl } 537*1399Sahl 538*1399Sahl if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0) 539*1399Sahl return (-1); 540*1399Sahl 541*1399Sahl for (pvp = dt_list_next(&dtp->dt_provlist); 542*1399Sahl pvp != NULL; pvp = dt_list_next(pvp)) { 543*1399Sahl if (dt_header_provider(dtp, pvp, out) != 0) 544*1399Sahl return (-1); /* dt_errno is set for us */ 545*1399Sahl } 546*1399Sahl 547*1399Sahl if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0) 548*1399Sahl return (dt_set_errno(dtp, errno)); 549*1399Sahl 550*1399Sahl if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0) 551*1399Sahl return (dt_set_errno(dtp, errno)); 552*1399Sahl 553*1399Sahl return (0); 554*1399Sahl } 555