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 51710Sahl * Common Development and Distribution License (the "License"). 61710Sahl * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211399Sahl 220Sstevel@tonic-gate /* 23*8803SJonathan.Haslam@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <unistd.h> 280Sstevel@tonic-gate #include <strings.h> 290Sstevel@tonic-gate #include <stdlib.h> 300Sstevel@tonic-gate #include <errno.h> 310Sstevel@tonic-gate #include <assert.h> 321399Sahl #include <ctype.h> 331399Sahl #include <alloca.h> 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <dt_impl.h> 36265Smws #include <dt_program.h> 370Sstevel@tonic-gate #include <dt_printf.h> 381399Sahl #include <dt_provider.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate dtrace_prog_t * 41265Smws dt_program_create(dtrace_hdl_t *dtp) 420Sstevel@tonic-gate { 43265Smws dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t)); 440Sstevel@tonic-gate 450Sstevel@tonic-gate if (pgp != NULL) 460Sstevel@tonic-gate dt_list_append(&dtp->dt_programs, pgp); 470Sstevel@tonic-gate else 480Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 490Sstevel@tonic-gate 501710Sahl /* 511710Sahl * By default, programs start with DOF version 1 so that output files 521710Sahl * containing DOF are backward compatible. If a program requires new 531710Sahl * DOF features, the version is increased as needed. 541710Sahl */ 551710Sahl pgp->dp_dofversion = DOF_VERSION_1; 561710Sahl 570Sstevel@tonic-gate return (pgp); 580Sstevel@tonic-gate } 590Sstevel@tonic-gate 600Sstevel@tonic-gate void 61265Smws dt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) 620Sstevel@tonic-gate { 630Sstevel@tonic-gate dt_stmt_t *stp, *next; 64265Smws uint_t i; 650Sstevel@tonic-gate 660Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 670Sstevel@tonic-gate next = dt_list_next(stp); 68265Smws dtrace_stmt_destroy(dtp, stp->ds_desc); 69265Smws dt_free(dtp, stp); 700Sstevel@tonic-gate } 710Sstevel@tonic-gate 72265Smws for (i = 0; i < pgp->dp_xrefslen; i++) 73265Smws dt_free(dtp, pgp->dp_xrefs[i]); 74265Smws 75265Smws dt_free(dtp, pgp->dp_xrefs); 760Sstevel@tonic-gate dt_list_delete(&dtp->dt_programs, pgp); 77265Smws dt_free(dtp, pgp); 780Sstevel@tonic-gate } 790Sstevel@tonic-gate 800Sstevel@tonic-gate /*ARGSUSED*/ 810Sstevel@tonic-gate void 820Sstevel@tonic-gate dtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 830Sstevel@tonic-gate dtrace_proginfo_t *pip) 840Sstevel@tonic-gate { 850Sstevel@tonic-gate dt_stmt_t *stp; 860Sstevel@tonic-gate dtrace_actdesc_t *ap; 870Sstevel@tonic-gate dtrace_ecbdesc_t *last = NULL; 880Sstevel@tonic-gate 890Sstevel@tonic-gate if (pip == NULL) 900Sstevel@tonic-gate return; 910Sstevel@tonic-gate 920Sstevel@tonic-gate bzero(pip, sizeof (dtrace_proginfo_t)); 930Sstevel@tonic-gate 940Sstevel@tonic-gate if (dt_list_next(&pgp->dp_stmts) != NULL) { 950Sstevel@tonic-gate pip->dpi_descattr = _dtrace_maxattr; 960Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_maxattr; 970Sstevel@tonic-gate } else { 980Sstevel@tonic-gate pip->dpi_descattr = _dtrace_defattr; 990Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_defattr; 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) { 1030Sstevel@tonic-gate dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc; 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate if (edp == last) 1060Sstevel@tonic-gate continue; 1070Sstevel@tonic-gate last = edp; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate pip->dpi_descattr = 1100Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr); 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate pip->dpi_stmtattr = 1130Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr); 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* 1160Sstevel@tonic-gate * If there aren't any actions, account for the fact that 1170Sstevel@tonic-gate * recording the epid will generate a record. 1180Sstevel@tonic-gate */ 1190Sstevel@tonic-gate if (edp->dted_action == NULL) 1200Sstevel@tonic-gate pip->dpi_recgens++; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 1230Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_SPECULATE) { 1240Sstevel@tonic-gate pip->dpi_speculations++; 1250Sstevel@tonic-gate continue; 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate if (DTRACEACT_ISAGG(ap->dtad_kind)) { 1290Sstevel@tonic-gate pip->dpi_recgens -= ap->dtad_arg; 1300Sstevel@tonic-gate pip->dpi_aggregates++; 1310Sstevel@tonic-gate continue; 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind)) 1350Sstevel@tonic-gate continue; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_DIFEXPR && 1380Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_kind == 1390Sstevel@tonic-gate DIF_TYPE_CTF && 1400Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_size == 0) 1410Sstevel@tonic-gate continue; 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate pip->dpi_recgens++; 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate int 1490Sstevel@tonic-gate dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 1500Sstevel@tonic-gate dtrace_proginfo_t *pip) 1510Sstevel@tonic-gate { 1520Sstevel@tonic-gate void *dof; 1530Sstevel@tonic-gate int n, err; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate dtrace_program_info(dtp, pgp, pip); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL) 1580Sstevel@tonic-gate return (-1); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate n = dt_ioctl(dtp, DTRACEIOC_ENABLE, dof); 1610Sstevel@tonic-gate dtrace_dof_destroy(dtp, dof); 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate if (n == -1) { 1640Sstevel@tonic-gate switch (errno) { 1650Sstevel@tonic-gate case EINVAL: 1660Sstevel@tonic-gate err = EDT_DIFINVAL; 1670Sstevel@tonic-gate break; 1680Sstevel@tonic-gate case EFAULT: 1690Sstevel@tonic-gate err = EDT_DIFFAULT; 1700Sstevel@tonic-gate break; 1710Sstevel@tonic-gate case E2BIG: 1720Sstevel@tonic-gate err = EDT_DIFSIZE; 1730Sstevel@tonic-gate break; 174*8803SJonathan.Haslam@Sun.COM case EBUSY: 175*8803SJonathan.Haslam@Sun.COM err = EDT_ENABLING_ERR; 176*8803SJonathan.Haslam@Sun.COM break; 1770Sstevel@tonic-gate default: 1780Sstevel@tonic-gate err = errno; 1790Sstevel@tonic-gate } 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate return (dt_set_errno(dtp, err)); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate if (pip != NULL) 1850Sstevel@tonic-gate pip->dpi_matches += n; 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate return (0); 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate 190265Smws static void 191265Smws dt_ecbdesc_hold(dtrace_ecbdesc_t *edp) 1920Sstevel@tonic-gate { 1930Sstevel@tonic-gate edp->dted_refcnt++; 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate void 197265Smws dt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 1980Sstevel@tonic-gate { 1990Sstevel@tonic-gate if (--edp->dted_refcnt > 0) 2000Sstevel@tonic-gate return; 2010Sstevel@tonic-gate 202265Smws dt_difo_free(dtp, edp->dted_pred.dtpdd_difo); 2030Sstevel@tonic-gate assert(edp->dted_action == NULL); 204265Smws dt_free(dtp, edp); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate dtrace_ecbdesc_t * 208265Smws dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp) 2090Sstevel@tonic-gate { 2100Sstevel@tonic-gate dtrace_ecbdesc_t *edp; 2110Sstevel@tonic-gate 212265Smws if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) { 2130Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 2140Sstevel@tonic-gate return (NULL); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate edp->dted_probe = *pdp; 218265Smws dt_ecbdesc_hold(edp); 2190Sstevel@tonic-gate return (edp); 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate dtrace_stmtdesc_t * 2230Sstevel@tonic-gate dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 2240Sstevel@tonic-gate { 2250Sstevel@tonic-gate dtrace_stmtdesc_t *sdp; 2260Sstevel@tonic-gate 227265Smws if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL) 2280Sstevel@tonic-gate return (NULL); 2290Sstevel@tonic-gate 230265Smws dt_ecbdesc_hold(edp); 2310Sstevel@tonic-gate sdp->dtsd_ecbdesc = edp; 2320Sstevel@tonic-gate sdp->dtsd_descattr = _dtrace_defattr; 2330Sstevel@tonic-gate sdp->dtsd_stmtattr = _dtrace_defattr; 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate return (sdp); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate dtrace_actdesc_t * 2390Sstevel@tonic-gate dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 2400Sstevel@tonic-gate { 2410Sstevel@tonic-gate dtrace_actdesc_t *new; 2420Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 2430Sstevel@tonic-gate 244265Smws if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL) 2450Sstevel@tonic-gate return (NULL); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate if (sdp->dtsd_action_last != NULL) { 2480Sstevel@tonic-gate assert(sdp->dtsd_action != NULL); 2490Sstevel@tonic-gate assert(sdp->dtsd_action_last->dtad_next == NULL); 2500Sstevel@tonic-gate sdp->dtsd_action_last->dtad_next = new; 2510Sstevel@tonic-gate } else { 2520Sstevel@tonic-gate dtrace_actdesc_t *ap = edp->dted_action; 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate assert(sdp->dtsd_action == NULL); 2550Sstevel@tonic-gate sdp->dtsd_action = new; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate while (ap != NULL && ap->dtad_next != NULL) 2580Sstevel@tonic-gate ap = ap->dtad_next; 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate if (ap == NULL) 2610Sstevel@tonic-gate edp->dted_action = new; 2620Sstevel@tonic-gate else 2630Sstevel@tonic-gate ap->dtad_next = new; 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate sdp->dtsd_action_last = new; 2670Sstevel@tonic-gate bzero(new, sizeof (dtrace_actdesc_t)); 2680Sstevel@tonic-gate new->dtad_uarg = (uintptr_t)sdp; 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate return (new); 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate int 2740Sstevel@tonic-gate dtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp) 2750Sstevel@tonic-gate { 276265Smws dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t)); 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate if (stp == NULL) 279265Smws return (-1); /* errno is set for us */ 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate dt_list_append(&pgp->dp_stmts, stp); 2820Sstevel@tonic-gate stp->ds_desc = sdp; 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate return (0); 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate int 2880Sstevel@tonic-gate dtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 2890Sstevel@tonic-gate dtrace_stmt_f *func, void *data) 2900Sstevel@tonic-gate { 2910Sstevel@tonic-gate dt_stmt_t *stp, *next; 2920Sstevel@tonic-gate int status = 0; 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 2950Sstevel@tonic-gate next = dt_list_next(stp); 2960Sstevel@tonic-gate if ((status = func(dtp, pgp, stp->ds_desc, data)) != 0) 2970Sstevel@tonic-gate break; 2980Sstevel@tonic-gate } 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate return (status); 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate void 304265Smws dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 3050Sstevel@tonic-gate { 3060Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * We need to remove any actions that we have on this ECB, and 3100Sstevel@tonic-gate * remove our hold on the ECB itself. 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate if (sdp->dtsd_action != NULL) { 3130Sstevel@tonic-gate dtrace_actdesc_t *last = sdp->dtsd_action_last; 3140Sstevel@tonic-gate dtrace_actdesc_t *ap, *next; 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate assert(last != NULL); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 3190Sstevel@tonic-gate if (ap == sdp->dtsd_action) 3200Sstevel@tonic-gate break; 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate if (ap->dtad_next == sdp->dtsd_action) 3230Sstevel@tonic-gate break; 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate assert(ap != NULL); 3270Sstevel@tonic-gate 328265Smws if (ap == edp->dted_action) 3290Sstevel@tonic-gate edp->dted_action = last->dtad_next; 330265Smws else 3310Sstevel@tonic-gate ap->dtad_next = last->dtad_next; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate /* 3340Sstevel@tonic-gate * We have now removed our action list from its ECB; we can 3350Sstevel@tonic-gate * safely destroy the list. 3360Sstevel@tonic-gate */ 3370Sstevel@tonic-gate last->dtad_next = NULL; 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate for (ap = sdp->dtsd_action; ap != NULL; ap = next) { 3400Sstevel@tonic-gate assert(ap->dtad_uarg == (uintptr_t)sdp); 341265Smws dt_difo_free(dtp, ap->dtad_difo); 3420Sstevel@tonic-gate next = ap->dtad_next; 343265Smws dt_free(dtp, ap); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL) 3480Sstevel@tonic-gate dt_printf_destroy(sdp->dtsd_fmtdata); 3490Sstevel@tonic-gate 350265Smws dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc); 351265Smws dt_free(dtp, sdp); 3520Sstevel@tonic-gate } 3531399Sahl 3541399Sahl typedef struct dt_header_info { 3551399Sahl dtrace_hdl_t *dthi_dtp; /* consumer handle */ 3561399Sahl FILE *dthi_out; /* output file */ 3571399Sahl char *dthi_pmname; /* provider macro name */ 3581399Sahl char *dthi_pfname; /* provider function name */ 3592769Sahl int dthi_empty; /* should we generate empty macros */ 3601399Sahl } dt_header_info_t; 3611399Sahl 3621399Sahl static void 3631399Sahl dt_header_fmt_macro(char *buf, const char *str) 3641399Sahl { 3651399Sahl for (;;) { 3661399Sahl if (islower(*str)) { 3671399Sahl *buf++ = *str++ + 'A' - 'a'; 3681399Sahl } else if (*str == '-') { 3691399Sahl *buf++ = '_'; 3701399Sahl str++; 3711399Sahl } else if (*str == '.') { 3721399Sahl *buf++ = '_'; 3731399Sahl str++; 3741399Sahl } else if ((*buf++ = *str++) == '\0') { 3751399Sahl break; 3761399Sahl } 3771399Sahl } 3781399Sahl } 3791399Sahl 3801399Sahl static void 3811399Sahl dt_header_fmt_func(char *buf, const char *str) 3821399Sahl { 3831399Sahl for (;;) { 3841399Sahl if (*str == '-') { 3851399Sahl *buf++ = '_'; 3861399Sahl *buf++ = '_'; 3871399Sahl str++; 3881399Sahl } else if ((*buf++ = *str++) == '\0') { 3891399Sahl break; 3901399Sahl } 3911399Sahl } 3921399Sahl } 3931399Sahl 3941399Sahl /*ARGSUSED*/ 3951399Sahl static int 3961399Sahl dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 3971399Sahl { 3981399Sahl dt_header_info_t *infop = data; 3991399Sahl dtrace_hdl_t *dtp = infop->dthi_dtp; 4001399Sahl dt_probe_t *prp = idp->di_data; 4011399Sahl dt_node_t *dnp; 4021399Sahl char buf[DT_TYPE_NAMELEN]; 4031399Sahl char *fname; 4041399Sahl const char *p; 4051399Sahl int i; 4061399Sahl 4071399Sahl p = prp->pr_name; 4081399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 4091399Sahl p++; 4101399Sahl 4111399Sahl fname = alloca(strlen(prp->pr_name) + 1 + i); 4121399Sahl dt_header_fmt_func(fname, prp->pr_name); 4131399Sahl 4141399Sahl if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(", 4151399Sahl infop->dthi_pfname, fname) < 0) 4161399Sahl return (dt_set_errno(dtp, errno)); 4171399Sahl 4181399Sahl for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) { 4191399Sahl if (fprintf(infop->dthi_out, "%s", 4201399Sahl ctf_type_name(dnp->dn_ctfp, dnp->dn_type, 4211399Sahl buf, sizeof (buf))) < 0) 4221399Sahl return (dt_set_errno(dtp, errno)); 4231399Sahl 4241399Sahl if (i + 1 != prp->pr_nargc && 4251399Sahl fprintf(infop->dthi_out, ", ") < 0) 4261399Sahl return (dt_set_errno(dtp, errno)); 4271399Sahl } 4281399Sahl 4291399Sahl if (i == 0 && fprintf(infop->dthi_out, "void") < 0) 4301399Sahl return (dt_set_errno(dtp, errno)); 4311399Sahl 4321399Sahl if (fprintf(infop->dthi_out, ");\n") < 0) 4331399Sahl return (dt_set_errno(dtp, errno)); 4341399Sahl 4356554Sahl if (fprintf(infop->dthi_out, 4366554Sahl "#ifndef\t__sparc\n" 4376554Sahl "extern int __dtraceenabled_%s___%s(void);\n" 4386554Sahl "#else\n" 4396554Sahl "extern int __dtraceenabled_%s___%s(long);\n" 4406554Sahl "#endif\n", 4416554Sahl infop->dthi_pfname, fname, infop->dthi_pfname, fname) < 0) 4421710Sahl return (dt_set_errno(dtp, errno)); 4431710Sahl 4441399Sahl return (0); 4451399Sahl } 4461399Sahl 4471399Sahl /*ARGSUSED*/ 4481399Sahl static int 4491399Sahl dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 4501399Sahl { 4511399Sahl dt_header_info_t *infop = data; 4521399Sahl dtrace_hdl_t *dtp = infop->dthi_dtp; 4531399Sahl dt_probe_t *prp = idp->di_data; 4541399Sahl char *mname, *fname; 4551399Sahl const char *p; 4561399Sahl int i; 4571399Sahl 4581399Sahl p = prp->pr_name; 4591399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 4601399Sahl p++; 4611399Sahl 4621399Sahl mname = alloca(strlen(prp->pr_name) + 1); 4631399Sahl dt_header_fmt_macro(mname, prp->pr_name); 4641399Sahl 4651399Sahl fname = alloca(strlen(prp->pr_name) + 1 + i); 4661399Sahl dt_header_fmt_func(fname, prp->pr_name); 4671399Sahl 4681399Sahl if (fprintf(infop->dthi_out, "#define\t%s_%s(", 4691399Sahl infop->dthi_pmname, mname) < 0) 4701399Sahl return (dt_set_errno(dtp, errno)); 4711399Sahl 4721399Sahl for (i = 0; i < prp->pr_nargc; i++) { 4731399Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0) 4741399Sahl return (dt_set_errno(dtp, errno)); 4751399Sahl 4761399Sahl if (i + 1 != prp->pr_nargc && 4771399Sahl fprintf(infop->dthi_out, ", ") < 0) 4781399Sahl return (dt_set_errno(dtp, errno)); 4791399Sahl } 4801399Sahl 4812769Sahl if (!infop->dthi_empty) { 4822769Sahl if (fprintf(infop->dthi_out, ") \\\n\t") < 0) 4832769Sahl return (dt_set_errno(dtp, errno)); 4841399Sahl 4852769Sahl if (fprintf(infop->dthi_out, "__dtrace_%s___%s(", 4862769Sahl infop->dthi_pfname, fname) < 0) 4871399Sahl return (dt_set_errno(dtp, errno)); 4881399Sahl 4892769Sahl for (i = 0; i < prp->pr_nargc; i++) { 4902769Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0) 4912769Sahl return (dt_set_errno(dtp, errno)); 4922769Sahl 4932769Sahl if (i + 1 != prp->pr_nargc && 4942769Sahl fprintf(infop->dthi_out, ", ") < 0) 4952769Sahl return (dt_set_errno(dtp, errno)); 4962769Sahl } 4971399Sahl } 4981399Sahl 4991399Sahl if (fprintf(infop->dthi_out, ")\n") < 0) 5001399Sahl return (dt_set_errno(dtp, errno)); 5011399Sahl 5022769Sahl if (!infop->dthi_empty) { 5036554Sahl if (fprintf(infop->dthi_out, 5046554Sahl "#ifndef\t__sparc\n" 5056554Sahl "#define\t%s_%s_ENABLED() \\\n" 5066554Sahl "\t__dtraceenabled_%s___%s()\n" 5076554Sahl "#else\n" 5086554Sahl "#define\t%s_%s_ENABLED() \\\n" 5096554Sahl "\t__dtraceenabled_%s___%s(0)\n" 5106554Sahl "#endif\n", 5116554Sahl infop->dthi_pmname, mname, 5126554Sahl infop->dthi_pfname, fname, 5136554Sahl infop->dthi_pmname, mname, 5146554Sahl infop->dthi_pfname, fname) < 0) 5152769Sahl return (dt_set_errno(dtp, errno)); 5161710Sahl 5172769Sahl } else { 5182769Sahl if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() (0)\n", 5192769Sahl infop->dthi_pmname, mname) < 0) 5202769Sahl return (dt_set_errno(dtp, errno)); 5212769Sahl } 5221710Sahl 5231399Sahl return (0); 5241399Sahl } 5251399Sahl 5261399Sahl static int 5271399Sahl dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out) 5281399Sahl { 5291399Sahl dt_header_info_t info; 5301399Sahl const char *p; 5311399Sahl int i; 5321399Sahl 5331399Sahl if (pvp->pv_flags & DT_PROVIDER_IMPL) 5341399Sahl return (0); 5351399Sahl 5362769Sahl /* 5372769Sahl * Count the instances of the '-' character since we'll need to double 5382769Sahl * those up. 5392769Sahl */ 5401399Sahl p = pvp->pv_desc.dtvd_name; 5411399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 5421399Sahl p++; 5431399Sahl 5441399Sahl info.dthi_dtp = dtp; 5451399Sahl info.dthi_out = out; 5462769Sahl info.dthi_empty = 0; 5471399Sahl 5481399Sahl info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1); 5491399Sahl dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name); 5501399Sahl 5511399Sahl info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i); 5521399Sahl dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name); 5531399Sahl 5542769Sahl if (fprintf(out, "#if _DTRACE_VERSION\n\n") < 0) 5552769Sahl return (dt_set_errno(dtp, errno)); 5561399Sahl 5571399Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 5581399Sahl return (-1); /* dt_errno is set for us */ 5591399Sahl if (fprintf(out, "\n\n") < 0) 5601399Sahl return (dt_set_errno(dtp, errno)); 5611399Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0) 5621399Sahl return (-1); /* dt_errno is set for us */ 5631399Sahl 5642769Sahl if (fprintf(out, "\n#else\n\n") < 0) 5652769Sahl return (dt_set_errno(dtp, errno)); 5662769Sahl 5672769Sahl info.dthi_empty = 1; 5682769Sahl 5692769Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 5702769Sahl return (-1); /* dt_errno is set for us */ 5712769Sahl 5722769Sahl if (fprintf(out, "\n#endif\n\n") < 0) 5732769Sahl return (dt_set_errno(dtp, errno)); 5742769Sahl 5751399Sahl return (0); 5761399Sahl } 5771399Sahl 5781399Sahl int 5791399Sahl dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname) 5801399Sahl { 5811399Sahl dt_provider_t *pvp; 5821399Sahl char *mfname, *p; 5831399Sahl 5841399Sahl if (fname != NULL) { 5851399Sahl if ((p = strrchr(fname, '/')) != NULL) 5861399Sahl fname = p + 1; 5871399Sahl 5881399Sahl mfname = alloca(strlen(fname) + 1); 5891399Sahl dt_header_fmt_macro(mfname, fname); 5901399Sahl if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n", 5911399Sahl mfname, mfname) < 0) 5921399Sahl return (dt_set_errno(dtp, errno)); 5931399Sahl } 5941399Sahl 5952769Sahl if (fprintf(out, "#include <unistd.h>\n\n") < 0) 5962769Sahl return (-1); 5972769Sahl 5981399Sahl if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0) 5991399Sahl return (-1); 6001399Sahl 6011399Sahl for (pvp = dt_list_next(&dtp->dt_provlist); 6021399Sahl pvp != NULL; pvp = dt_list_next(pvp)) { 6031399Sahl if (dt_header_provider(dtp, pvp, out) != 0) 6041399Sahl return (-1); /* dt_errno is set for us */ 6051399Sahl } 6061399Sahl 6071399Sahl if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0) 6081399Sahl return (dt_set_errno(dtp, errno)); 6091399Sahl 6101399Sahl if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0) 6111399Sahl return (dt_set_errno(dtp, errno)); 6121399Sahl 6131399Sahl return (0); 6141399Sahl } 615