xref: /onnv-gate/usr/src/lib/libdtrace/common/dt_program.c (revision 1399:f3a549d00510)
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