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*12902SBryan.Cantrill@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <unistd.h>
270Sstevel@tonic-gate #include <strings.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate #include <assert.h>
311399Sahl #include <ctype.h>
321399Sahl #include <alloca.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate #include <dt_impl.h>
35265Smws #include <dt_program.h>
360Sstevel@tonic-gate #include <dt_printf.h>
371399Sahl #include <dt_provider.h>
380Sstevel@tonic-gate
390Sstevel@tonic-gate dtrace_prog_t *
dt_program_create(dtrace_hdl_t * dtp)40265Smws dt_program_create(dtrace_hdl_t *dtp)
410Sstevel@tonic-gate {
42265Smws dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t));
430Sstevel@tonic-gate
44*12902SBryan.Cantrill@Sun.COM if (pgp != NULL) {
450Sstevel@tonic-gate dt_list_append(&dtp->dt_programs, pgp);
46*12902SBryan.Cantrill@Sun.COM } else {
470Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM);
48*12902SBryan.Cantrill@Sun.COM return (NULL);
49*12902SBryan.Cantrill@Sun.COM }
500Sstevel@tonic-gate
511710Sahl /*
521710Sahl * By default, programs start with DOF version 1 so that output files
531710Sahl * containing DOF are backward compatible. If a program requires new
541710Sahl * DOF features, the version is increased as needed.
551710Sahl */
561710Sahl pgp->dp_dofversion = DOF_VERSION_1;
571710Sahl
580Sstevel@tonic-gate return (pgp);
590Sstevel@tonic-gate }
600Sstevel@tonic-gate
610Sstevel@tonic-gate void
dt_program_destroy(dtrace_hdl_t * dtp,dtrace_prog_t * pgp)62265Smws dt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp)
630Sstevel@tonic-gate {
640Sstevel@tonic-gate dt_stmt_t *stp, *next;
65265Smws uint_t i;
660Sstevel@tonic-gate
670Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) {
680Sstevel@tonic-gate next = dt_list_next(stp);
69265Smws dtrace_stmt_destroy(dtp, stp->ds_desc);
70265Smws dt_free(dtp, stp);
710Sstevel@tonic-gate }
720Sstevel@tonic-gate
73265Smws for (i = 0; i < pgp->dp_xrefslen; i++)
74265Smws dt_free(dtp, pgp->dp_xrefs[i]);
75265Smws
76265Smws dt_free(dtp, pgp->dp_xrefs);
770Sstevel@tonic-gate dt_list_delete(&dtp->dt_programs, pgp);
78265Smws dt_free(dtp, pgp);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate
810Sstevel@tonic-gate /*ARGSUSED*/
820Sstevel@tonic-gate void
dtrace_program_info(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_proginfo_t * pip)830Sstevel@tonic-gate dtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
840Sstevel@tonic-gate dtrace_proginfo_t *pip)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate dt_stmt_t *stp;
870Sstevel@tonic-gate dtrace_actdesc_t *ap;
880Sstevel@tonic-gate dtrace_ecbdesc_t *last = NULL;
890Sstevel@tonic-gate
900Sstevel@tonic-gate if (pip == NULL)
910Sstevel@tonic-gate return;
920Sstevel@tonic-gate
930Sstevel@tonic-gate bzero(pip, sizeof (dtrace_proginfo_t));
940Sstevel@tonic-gate
950Sstevel@tonic-gate if (dt_list_next(&pgp->dp_stmts) != NULL) {
960Sstevel@tonic-gate pip->dpi_descattr = _dtrace_maxattr;
970Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_maxattr;
980Sstevel@tonic-gate } else {
990Sstevel@tonic-gate pip->dpi_descattr = _dtrace_defattr;
1000Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_defattr;
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) {
1040Sstevel@tonic-gate dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc;
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate if (edp == last)
1070Sstevel@tonic-gate continue;
1080Sstevel@tonic-gate last = edp;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate pip->dpi_descattr =
1110Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr);
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate pip->dpi_stmtattr =
1140Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr);
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate /*
1170Sstevel@tonic-gate * If there aren't any actions, account for the fact that
1180Sstevel@tonic-gate * recording the epid will generate a record.
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate if (edp->dted_action == NULL)
1210Sstevel@tonic-gate pip->dpi_recgens++;
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) {
1240Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_SPECULATE) {
1250Sstevel@tonic-gate pip->dpi_speculations++;
1260Sstevel@tonic-gate continue;
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate if (DTRACEACT_ISAGG(ap->dtad_kind)) {
1300Sstevel@tonic-gate pip->dpi_recgens -= ap->dtad_arg;
1310Sstevel@tonic-gate pip->dpi_aggregates++;
1320Sstevel@tonic-gate continue;
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind))
1360Sstevel@tonic-gate continue;
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_DIFEXPR &&
1390Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_kind ==
1400Sstevel@tonic-gate DIF_TYPE_CTF &&
1410Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_size == 0)
1420Sstevel@tonic-gate continue;
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate pip->dpi_recgens++;
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate int
dtrace_program_exec(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_proginfo_t * pip)1500Sstevel@tonic-gate dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
1510Sstevel@tonic-gate dtrace_proginfo_t *pip)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate void *dof;
1540Sstevel@tonic-gate int n, err;
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate dtrace_program_info(dtp, pgp, pip);
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL)
1590Sstevel@tonic-gate return (-1);
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate n = dt_ioctl(dtp, DTRACEIOC_ENABLE, dof);
1620Sstevel@tonic-gate dtrace_dof_destroy(dtp, dof);
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate if (n == -1) {
1650Sstevel@tonic-gate switch (errno) {
1660Sstevel@tonic-gate case EINVAL:
1670Sstevel@tonic-gate err = EDT_DIFINVAL;
1680Sstevel@tonic-gate break;
1690Sstevel@tonic-gate case EFAULT:
1700Sstevel@tonic-gate err = EDT_DIFFAULT;
1710Sstevel@tonic-gate break;
1720Sstevel@tonic-gate case E2BIG:
1730Sstevel@tonic-gate err = EDT_DIFSIZE;
1740Sstevel@tonic-gate break;
1758803SJonathan.Haslam@Sun.COM case EBUSY:
1768803SJonathan.Haslam@Sun.COM err = EDT_ENABLING_ERR;
1778803SJonathan.Haslam@Sun.COM break;
1780Sstevel@tonic-gate default:
1790Sstevel@tonic-gate err = errno;
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate return (dt_set_errno(dtp, err));
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate if (pip != NULL)
1860Sstevel@tonic-gate pip->dpi_matches += n;
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate return (0);
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate
191265Smws static void
dt_ecbdesc_hold(dtrace_ecbdesc_t * edp)192265Smws dt_ecbdesc_hold(dtrace_ecbdesc_t *edp)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate edp->dted_refcnt++;
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate void
dt_ecbdesc_release(dtrace_hdl_t * dtp,dtrace_ecbdesc_t * edp)198265Smws dt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate if (--edp->dted_refcnt > 0)
2010Sstevel@tonic-gate return;
2020Sstevel@tonic-gate
203265Smws dt_difo_free(dtp, edp->dted_pred.dtpdd_difo);
2040Sstevel@tonic-gate assert(edp->dted_action == NULL);
205265Smws dt_free(dtp, edp);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate dtrace_ecbdesc_t *
dt_ecbdesc_create(dtrace_hdl_t * dtp,const dtrace_probedesc_t * pdp)209265Smws dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate dtrace_ecbdesc_t *edp;
2120Sstevel@tonic-gate
213265Smws if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) {
2140Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM);
2150Sstevel@tonic-gate return (NULL);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate edp->dted_probe = *pdp;
219265Smws dt_ecbdesc_hold(edp);
2200Sstevel@tonic-gate return (edp);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate dtrace_stmtdesc_t *
dtrace_stmt_create(dtrace_hdl_t * dtp,dtrace_ecbdesc_t * edp)2240Sstevel@tonic-gate dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate dtrace_stmtdesc_t *sdp;
2270Sstevel@tonic-gate
228265Smws if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL)
2290Sstevel@tonic-gate return (NULL);
2300Sstevel@tonic-gate
231265Smws dt_ecbdesc_hold(edp);
2320Sstevel@tonic-gate sdp->dtsd_ecbdesc = edp;
2330Sstevel@tonic-gate sdp->dtsd_descattr = _dtrace_defattr;
2340Sstevel@tonic-gate sdp->dtsd_stmtattr = _dtrace_defattr;
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate return (sdp);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate dtrace_actdesc_t *
dtrace_stmt_action(dtrace_hdl_t * dtp,dtrace_stmtdesc_t * sdp)2400Sstevel@tonic-gate dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate dtrace_actdesc_t *new;
2430Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
2440Sstevel@tonic-gate
245265Smws if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL)
2460Sstevel@tonic-gate return (NULL);
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate if (sdp->dtsd_action_last != NULL) {
2490Sstevel@tonic-gate assert(sdp->dtsd_action != NULL);
2500Sstevel@tonic-gate assert(sdp->dtsd_action_last->dtad_next == NULL);
2510Sstevel@tonic-gate sdp->dtsd_action_last->dtad_next = new;
2520Sstevel@tonic-gate } else {
2530Sstevel@tonic-gate dtrace_actdesc_t *ap = edp->dted_action;
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate assert(sdp->dtsd_action == NULL);
2560Sstevel@tonic-gate sdp->dtsd_action = new;
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate while (ap != NULL && ap->dtad_next != NULL)
2590Sstevel@tonic-gate ap = ap->dtad_next;
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate if (ap == NULL)
2620Sstevel@tonic-gate edp->dted_action = new;
2630Sstevel@tonic-gate else
2640Sstevel@tonic-gate ap->dtad_next = new;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate sdp->dtsd_action_last = new;
2680Sstevel@tonic-gate bzero(new, sizeof (dtrace_actdesc_t));
2690Sstevel@tonic-gate new->dtad_uarg = (uintptr_t)sdp;
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate return (new);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate int
dtrace_stmt_add(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_stmtdesc_t * sdp)2750Sstevel@tonic-gate dtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp)
2760Sstevel@tonic-gate {
277265Smws dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t));
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate if (stp == NULL)
280265Smws return (-1); /* errno is set for us */
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate dt_list_append(&pgp->dp_stmts, stp);
2830Sstevel@tonic-gate stp->ds_desc = sdp;
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate return (0);
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate int
dtrace_stmt_iter(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_stmt_f * func,void * data)2890Sstevel@tonic-gate dtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
2900Sstevel@tonic-gate dtrace_stmt_f *func, void *data)
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate dt_stmt_t *stp, *next;
2930Sstevel@tonic-gate int status = 0;
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) {
2960Sstevel@tonic-gate next = dt_list_next(stp);
2970Sstevel@tonic-gate if ((status = func(dtp, pgp, stp->ds_desc, data)) != 0)
2980Sstevel@tonic-gate break;
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate return (status);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate void
dtrace_stmt_destroy(dtrace_hdl_t * dtp,dtrace_stmtdesc_t * sdp)305265Smws dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate /*
3100Sstevel@tonic-gate * We need to remove any actions that we have on this ECB, and
3110Sstevel@tonic-gate * remove our hold on the ECB itself.
3120Sstevel@tonic-gate */
3130Sstevel@tonic-gate if (sdp->dtsd_action != NULL) {
3140Sstevel@tonic-gate dtrace_actdesc_t *last = sdp->dtsd_action_last;
3150Sstevel@tonic-gate dtrace_actdesc_t *ap, *next;
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate assert(last != NULL);
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) {
3200Sstevel@tonic-gate if (ap == sdp->dtsd_action)
3210Sstevel@tonic-gate break;
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate if (ap->dtad_next == sdp->dtsd_action)
3240Sstevel@tonic-gate break;
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate assert(ap != NULL);
3280Sstevel@tonic-gate
329265Smws if (ap == edp->dted_action)
3300Sstevel@tonic-gate edp->dted_action = last->dtad_next;
331265Smws else
3320Sstevel@tonic-gate ap->dtad_next = last->dtad_next;
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate /*
3350Sstevel@tonic-gate * We have now removed our action list from its ECB; we can
3360Sstevel@tonic-gate * safely destroy the list.
3370Sstevel@tonic-gate */
3380Sstevel@tonic-gate last->dtad_next = NULL;
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate for (ap = sdp->dtsd_action; ap != NULL; ap = next) {
3410Sstevel@tonic-gate assert(ap->dtad_uarg == (uintptr_t)sdp);
342265Smws dt_difo_free(dtp, ap->dtad_difo);
3430Sstevel@tonic-gate next = ap->dtad_next;
344265Smws dt_free(dtp, ap);
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL)
3490Sstevel@tonic-gate dt_printf_destroy(sdp->dtsd_fmtdata);
3500Sstevel@tonic-gate
351265Smws dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc);
352265Smws dt_free(dtp, sdp);
3530Sstevel@tonic-gate }
3541399Sahl
3551399Sahl typedef struct dt_header_info {
3561399Sahl dtrace_hdl_t *dthi_dtp; /* consumer handle */
3571399Sahl FILE *dthi_out; /* output file */
3581399Sahl char *dthi_pmname; /* provider macro name */
3591399Sahl char *dthi_pfname; /* provider function name */
3602769Sahl int dthi_empty; /* should we generate empty macros */
3611399Sahl } dt_header_info_t;
3621399Sahl
3631399Sahl static void
dt_header_fmt_macro(char * buf,const char * str)3641399Sahl dt_header_fmt_macro(char *buf, const char *str)
3651399Sahl {
3661399Sahl for (;;) {
3671399Sahl if (islower(*str)) {
3681399Sahl *buf++ = *str++ + 'A' - 'a';
3691399Sahl } else if (*str == '-') {
3701399Sahl *buf++ = '_';
3711399Sahl str++;
3721399Sahl } else if (*str == '.') {
3731399Sahl *buf++ = '_';
3741399Sahl str++;
3751399Sahl } else if ((*buf++ = *str++) == '\0') {
3761399Sahl break;
3771399Sahl }
3781399Sahl }
3791399Sahl }
3801399Sahl
3811399Sahl static void
dt_header_fmt_func(char * buf,const char * str)3821399Sahl dt_header_fmt_func(char *buf, const char *str)
3831399Sahl {
3841399Sahl for (;;) {
3851399Sahl if (*str == '-') {
3861399Sahl *buf++ = '_';
3871399Sahl *buf++ = '_';
3881399Sahl str++;
3891399Sahl } else if ((*buf++ = *str++) == '\0') {
3901399Sahl break;
3911399Sahl }
3921399Sahl }
3931399Sahl }
3941399Sahl
3951399Sahl /*ARGSUSED*/
3961399Sahl static int
dt_header_decl(dt_idhash_t * dhp,dt_ident_t * idp,void * data)3971399Sahl dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
3981399Sahl {
3991399Sahl dt_header_info_t *infop = data;
4001399Sahl dtrace_hdl_t *dtp = infop->dthi_dtp;
4011399Sahl dt_probe_t *prp = idp->di_data;
4021399Sahl dt_node_t *dnp;
4031399Sahl char buf[DT_TYPE_NAMELEN];
4041399Sahl char *fname;
4051399Sahl const char *p;
4061399Sahl int i;
4071399Sahl
4081399Sahl p = prp->pr_name;
4091399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++)
4101399Sahl p++;
4111399Sahl
4121399Sahl fname = alloca(strlen(prp->pr_name) + 1 + i);
4131399Sahl dt_header_fmt_func(fname, prp->pr_name);
4141399Sahl
4151399Sahl if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(",
4161399Sahl infop->dthi_pfname, fname) < 0)
4171399Sahl return (dt_set_errno(dtp, errno));
4181399Sahl
4191399Sahl for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) {
4201399Sahl if (fprintf(infop->dthi_out, "%s",
4211399Sahl ctf_type_name(dnp->dn_ctfp, dnp->dn_type,
4221399Sahl buf, sizeof (buf))) < 0)
4231399Sahl return (dt_set_errno(dtp, errno));
4241399Sahl
4251399Sahl if (i + 1 != prp->pr_nargc &&
4261399Sahl fprintf(infop->dthi_out, ", ") < 0)
4271399Sahl return (dt_set_errno(dtp, errno));
4281399Sahl }
4291399Sahl
4301399Sahl if (i == 0 && fprintf(infop->dthi_out, "void") < 0)
4311399Sahl return (dt_set_errno(dtp, errno));
4321399Sahl
4331399Sahl if (fprintf(infop->dthi_out, ");\n") < 0)
4341399Sahl return (dt_set_errno(dtp, errno));
4351399Sahl
4366554Sahl if (fprintf(infop->dthi_out,
4376554Sahl "#ifndef\t__sparc\n"
4386554Sahl "extern int __dtraceenabled_%s___%s(void);\n"
4396554Sahl "#else\n"
4406554Sahl "extern int __dtraceenabled_%s___%s(long);\n"
4416554Sahl "#endif\n",
4426554Sahl infop->dthi_pfname, fname, infop->dthi_pfname, fname) < 0)
4431710Sahl return (dt_set_errno(dtp, errno));
4441710Sahl
4451399Sahl return (0);
4461399Sahl }
4471399Sahl
4481399Sahl /*ARGSUSED*/
4491399Sahl static int
dt_header_probe(dt_idhash_t * dhp,dt_ident_t * idp,void * data)4501399Sahl dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
4511399Sahl {
4521399Sahl dt_header_info_t *infop = data;
4531399Sahl dtrace_hdl_t *dtp = infop->dthi_dtp;
4541399Sahl dt_probe_t *prp = idp->di_data;
4551399Sahl char *mname, *fname;
4561399Sahl const char *p;
4571399Sahl int i;
4581399Sahl
4591399Sahl p = prp->pr_name;
4601399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++)
4611399Sahl p++;
4621399Sahl
4631399Sahl mname = alloca(strlen(prp->pr_name) + 1);
4641399Sahl dt_header_fmt_macro(mname, prp->pr_name);
4651399Sahl
4661399Sahl fname = alloca(strlen(prp->pr_name) + 1 + i);
4671399Sahl dt_header_fmt_func(fname, prp->pr_name);
4681399Sahl
4691399Sahl if (fprintf(infop->dthi_out, "#define\t%s_%s(",
4701399Sahl infop->dthi_pmname, mname) < 0)
4711399Sahl return (dt_set_errno(dtp, errno));
4721399Sahl
4731399Sahl for (i = 0; i < prp->pr_nargc; i++) {
4741399Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0)
4751399Sahl return (dt_set_errno(dtp, errno));
4761399Sahl
4771399Sahl if (i + 1 != prp->pr_nargc &&
4781399Sahl fprintf(infop->dthi_out, ", ") < 0)
4791399Sahl return (dt_set_errno(dtp, errno));
4801399Sahl }
4811399Sahl
4822769Sahl if (!infop->dthi_empty) {
4832769Sahl if (fprintf(infop->dthi_out, ") \\\n\t") < 0)
4842769Sahl return (dt_set_errno(dtp, errno));
4851399Sahl
4862769Sahl if (fprintf(infop->dthi_out, "__dtrace_%s___%s(",
4872769Sahl infop->dthi_pfname, fname) < 0)
4881399Sahl return (dt_set_errno(dtp, errno));
4891399Sahl
4902769Sahl for (i = 0; i < prp->pr_nargc; i++) {
4912769Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0)
4922769Sahl return (dt_set_errno(dtp, errno));
4932769Sahl
4942769Sahl if (i + 1 != prp->pr_nargc &&
4952769Sahl fprintf(infop->dthi_out, ", ") < 0)
4962769Sahl return (dt_set_errno(dtp, errno));
4972769Sahl }
4981399Sahl }
4991399Sahl
5001399Sahl if (fprintf(infop->dthi_out, ")\n") < 0)
5011399Sahl return (dt_set_errno(dtp, errno));
5021399Sahl
5032769Sahl if (!infop->dthi_empty) {
5046554Sahl if (fprintf(infop->dthi_out,
5056554Sahl "#ifndef\t__sparc\n"
5066554Sahl "#define\t%s_%s_ENABLED() \\\n"
5076554Sahl "\t__dtraceenabled_%s___%s()\n"
5086554Sahl "#else\n"
5096554Sahl "#define\t%s_%s_ENABLED() \\\n"
5106554Sahl "\t__dtraceenabled_%s___%s(0)\n"
5116554Sahl "#endif\n",
5126554Sahl infop->dthi_pmname, mname,
5136554Sahl infop->dthi_pfname, fname,
5146554Sahl infop->dthi_pmname, mname,
5156554Sahl infop->dthi_pfname, fname) < 0)
5162769Sahl return (dt_set_errno(dtp, errno));
5171710Sahl
5182769Sahl } else {
5192769Sahl if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() (0)\n",
5202769Sahl infop->dthi_pmname, mname) < 0)
5212769Sahl return (dt_set_errno(dtp, errno));
5222769Sahl }
5231710Sahl
5241399Sahl return (0);
5251399Sahl }
5261399Sahl
5271399Sahl static int
dt_header_provider(dtrace_hdl_t * dtp,dt_provider_t * pvp,FILE * out)5281399Sahl dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out)
5291399Sahl {
5301399Sahl dt_header_info_t info;
5311399Sahl const char *p;
5321399Sahl int i;
5331399Sahl
5341399Sahl if (pvp->pv_flags & DT_PROVIDER_IMPL)
5351399Sahl return (0);
5361399Sahl
5372769Sahl /*
5382769Sahl * Count the instances of the '-' character since we'll need to double
5392769Sahl * those up.
5402769Sahl */
5411399Sahl p = pvp->pv_desc.dtvd_name;
5421399Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++)
5431399Sahl p++;
5441399Sahl
5451399Sahl info.dthi_dtp = dtp;
5461399Sahl info.dthi_out = out;
5472769Sahl info.dthi_empty = 0;
5481399Sahl
5491399Sahl info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1);
5501399Sahl dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name);
5511399Sahl
5521399Sahl info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i);
5531399Sahl dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name);
5541399Sahl
5552769Sahl if (fprintf(out, "#if _DTRACE_VERSION\n\n") < 0)
5562769Sahl return (dt_set_errno(dtp, errno));
5571399Sahl
5581399Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0)
5591399Sahl return (-1); /* dt_errno is set for us */
5601399Sahl if (fprintf(out, "\n\n") < 0)
5611399Sahl return (dt_set_errno(dtp, errno));
5621399Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0)
5631399Sahl return (-1); /* dt_errno is set for us */
5641399Sahl
5652769Sahl if (fprintf(out, "\n#else\n\n") < 0)
5662769Sahl return (dt_set_errno(dtp, errno));
5672769Sahl
5682769Sahl info.dthi_empty = 1;
5692769Sahl
5702769Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0)
5712769Sahl return (-1); /* dt_errno is set for us */
5722769Sahl
5732769Sahl if (fprintf(out, "\n#endif\n\n") < 0)
5742769Sahl return (dt_set_errno(dtp, errno));
5752769Sahl
5761399Sahl return (0);
5771399Sahl }
5781399Sahl
5791399Sahl int
dtrace_program_header(dtrace_hdl_t * dtp,FILE * out,const char * fname)5801399Sahl dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname)
5811399Sahl {
5821399Sahl dt_provider_t *pvp;
5831399Sahl char *mfname, *p;
5841399Sahl
5851399Sahl if (fname != NULL) {
5861399Sahl if ((p = strrchr(fname, '/')) != NULL)
5871399Sahl fname = p + 1;
5881399Sahl
5891399Sahl mfname = alloca(strlen(fname) + 1);
5901399Sahl dt_header_fmt_macro(mfname, fname);
5911399Sahl if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n",
5921399Sahl mfname, mfname) < 0)
5931399Sahl return (dt_set_errno(dtp, errno));
5941399Sahl }
5951399Sahl
5962769Sahl if (fprintf(out, "#include <unistd.h>\n\n") < 0)
5972769Sahl return (-1);
5982769Sahl
5991399Sahl if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0)
6001399Sahl return (-1);
6011399Sahl
6021399Sahl for (pvp = dt_list_next(&dtp->dt_provlist);
6031399Sahl pvp != NULL; pvp = dt_list_next(pvp)) {
6041399Sahl if (dt_header_provider(dtp, pvp, out) != 0)
6051399Sahl return (-1); /* dt_errno is set for us */
6061399Sahl }
6071399Sahl
6081399Sahl if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0)
6091399Sahl return (dt_set_errno(dtp, errno));
6101399Sahl
6111399Sahl if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0)
6121399Sahl return (dt_set_errno(dtp, errno));
6131399Sahl
6141399Sahl return (0);
6151399Sahl }
616