17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5ac448965Sahl * Common Development and Distribution License (the "License").
6ac448965Sahl * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21900524f3Sahl
227c478bd9Sstevel@tonic-gate /*
23c9a6ea2eSBryan Cantrill * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*deef35fdSEric Schrock * Copyright (c) 2011 by Delphix. All rights reserved.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <unistd.h>
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <assert.h>
32900524f3Sahl #include <ctype.h>
33900524f3Sahl #include <alloca.h>
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #include <dt_impl.h>
361a7c1b72Smws #include <dt_program.h>
377c478bd9Sstevel@tonic-gate #include <dt_printf.h>
38900524f3Sahl #include <dt_provider.h>
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate dtrace_prog_t *
dt_program_create(dtrace_hdl_t * dtp)411a7c1b72Smws dt_program_create(dtrace_hdl_t *dtp)
427c478bd9Sstevel@tonic-gate {
431a7c1b72Smws dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t));
447c478bd9Sstevel@tonic-gate
45c9a6ea2eSBryan Cantrill if (pgp != NULL) {
467c478bd9Sstevel@tonic-gate dt_list_append(&dtp->dt_programs, pgp);
47c9a6ea2eSBryan Cantrill } else {
487c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM);
49c9a6ea2eSBryan Cantrill return (NULL);
50c9a6ea2eSBryan Cantrill }
517c478bd9Sstevel@tonic-gate
52ac448965Sahl /*
53ac448965Sahl * By default, programs start with DOF version 1 so that output files
54ac448965Sahl * containing DOF are backward compatible. If a program requires new
55ac448965Sahl * DOF features, the version is increased as needed.
56ac448965Sahl */
57ac448965Sahl pgp->dp_dofversion = DOF_VERSION_1;
58ac448965Sahl
597c478bd9Sstevel@tonic-gate return (pgp);
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate void
dt_program_destroy(dtrace_hdl_t * dtp,dtrace_prog_t * pgp)631a7c1b72Smws dt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate dt_stmt_t *stp, *next;
661a7c1b72Smws uint_t i;
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) {
697c478bd9Sstevel@tonic-gate next = dt_list_next(stp);
701a7c1b72Smws dtrace_stmt_destroy(dtp, stp->ds_desc);
711a7c1b72Smws dt_free(dtp, stp);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate
741a7c1b72Smws for (i = 0; i < pgp->dp_xrefslen; i++)
751a7c1b72Smws dt_free(dtp, pgp->dp_xrefs[i]);
761a7c1b72Smws
771a7c1b72Smws dt_free(dtp, pgp->dp_xrefs);
787c478bd9Sstevel@tonic-gate dt_list_delete(&dtp->dt_programs, pgp);
791a7c1b72Smws dt_free(dtp, pgp);
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
837c478bd9Sstevel@tonic-gate void
dtrace_program_info(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_proginfo_t * pip)847c478bd9Sstevel@tonic-gate dtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
857c478bd9Sstevel@tonic-gate dtrace_proginfo_t *pip)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate dt_stmt_t *stp;
887c478bd9Sstevel@tonic-gate dtrace_actdesc_t *ap;
897c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *last = NULL;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate if (pip == NULL)
927c478bd9Sstevel@tonic-gate return;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate bzero(pip, sizeof (dtrace_proginfo_t));
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate if (dt_list_next(&pgp->dp_stmts) != NULL) {
977c478bd9Sstevel@tonic-gate pip->dpi_descattr = _dtrace_maxattr;
987c478bd9Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_maxattr;
997c478bd9Sstevel@tonic-gate } else {
1007c478bd9Sstevel@tonic-gate pip->dpi_descattr = _dtrace_defattr;
1017c478bd9Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_defattr;
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) {
1057c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc;
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate if (edp == last)
1087c478bd9Sstevel@tonic-gate continue;
1097c478bd9Sstevel@tonic-gate last = edp;
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate pip->dpi_descattr =
1127c478bd9Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr);
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate pip->dpi_stmtattr =
1157c478bd9Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr);
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate * If there aren't any actions, account for the fact that
1197c478bd9Sstevel@tonic-gate * recording the epid will generate a record.
1207c478bd9Sstevel@tonic-gate */
1217c478bd9Sstevel@tonic-gate if (edp->dted_action == NULL)
1227c478bd9Sstevel@tonic-gate pip->dpi_recgens++;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) {
1257c478bd9Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_SPECULATE) {
1267c478bd9Sstevel@tonic-gate pip->dpi_speculations++;
1277c478bd9Sstevel@tonic-gate continue;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate if (DTRACEACT_ISAGG(ap->dtad_kind)) {
1317c478bd9Sstevel@tonic-gate pip->dpi_recgens -= ap->dtad_arg;
1327c478bd9Sstevel@tonic-gate pip->dpi_aggregates++;
1337c478bd9Sstevel@tonic-gate continue;
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind))
1377c478bd9Sstevel@tonic-gate continue;
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_DIFEXPR &&
1407c478bd9Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_kind ==
1417c478bd9Sstevel@tonic-gate DIF_TYPE_CTF &&
1427c478bd9Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_size == 0)
1437c478bd9Sstevel@tonic-gate continue;
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate pip->dpi_recgens++;
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate int
dtrace_program_exec(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_proginfo_t * pip)1517c478bd9Sstevel@tonic-gate dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
1527c478bd9Sstevel@tonic-gate dtrace_proginfo_t *pip)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate void *dof;
1557c478bd9Sstevel@tonic-gate int n, err;
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate dtrace_program_info(dtp, pgp, pip);
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL)
1607c478bd9Sstevel@tonic-gate return (-1);
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate n = dt_ioctl(dtp, DTRACEIOC_ENABLE, dof);
1637c478bd9Sstevel@tonic-gate dtrace_dof_destroy(dtp, dof);
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate if (n == -1) {
1667c478bd9Sstevel@tonic-gate switch (errno) {
1677c478bd9Sstevel@tonic-gate case EINVAL:
1687c478bd9Sstevel@tonic-gate err = EDT_DIFINVAL;
1697c478bd9Sstevel@tonic-gate break;
1707c478bd9Sstevel@tonic-gate case EFAULT:
1717c478bd9Sstevel@tonic-gate err = EDT_DIFFAULT;
1727c478bd9Sstevel@tonic-gate break;
1737c478bd9Sstevel@tonic-gate case E2BIG:
1747c478bd9Sstevel@tonic-gate err = EDT_DIFSIZE;
1757c478bd9Sstevel@tonic-gate break;
176b9e93c10SJonathan Haslam case EBUSY:
177b9e93c10SJonathan Haslam err = EDT_ENABLING_ERR;
178b9e93c10SJonathan Haslam break;
1797c478bd9Sstevel@tonic-gate default:
1807c478bd9Sstevel@tonic-gate err = errno;
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate return (dt_set_errno(dtp, err));
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate if (pip != NULL)
1877c478bd9Sstevel@tonic-gate pip->dpi_matches += n;
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate return (0);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate
1921a7c1b72Smws static void
dt_ecbdesc_hold(dtrace_ecbdesc_t * edp)1931a7c1b72Smws dt_ecbdesc_hold(dtrace_ecbdesc_t *edp)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate edp->dted_refcnt++;
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate void
dt_ecbdesc_release(dtrace_hdl_t * dtp,dtrace_ecbdesc_t * edp)1991a7c1b72Smws dt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate if (--edp->dted_refcnt > 0)
2027c478bd9Sstevel@tonic-gate return;
2037c478bd9Sstevel@tonic-gate
2041a7c1b72Smws dt_difo_free(dtp, edp->dted_pred.dtpdd_difo);
2057c478bd9Sstevel@tonic-gate assert(edp->dted_action == NULL);
2061a7c1b72Smws dt_free(dtp, edp);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *
dt_ecbdesc_create(dtrace_hdl_t * dtp,const dtrace_probedesc_t * pdp)2101a7c1b72Smws dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp;
2137c478bd9Sstevel@tonic-gate
2141a7c1b72Smws if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) {
2157c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM);
2167c478bd9Sstevel@tonic-gate return (NULL);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate edp->dted_probe = *pdp;
2201a7c1b72Smws dt_ecbdesc_hold(edp);
2217c478bd9Sstevel@tonic-gate return (edp);
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate dtrace_stmtdesc_t *
dtrace_stmt_create(dtrace_hdl_t * dtp,dtrace_ecbdesc_t * edp)2257c478bd9Sstevel@tonic-gate dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate dtrace_stmtdesc_t *sdp;
2287c478bd9Sstevel@tonic-gate
2291a7c1b72Smws if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL)
2307c478bd9Sstevel@tonic-gate return (NULL);
2317c478bd9Sstevel@tonic-gate
2321a7c1b72Smws dt_ecbdesc_hold(edp);
2337c478bd9Sstevel@tonic-gate sdp->dtsd_ecbdesc = edp;
2347c478bd9Sstevel@tonic-gate sdp->dtsd_descattr = _dtrace_defattr;
2357c478bd9Sstevel@tonic-gate sdp->dtsd_stmtattr = _dtrace_defattr;
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate return (sdp);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate dtrace_actdesc_t *
dtrace_stmt_action(dtrace_hdl_t * dtp,dtrace_stmtdesc_t * sdp)2417c478bd9Sstevel@tonic-gate dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate dtrace_actdesc_t *new;
2447c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
2457c478bd9Sstevel@tonic-gate
2461a7c1b72Smws if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL)
2477c478bd9Sstevel@tonic-gate return (NULL);
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate if (sdp->dtsd_action_last != NULL) {
2507c478bd9Sstevel@tonic-gate assert(sdp->dtsd_action != NULL);
2517c478bd9Sstevel@tonic-gate assert(sdp->dtsd_action_last->dtad_next == NULL);
2527c478bd9Sstevel@tonic-gate sdp->dtsd_action_last->dtad_next = new;
2537c478bd9Sstevel@tonic-gate } else {
2547c478bd9Sstevel@tonic-gate dtrace_actdesc_t *ap = edp->dted_action;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate assert(sdp->dtsd_action == NULL);
2577c478bd9Sstevel@tonic-gate sdp->dtsd_action = new;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate while (ap != NULL && ap->dtad_next != NULL)
2607c478bd9Sstevel@tonic-gate ap = ap->dtad_next;
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate if (ap == NULL)
2637c478bd9Sstevel@tonic-gate edp->dted_action = new;
2647c478bd9Sstevel@tonic-gate else
2657c478bd9Sstevel@tonic-gate ap->dtad_next = new;
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate sdp->dtsd_action_last = new;
2697c478bd9Sstevel@tonic-gate bzero(new, sizeof (dtrace_actdesc_t));
2707c478bd9Sstevel@tonic-gate new->dtad_uarg = (uintptr_t)sdp;
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate return (new);
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate int
dtrace_stmt_add(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_stmtdesc_t * sdp)2767c478bd9Sstevel@tonic-gate dtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp)
2777c478bd9Sstevel@tonic-gate {
2781a7c1b72Smws dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t));
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate if (stp == NULL)
2811a7c1b72Smws return (-1); /* errno is set for us */
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate dt_list_append(&pgp->dp_stmts, stp);
2847c478bd9Sstevel@tonic-gate stp->ds_desc = sdp;
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate return (0);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate int
dtrace_stmt_iter(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,dtrace_stmt_f * func,void * data)2907c478bd9Sstevel@tonic-gate dtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
2917c478bd9Sstevel@tonic-gate dtrace_stmt_f *func, void *data)
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate dt_stmt_t *stp, *next;
2947c478bd9Sstevel@tonic-gate int status = 0;
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) {
2977c478bd9Sstevel@tonic-gate next = dt_list_next(stp);
2987c478bd9Sstevel@tonic-gate if ((status = func(dtp, pgp, stp->ds_desc, data)) != 0)
2997c478bd9Sstevel@tonic-gate break;
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate return (status);
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate void
dtrace_stmt_destroy(dtrace_hdl_t * dtp,dtrace_stmtdesc_t * sdp)3061a7c1b72Smws dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
3077c478bd9Sstevel@tonic-gate {
3087c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate /*
3117c478bd9Sstevel@tonic-gate * We need to remove any actions that we have on this ECB, and
3127c478bd9Sstevel@tonic-gate * remove our hold on the ECB itself.
3137c478bd9Sstevel@tonic-gate */
3147c478bd9Sstevel@tonic-gate if (sdp->dtsd_action != NULL) {
3157c478bd9Sstevel@tonic-gate dtrace_actdesc_t *last = sdp->dtsd_action_last;
3167c478bd9Sstevel@tonic-gate dtrace_actdesc_t *ap, *next;
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate assert(last != NULL);
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) {
3217c478bd9Sstevel@tonic-gate if (ap == sdp->dtsd_action)
3227c478bd9Sstevel@tonic-gate break;
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate if (ap->dtad_next == sdp->dtsd_action)
3257c478bd9Sstevel@tonic-gate break;
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate assert(ap != NULL);
3297c478bd9Sstevel@tonic-gate
3301a7c1b72Smws if (ap == edp->dted_action)
3317c478bd9Sstevel@tonic-gate edp->dted_action = last->dtad_next;
3321a7c1b72Smws else
3337c478bd9Sstevel@tonic-gate ap->dtad_next = last->dtad_next;
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate * We have now removed our action list from its ECB; we can
3377c478bd9Sstevel@tonic-gate * safely destroy the list.
3387c478bd9Sstevel@tonic-gate */
3397c478bd9Sstevel@tonic-gate last->dtad_next = NULL;
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate for (ap = sdp->dtsd_action; ap != NULL; ap = next) {
3427c478bd9Sstevel@tonic-gate assert(ap->dtad_uarg == (uintptr_t)sdp);
3431a7c1b72Smws dt_difo_free(dtp, ap->dtad_difo);
3447c478bd9Sstevel@tonic-gate next = ap->dtad_next;
3451a7c1b72Smws dt_free(dtp, ap);
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL)
3507c478bd9Sstevel@tonic-gate dt_printf_destroy(sdp->dtsd_fmtdata);
351*deef35fdSEric Schrock dt_free(dtp, sdp->dtsd_strdata);
3527c478bd9Sstevel@tonic-gate
3531a7c1b72Smws dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc);
3541a7c1b72Smws dt_free(dtp, sdp);
3557c478bd9Sstevel@tonic-gate }
356900524f3Sahl
357900524f3Sahl typedef struct dt_header_info {
358900524f3Sahl dtrace_hdl_t *dthi_dtp; /* consumer handle */
359900524f3Sahl FILE *dthi_out; /* output file */
360900524f3Sahl char *dthi_pmname; /* provider macro name */
361900524f3Sahl char *dthi_pfname; /* provider function name */
3622b6e762cSahl int dthi_empty; /* should we generate empty macros */
363900524f3Sahl } dt_header_info_t;
364900524f3Sahl
365900524f3Sahl static void
dt_header_fmt_macro(char * buf,const char * str)366900524f3Sahl dt_header_fmt_macro(char *buf, const char *str)
367900524f3Sahl {
368900524f3Sahl for (;;) {
369900524f3Sahl if (islower(*str)) {
370900524f3Sahl *buf++ = *str++ + 'A' - 'a';
371900524f3Sahl } else if (*str == '-') {
372900524f3Sahl *buf++ = '_';
373900524f3Sahl str++;
374900524f3Sahl } else if (*str == '.') {
375900524f3Sahl *buf++ = '_';
376900524f3Sahl str++;
377900524f3Sahl } else if ((*buf++ = *str++) == '\0') {
378900524f3Sahl break;
379900524f3Sahl }
380900524f3Sahl }
381900524f3Sahl }
382900524f3Sahl
383900524f3Sahl static void
dt_header_fmt_func(char * buf,const char * str)384900524f3Sahl dt_header_fmt_func(char *buf, const char *str)
385900524f3Sahl {
386900524f3Sahl for (;;) {
387900524f3Sahl if (*str == '-') {
388900524f3Sahl *buf++ = '_';
389900524f3Sahl *buf++ = '_';
390900524f3Sahl str++;
391900524f3Sahl } else if ((*buf++ = *str++) == '\0') {
392900524f3Sahl break;
393900524f3Sahl }
394900524f3Sahl }
395900524f3Sahl }
396900524f3Sahl
397900524f3Sahl /*ARGSUSED*/
398900524f3Sahl static int
dt_header_decl(dt_idhash_t * dhp,dt_ident_t * idp,void * data)399900524f3Sahl dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
400900524f3Sahl {
401900524f3Sahl dt_header_info_t *infop = data;
402900524f3Sahl dtrace_hdl_t *dtp = infop->dthi_dtp;
403900524f3Sahl dt_probe_t *prp = idp->di_data;
404900524f3Sahl dt_node_t *dnp;
405900524f3Sahl char buf[DT_TYPE_NAMELEN];
406900524f3Sahl char *fname;
407900524f3Sahl const char *p;
408900524f3Sahl int i;
409900524f3Sahl
410900524f3Sahl p = prp->pr_name;
411900524f3Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++)
412900524f3Sahl p++;
413900524f3Sahl
414900524f3Sahl fname = alloca(strlen(prp->pr_name) + 1 + i);
415900524f3Sahl dt_header_fmt_func(fname, prp->pr_name);
416900524f3Sahl
417900524f3Sahl if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(",
418900524f3Sahl infop->dthi_pfname, fname) < 0)
419900524f3Sahl return (dt_set_errno(dtp, errno));
420900524f3Sahl
421900524f3Sahl for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) {
422900524f3Sahl if (fprintf(infop->dthi_out, "%s",
423900524f3Sahl ctf_type_name(dnp->dn_ctfp, dnp->dn_type,
424900524f3Sahl buf, sizeof (buf))) < 0)
425900524f3Sahl return (dt_set_errno(dtp, errno));
426900524f3Sahl
427900524f3Sahl if (i + 1 != prp->pr_nargc &&
428900524f3Sahl fprintf(infop->dthi_out, ", ") < 0)
429900524f3Sahl return (dt_set_errno(dtp, errno));
430900524f3Sahl }
431900524f3Sahl
432900524f3Sahl if (i == 0 && fprintf(infop->dthi_out, "void") < 0)
433900524f3Sahl return (dt_set_errno(dtp, errno));
434900524f3Sahl
435900524f3Sahl if (fprintf(infop->dthi_out, ");\n") < 0)
436900524f3Sahl return (dt_set_errno(dtp, errno));
437900524f3Sahl
4380bac14eaSahl if (fprintf(infop->dthi_out,
4390bac14eaSahl "#ifndef\t__sparc\n"
4400bac14eaSahl "extern int __dtraceenabled_%s___%s(void);\n"
4410bac14eaSahl "#else\n"
4420bac14eaSahl "extern int __dtraceenabled_%s___%s(long);\n"
4430bac14eaSahl "#endif\n",
4440bac14eaSahl infop->dthi_pfname, fname, infop->dthi_pfname, fname) < 0)
445ac448965Sahl return (dt_set_errno(dtp, errno));
446ac448965Sahl
447900524f3Sahl return (0);
448900524f3Sahl }
449900524f3Sahl
450900524f3Sahl /*ARGSUSED*/
451900524f3Sahl static int
dt_header_probe(dt_idhash_t * dhp,dt_ident_t * idp,void * data)452900524f3Sahl dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
453900524f3Sahl {
454900524f3Sahl dt_header_info_t *infop = data;
455900524f3Sahl dtrace_hdl_t *dtp = infop->dthi_dtp;
456900524f3Sahl dt_probe_t *prp = idp->di_data;
457900524f3Sahl char *mname, *fname;
458900524f3Sahl const char *p;
459900524f3Sahl int i;
460900524f3Sahl
461900524f3Sahl p = prp->pr_name;
462900524f3Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++)
463900524f3Sahl p++;
464900524f3Sahl
465900524f3Sahl mname = alloca(strlen(prp->pr_name) + 1);
466900524f3Sahl dt_header_fmt_macro(mname, prp->pr_name);
467900524f3Sahl
468900524f3Sahl fname = alloca(strlen(prp->pr_name) + 1 + i);
469900524f3Sahl dt_header_fmt_func(fname, prp->pr_name);
470900524f3Sahl
471900524f3Sahl if (fprintf(infop->dthi_out, "#define\t%s_%s(",
472900524f3Sahl infop->dthi_pmname, mname) < 0)
473900524f3Sahl return (dt_set_errno(dtp, errno));
474900524f3Sahl
475900524f3Sahl for (i = 0; i < prp->pr_nargc; i++) {
476900524f3Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0)
477900524f3Sahl return (dt_set_errno(dtp, errno));
478900524f3Sahl
479900524f3Sahl if (i + 1 != prp->pr_nargc &&
480900524f3Sahl fprintf(infop->dthi_out, ", ") < 0)
481900524f3Sahl return (dt_set_errno(dtp, errno));
482900524f3Sahl }
483900524f3Sahl
4842b6e762cSahl if (!infop->dthi_empty) {
485900524f3Sahl if (fprintf(infop->dthi_out, ") \\\n\t") < 0)
486900524f3Sahl return (dt_set_errno(dtp, errno));
487900524f3Sahl
488900524f3Sahl if (fprintf(infop->dthi_out, "__dtrace_%s___%s(",
489900524f3Sahl infop->dthi_pfname, fname) < 0)
490900524f3Sahl return (dt_set_errno(dtp, errno));
491900524f3Sahl
492900524f3Sahl for (i = 0; i < prp->pr_nargc; i++) {
493900524f3Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0)
494900524f3Sahl return (dt_set_errno(dtp, errno));
495900524f3Sahl
496900524f3Sahl if (i + 1 != prp->pr_nargc &&
497900524f3Sahl fprintf(infop->dthi_out, ", ") < 0)
498900524f3Sahl return (dt_set_errno(dtp, errno));
499900524f3Sahl }
5002b6e762cSahl }
501900524f3Sahl
502900524f3Sahl if (fprintf(infop->dthi_out, ")\n") < 0)
503900524f3Sahl return (dt_set_errno(dtp, errno));
504900524f3Sahl
5052b6e762cSahl if (!infop->dthi_empty) {
5060bac14eaSahl if (fprintf(infop->dthi_out,
5070bac14eaSahl "#ifndef\t__sparc\n"
5080bac14eaSahl "#define\t%s_%s_ENABLED() \\\n"
5090bac14eaSahl "\t__dtraceenabled_%s___%s()\n"
5100bac14eaSahl "#else\n"
5110bac14eaSahl "#define\t%s_%s_ENABLED() \\\n"
5120bac14eaSahl "\t__dtraceenabled_%s___%s(0)\n"
5130bac14eaSahl "#endif\n",
5140bac14eaSahl infop->dthi_pmname, mname,
5150bac14eaSahl infop->dthi_pfname, fname,
5160bac14eaSahl infop->dthi_pmname, mname,
517ac448965Sahl infop->dthi_pfname, fname) < 0)
518ac448965Sahl return (dt_set_errno(dtp, errno));
5190bac14eaSahl
5202b6e762cSahl } else {
5212b6e762cSahl if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() (0)\n",
5222b6e762cSahl infop->dthi_pmname, mname) < 0)
5232b6e762cSahl return (dt_set_errno(dtp, errno));
5242b6e762cSahl }
525ac448965Sahl
526900524f3Sahl return (0);
527900524f3Sahl }
528900524f3Sahl
529900524f3Sahl static int
dt_header_provider(dtrace_hdl_t * dtp,dt_provider_t * pvp,FILE * out)530900524f3Sahl dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out)
531900524f3Sahl {
532900524f3Sahl dt_header_info_t info;
533900524f3Sahl const char *p;
534900524f3Sahl int i;
535900524f3Sahl
536900524f3Sahl if (pvp->pv_flags & DT_PROVIDER_IMPL)
537900524f3Sahl return (0);
538900524f3Sahl
5392b6e762cSahl /*
5402b6e762cSahl * Count the instances of the '-' character since we'll need to double
5412b6e762cSahl * those up.
5422b6e762cSahl */
543900524f3Sahl p = pvp->pv_desc.dtvd_name;
544900524f3Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++)
545900524f3Sahl p++;
546900524f3Sahl
547900524f3Sahl info.dthi_dtp = dtp;
548900524f3Sahl info.dthi_out = out;
5492b6e762cSahl info.dthi_empty = 0;
550900524f3Sahl
551900524f3Sahl info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1);
552900524f3Sahl dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name);
553900524f3Sahl
554900524f3Sahl info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i);
555900524f3Sahl dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name);
556900524f3Sahl
5572b6e762cSahl if (fprintf(out, "#if _DTRACE_VERSION\n\n") < 0)
5582b6e762cSahl return (dt_set_errno(dtp, errno));
559900524f3Sahl
560900524f3Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0)
561900524f3Sahl return (-1); /* dt_errno is set for us */
562900524f3Sahl if (fprintf(out, "\n\n") < 0)
563900524f3Sahl return (dt_set_errno(dtp, errno));
564900524f3Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0)
565900524f3Sahl return (-1); /* dt_errno is set for us */
566900524f3Sahl
5672b6e762cSahl if (fprintf(out, "\n#else\n\n") < 0)
5682b6e762cSahl return (dt_set_errno(dtp, errno));
5692b6e762cSahl
5702b6e762cSahl info.dthi_empty = 1;
5712b6e762cSahl
5722b6e762cSahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0)
5732b6e762cSahl return (-1); /* dt_errno is set for us */
5742b6e762cSahl
5752b6e762cSahl if (fprintf(out, "\n#endif\n\n") < 0)
5762b6e762cSahl return (dt_set_errno(dtp, errno));
5772b6e762cSahl
578900524f3Sahl return (0);
579900524f3Sahl }
580900524f3Sahl
581900524f3Sahl int
dtrace_program_header(dtrace_hdl_t * dtp,FILE * out,const char * fname)582900524f3Sahl dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname)
583900524f3Sahl {
584900524f3Sahl dt_provider_t *pvp;
585900524f3Sahl char *mfname, *p;
586900524f3Sahl
587900524f3Sahl if (fname != NULL) {
588900524f3Sahl if ((p = strrchr(fname, '/')) != NULL)
589900524f3Sahl fname = p + 1;
590900524f3Sahl
591900524f3Sahl mfname = alloca(strlen(fname) + 1);
592900524f3Sahl dt_header_fmt_macro(mfname, fname);
593900524f3Sahl if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n",
594900524f3Sahl mfname, mfname) < 0)
595900524f3Sahl return (dt_set_errno(dtp, errno));
596900524f3Sahl }
597900524f3Sahl
5982b6e762cSahl if (fprintf(out, "#include <unistd.h>\n\n") < 0)
5992b6e762cSahl return (-1);
6002b6e762cSahl
601900524f3Sahl if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0)
602900524f3Sahl return (-1);
603900524f3Sahl
604900524f3Sahl for (pvp = dt_list_next(&dtp->dt_provlist);
605900524f3Sahl pvp != NULL; pvp = dt_list_next(pvp)) {
606900524f3Sahl if (dt_header_provider(dtp, pvp, out) != 0)
607900524f3Sahl return (-1); /* dt_errno is set for us */
608900524f3Sahl }
609900524f3Sahl
610900524f3Sahl if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0)
611900524f3Sahl return (dt_set_errno(dtp, errno));
612900524f3Sahl
613900524f3Sahl if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0)
614900524f3Sahl return (dt_set_errno(dtp, errno));
615900524f3Sahl
616900524f3Sahl return (0);
617900524f3Sahl }
618