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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22*900524f3Sahl 237c478bd9Sstevel@tonic-gate /* 24*900524f3Sahl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <unistd.h> 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <errno.h> 347c478bd9Sstevel@tonic-gate #include <assert.h> 35*900524f3Sahl #include <ctype.h> 36*900524f3Sahl #include <alloca.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <dt_impl.h> 391a7c1b72Smws #include <dt_program.h> 407c478bd9Sstevel@tonic-gate #include <dt_printf.h> 41*900524f3Sahl #include <dt_provider.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate dtrace_prog_t * 441a7c1b72Smws dt_program_create(dtrace_hdl_t *dtp) 457c478bd9Sstevel@tonic-gate { 461a7c1b72Smws dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t)); 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate if (pgp != NULL) 497c478bd9Sstevel@tonic-gate dt_list_append(&dtp->dt_programs, pgp); 507c478bd9Sstevel@tonic-gate else 517c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate return (pgp); 547c478bd9Sstevel@tonic-gate } 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate void 571a7c1b72Smws dt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) 587c478bd9Sstevel@tonic-gate { 597c478bd9Sstevel@tonic-gate dt_stmt_t *stp, *next; 601a7c1b72Smws uint_t i; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 637c478bd9Sstevel@tonic-gate next = dt_list_next(stp); 641a7c1b72Smws dtrace_stmt_destroy(dtp, stp->ds_desc); 651a7c1b72Smws dt_free(dtp, stp); 667c478bd9Sstevel@tonic-gate } 677c478bd9Sstevel@tonic-gate 681a7c1b72Smws for (i = 0; i < pgp->dp_xrefslen; i++) 691a7c1b72Smws dt_free(dtp, pgp->dp_xrefs[i]); 701a7c1b72Smws 711a7c1b72Smws dt_free(dtp, pgp->dp_xrefs); 727c478bd9Sstevel@tonic-gate dt_list_delete(&dtp->dt_programs, pgp); 731a7c1b72Smws dt_free(dtp, pgp); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 777c478bd9Sstevel@tonic-gate void 787c478bd9Sstevel@tonic-gate dtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 797c478bd9Sstevel@tonic-gate dtrace_proginfo_t *pip) 807c478bd9Sstevel@tonic-gate { 817c478bd9Sstevel@tonic-gate dt_stmt_t *stp; 827c478bd9Sstevel@tonic-gate dtrace_actdesc_t *ap; 837c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *last = NULL; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate if (pip == NULL) 867c478bd9Sstevel@tonic-gate return; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate bzero(pip, sizeof (dtrace_proginfo_t)); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate if (dt_list_next(&pgp->dp_stmts) != NULL) { 917c478bd9Sstevel@tonic-gate pip->dpi_descattr = _dtrace_maxattr; 927c478bd9Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_maxattr; 937c478bd9Sstevel@tonic-gate } else { 947c478bd9Sstevel@tonic-gate pip->dpi_descattr = _dtrace_defattr; 957c478bd9Sstevel@tonic-gate pip->dpi_stmtattr = _dtrace_defattr; 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) { 997c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if (edp == last) 1027c478bd9Sstevel@tonic-gate continue; 1037c478bd9Sstevel@tonic-gate last = edp; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate pip->dpi_descattr = 1067c478bd9Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate pip->dpi_stmtattr = 1097c478bd9Sstevel@tonic-gate dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr); 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * If there aren't any actions, account for the fact that 1137c478bd9Sstevel@tonic-gate * recording the epid will generate a record. 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate if (edp->dted_action == NULL) 1167c478bd9Sstevel@tonic-gate pip->dpi_recgens++; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 1197c478bd9Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_SPECULATE) { 1207c478bd9Sstevel@tonic-gate pip->dpi_speculations++; 1217c478bd9Sstevel@tonic-gate continue; 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate if (DTRACEACT_ISAGG(ap->dtad_kind)) { 1257c478bd9Sstevel@tonic-gate pip->dpi_recgens -= ap->dtad_arg; 1267c478bd9Sstevel@tonic-gate pip->dpi_aggregates++; 1277c478bd9Sstevel@tonic-gate continue; 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind)) 1317c478bd9Sstevel@tonic-gate continue; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (ap->dtad_kind == DTRACEACT_DIFEXPR && 1347c478bd9Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_kind == 1357c478bd9Sstevel@tonic-gate DIF_TYPE_CTF && 1367c478bd9Sstevel@tonic-gate ap->dtad_difo->dtdo_rtype.dtdt_size == 0) 1377c478bd9Sstevel@tonic-gate continue; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate pip->dpi_recgens++; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate int 1457c478bd9Sstevel@tonic-gate dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 1467c478bd9Sstevel@tonic-gate dtrace_proginfo_t *pip) 1477c478bd9Sstevel@tonic-gate { 1487c478bd9Sstevel@tonic-gate void *dof; 1497c478bd9Sstevel@tonic-gate int n, err; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate dtrace_program_info(dtp, pgp, pip); 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL) 1547c478bd9Sstevel@tonic-gate return (-1); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate n = dt_ioctl(dtp, DTRACEIOC_ENABLE, dof); 1577c478bd9Sstevel@tonic-gate dtrace_dof_destroy(dtp, dof); 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate if (n == -1) { 1607c478bd9Sstevel@tonic-gate switch (errno) { 1617c478bd9Sstevel@tonic-gate case EINVAL: 1627c478bd9Sstevel@tonic-gate err = EDT_DIFINVAL; 1637c478bd9Sstevel@tonic-gate break; 1647c478bd9Sstevel@tonic-gate case EFAULT: 1657c478bd9Sstevel@tonic-gate err = EDT_DIFFAULT; 1667c478bd9Sstevel@tonic-gate break; 1677c478bd9Sstevel@tonic-gate case E2BIG: 1687c478bd9Sstevel@tonic-gate err = EDT_DIFSIZE; 1697c478bd9Sstevel@tonic-gate break; 1707c478bd9Sstevel@tonic-gate default: 1717c478bd9Sstevel@tonic-gate err = errno; 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate return (dt_set_errno(dtp, err)); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate if (pip != NULL) 1787c478bd9Sstevel@tonic-gate pip->dpi_matches += n; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate return (0); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1831a7c1b72Smws static void 1841a7c1b72Smws dt_ecbdesc_hold(dtrace_ecbdesc_t *edp) 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate edp->dted_refcnt++; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate void 1901a7c1b72Smws dt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate if (--edp->dted_refcnt > 0) 1937c478bd9Sstevel@tonic-gate return; 1947c478bd9Sstevel@tonic-gate 1951a7c1b72Smws dt_difo_free(dtp, edp->dted_pred.dtpdd_difo); 1967c478bd9Sstevel@tonic-gate assert(edp->dted_action == NULL); 1971a7c1b72Smws dt_free(dtp, edp); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t * 2011a7c1b72Smws dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp) 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp; 2047c478bd9Sstevel@tonic-gate 2051a7c1b72Smws if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) { 2067c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOMEM); 2077c478bd9Sstevel@tonic-gate return (NULL); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate edp->dted_probe = *pdp; 2111a7c1b72Smws dt_ecbdesc_hold(edp); 2127c478bd9Sstevel@tonic-gate return (edp); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate dtrace_stmtdesc_t * 2167c478bd9Sstevel@tonic-gate dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 2177c478bd9Sstevel@tonic-gate { 2187c478bd9Sstevel@tonic-gate dtrace_stmtdesc_t *sdp; 2197c478bd9Sstevel@tonic-gate 2201a7c1b72Smws if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL) 2217c478bd9Sstevel@tonic-gate return (NULL); 2227c478bd9Sstevel@tonic-gate 2231a7c1b72Smws dt_ecbdesc_hold(edp); 2247c478bd9Sstevel@tonic-gate sdp->dtsd_ecbdesc = edp; 2257c478bd9Sstevel@tonic-gate sdp->dtsd_descattr = _dtrace_defattr; 2267c478bd9Sstevel@tonic-gate sdp->dtsd_stmtattr = _dtrace_defattr; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate return (sdp); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate dtrace_actdesc_t * 2327c478bd9Sstevel@tonic-gate dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate dtrace_actdesc_t *new; 2357c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 2367c478bd9Sstevel@tonic-gate 2371a7c1b72Smws if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL) 2387c478bd9Sstevel@tonic-gate return (NULL); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if (sdp->dtsd_action_last != NULL) { 2417c478bd9Sstevel@tonic-gate assert(sdp->dtsd_action != NULL); 2427c478bd9Sstevel@tonic-gate assert(sdp->dtsd_action_last->dtad_next == NULL); 2437c478bd9Sstevel@tonic-gate sdp->dtsd_action_last->dtad_next = new; 2447c478bd9Sstevel@tonic-gate } else { 2457c478bd9Sstevel@tonic-gate dtrace_actdesc_t *ap = edp->dted_action; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate assert(sdp->dtsd_action == NULL); 2487c478bd9Sstevel@tonic-gate sdp->dtsd_action = new; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate while (ap != NULL && ap->dtad_next != NULL) 2517c478bd9Sstevel@tonic-gate ap = ap->dtad_next; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate if (ap == NULL) 2547c478bd9Sstevel@tonic-gate edp->dted_action = new; 2557c478bd9Sstevel@tonic-gate else 2567c478bd9Sstevel@tonic-gate ap->dtad_next = new; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate sdp->dtsd_action_last = new; 2607c478bd9Sstevel@tonic-gate bzero(new, sizeof (dtrace_actdesc_t)); 2617c478bd9Sstevel@tonic-gate new->dtad_uarg = (uintptr_t)sdp; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate return (new); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate int 2677c478bd9Sstevel@tonic-gate dtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp) 2687c478bd9Sstevel@tonic-gate { 2691a7c1b72Smws dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t)); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate if (stp == NULL) 2721a7c1b72Smws return (-1); /* errno is set for us */ 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate dt_list_append(&pgp->dp_stmts, stp); 2757c478bd9Sstevel@tonic-gate stp->ds_desc = sdp; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate return (0); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate int 2817c478bd9Sstevel@tonic-gate dtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 2827c478bd9Sstevel@tonic-gate dtrace_stmt_f *func, void *data) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate dt_stmt_t *stp, *next; 2857c478bd9Sstevel@tonic-gate int status = 0; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 2887c478bd9Sstevel@tonic-gate next = dt_list_next(stp); 2897c478bd9Sstevel@tonic-gate if ((status = func(dtp, pgp, stp->ds_desc, data)) != 0) 2907c478bd9Sstevel@tonic-gate break; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate return (status); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate void 2971a7c1b72Smws dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * We need to remove any actions that we have on this ECB, and 3037c478bd9Sstevel@tonic-gate * remove our hold on the ECB itself. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate if (sdp->dtsd_action != NULL) { 3067c478bd9Sstevel@tonic-gate dtrace_actdesc_t *last = sdp->dtsd_action_last; 3077c478bd9Sstevel@tonic-gate dtrace_actdesc_t *ap, *next; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate assert(last != NULL); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 3127c478bd9Sstevel@tonic-gate if (ap == sdp->dtsd_action) 3137c478bd9Sstevel@tonic-gate break; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (ap->dtad_next == sdp->dtsd_action) 3167c478bd9Sstevel@tonic-gate break; 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate assert(ap != NULL); 3207c478bd9Sstevel@tonic-gate 3211a7c1b72Smws if (ap == edp->dted_action) 3227c478bd9Sstevel@tonic-gate edp->dted_action = last->dtad_next; 3231a7c1b72Smws else 3247c478bd9Sstevel@tonic-gate ap->dtad_next = last->dtad_next; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /* 3277c478bd9Sstevel@tonic-gate * We have now removed our action list from its ECB; we can 3287c478bd9Sstevel@tonic-gate * safely destroy the list. 3297c478bd9Sstevel@tonic-gate */ 3307c478bd9Sstevel@tonic-gate last->dtad_next = NULL; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate for (ap = sdp->dtsd_action; ap != NULL; ap = next) { 3337c478bd9Sstevel@tonic-gate assert(ap->dtad_uarg == (uintptr_t)sdp); 3341a7c1b72Smws dt_difo_free(dtp, ap->dtad_difo); 3357c478bd9Sstevel@tonic-gate next = ap->dtad_next; 3361a7c1b72Smws dt_free(dtp, ap); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL) 3417c478bd9Sstevel@tonic-gate dt_printf_destroy(sdp->dtsd_fmtdata); 3427c478bd9Sstevel@tonic-gate 3431a7c1b72Smws dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc); 3441a7c1b72Smws dt_free(dtp, sdp); 3457c478bd9Sstevel@tonic-gate } 346*900524f3Sahl 347*900524f3Sahl typedef struct dt_header_info { 348*900524f3Sahl dtrace_hdl_t *dthi_dtp; /* consumer handle */ 349*900524f3Sahl FILE *dthi_out; /* output file */ 350*900524f3Sahl char *dthi_pmname; /* provider macro name */ 351*900524f3Sahl char *dthi_pfname; /* provider function name */ 352*900524f3Sahl } dt_header_info_t; 353*900524f3Sahl 354*900524f3Sahl 355*900524f3Sahl static void 356*900524f3Sahl dt_header_fmt_macro(char *buf, const char *str) 357*900524f3Sahl { 358*900524f3Sahl for (;;) { 359*900524f3Sahl if (islower(*str)) { 360*900524f3Sahl *buf++ = *str++ + 'A' - 'a'; 361*900524f3Sahl } else if (*str == '-') { 362*900524f3Sahl *buf++ = '_'; 363*900524f3Sahl str++; 364*900524f3Sahl } else if (*str == '.') { 365*900524f3Sahl *buf++ = '_'; 366*900524f3Sahl str++; 367*900524f3Sahl } else if ((*buf++ = *str++) == '\0') { 368*900524f3Sahl break; 369*900524f3Sahl } 370*900524f3Sahl } 371*900524f3Sahl } 372*900524f3Sahl 373*900524f3Sahl static void 374*900524f3Sahl dt_header_fmt_func(char *buf, const char *str) 375*900524f3Sahl { 376*900524f3Sahl for (;;) { 377*900524f3Sahl if (*str == '-') { 378*900524f3Sahl *buf++ = '_'; 379*900524f3Sahl *buf++ = '_'; 380*900524f3Sahl str++; 381*900524f3Sahl } else if ((*buf++ = *str++) == '\0') { 382*900524f3Sahl break; 383*900524f3Sahl } 384*900524f3Sahl } 385*900524f3Sahl } 386*900524f3Sahl 387*900524f3Sahl /*ARGSUSED*/ 388*900524f3Sahl static int 389*900524f3Sahl dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 390*900524f3Sahl { 391*900524f3Sahl dt_header_info_t *infop = data; 392*900524f3Sahl dtrace_hdl_t *dtp = infop->dthi_dtp; 393*900524f3Sahl dt_probe_t *prp = idp->di_data; 394*900524f3Sahl dt_node_t *dnp; 395*900524f3Sahl char buf[DT_TYPE_NAMELEN]; 396*900524f3Sahl char *fname; 397*900524f3Sahl const char *p; 398*900524f3Sahl int i; 399*900524f3Sahl 400*900524f3Sahl p = prp->pr_name; 401*900524f3Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 402*900524f3Sahl p++; 403*900524f3Sahl 404*900524f3Sahl fname = alloca(strlen(prp->pr_name) + 1 + i); 405*900524f3Sahl dt_header_fmt_func(fname, prp->pr_name); 406*900524f3Sahl 407*900524f3Sahl if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(", 408*900524f3Sahl infop->dthi_pfname, fname) < 0) 409*900524f3Sahl return (dt_set_errno(dtp, errno)); 410*900524f3Sahl 411*900524f3Sahl for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) { 412*900524f3Sahl if (fprintf(infop->dthi_out, "%s", 413*900524f3Sahl ctf_type_name(dnp->dn_ctfp, dnp->dn_type, 414*900524f3Sahl buf, sizeof (buf))) < 0) 415*900524f3Sahl return (dt_set_errno(dtp, errno)); 416*900524f3Sahl 417*900524f3Sahl if (i + 1 != prp->pr_nargc && 418*900524f3Sahl fprintf(infop->dthi_out, ", ") < 0) 419*900524f3Sahl return (dt_set_errno(dtp, errno)); 420*900524f3Sahl } 421*900524f3Sahl 422*900524f3Sahl if (i == 0 && fprintf(infop->dthi_out, "void") < 0) 423*900524f3Sahl return (dt_set_errno(dtp, errno)); 424*900524f3Sahl 425*900524f3Sahl if (fprintf(infop->dthi_out, ");\n") < 0) 426*900524f3Sahl return (dt_set_errno(dtp, errno)); 427*900524f3Sahl 428*900524f3Sahl return (0); 429*900524f3Sahl } 430*900524f3Sahl 431*900524f3Sahl /*ARGSUSED*/ 432*900524f3Sahl static int 433*900524f3Sahl dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 434*900524f3Sahl { 435*900524f3Sahl dt_header_info_t *infop = data; 436*900524f3Sahl dtrace_hdl_t *dtp = infop->dthi_dtp; 437*900524f3Sahl dt_probe_t *prp = idp->di_data; 438*900524f3Sahl char *mname, *fname; 439*900524f3Sahl const char *p; 440*900524f3Sahl int i; 441*900524f3Sahl 442*900524f3Sahl p = prp->pr_name; 443*900524f3Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 444*900524f3Sahl p++; 445*900524f3Sahl 446*900524f3Sahl mname = alloca(strlen(prp->pr_name) + 1); 447*900524f3Sahl dt_header_fmt_macro(mname, prp->pr_name); 448*900524f3Sahl 449*900524f3Sahl fname = alloca(strlen(prp->pr_name) + 1 + i); 450*900524f3Sahl dt_header_fmt_func(fname, prp->pr_name); 451*900524f3Sahl 452*900524f3Sahl if (fprintf(infop->dthi_out, "#define\t%s_%s(", 453*900524f3Sahl infop->dthi_pmname, mname) < 0) 454*900524f3Sahl return (dt_set_errno(dtp, errno)); 455*900524f3Sahl 456*900524f3Sahl for (i = 0; i < prp->pr_nargc; i++) { 457*900524f3Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0) 458*900524f3Sahl return (dt_set_errno(dtp, errno)); 459*900524f3Sahl 460*900524f3Sahl if (i + 1 != prp->pr_nargc && 461*900524f3Sahl fprintf(infop->dthi_out, ", ") < 0) 462*900524f3Sahl return (dt_set_errno(dtp, errno)); 463*900524f3Sahl } 464*900524f3Sahl 465*900524f3Sahl if (fprintf(infop->dthi_out, ") \\\n\t") < 0) 466*900524f3Sahl return (dt_set_errno(dtp, errno)); 467*900524f3Sahl 468*900524f3Sahl if (fprintf(infop->dthi_out, "__dtrace_%s___%s(", 469*900524f3Sahl infop->dthi_pfname, fname) < 0) 470*900524f3Sahl return (dt_set_errno(dtp, errno)); 471*900524f3Sahl 472*900524f3Sahl for (i = 0; i < prp->pr_nargc; i++) { 473*900524f3Sahl if (fprintf(infop->dthi_out, "arg%d", i) < 0) 474*900524f3Sahl return (dt_set_errno(dtp, errno)); 475*900524f3Sahl 476*900524f3Sahl if (i + 1 != prp->pr_nargc && 477*900524f3Sahl fprintf(infop->dthi_out, ", ") < 0) 478*900524f3Sahl return (dt_set_errno(dtp, errno)); 479*900524f3Sahl } 480*900524f3Sahl 481*900524f3Sahl if (fprintf(infop->dthi_out, ")\n") < 0) 482*900524f3Sahl return (dt_set_errno(dtp, errno)); 483*900524f3Sahl 484*900524f3Sahl return (0); 485*900524f3Sahl } 486*900524f3Sahl 487*900524f3Sahl static int 488*900524f3Sahl dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out) 489*900524f3Sahl { 490*900524f3Sahl dt_header_info_t info; 491*900524f3Sahl const char *p; 492*900524f3Sahl int i; 493*900524f3Sahl 494*900524f3Sahl if (pvp->pv_flags & DT_PROVIDER_IMPL) 495*900524f3Sahl return (0); 496*900524f3Sahl 497*900524f3Sahl p = pvp->pv_desc.dtvd_name; 498*900524f3Sahl for (i = 0; (p = strchr(p, '-')) != NULL; i++) 499*900524f3Sahl p++; 500*900524f3Sahl 501*900524f3Sahl info.dthi_dtp = dtp; 502*900524f3Sahl info.dthi_out = out; 503*900524f3Sahl 504*900524f3Sahl info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1); 505*900524f3Sahl dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name); 506*900524f3Sahl 507*900524f3Sahl info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i); 508*900524f3Sahl dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name); 509*900524f3Sahl 510*900524f3Sahl 511*900524f3Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 512*900524f3Sahl return (-1); /* dt_errno is set for us */ 513*900524f3Sahl if (fprintf(out, "\n\n") < 0) 514*900524f3Sahl return (dt_set_errno(dtp, errno)); 515*900524f3Sahl if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0) 516*900524f3Sahl return (-1); /* dt_errno is set for us */ 517*900524f3Sahl 518*900524f3Sahl return (0); 519*900524f3Sahl } 520*900524f3Sahl 521*900524f3Sahl int 522*900524f3Sahl dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname) 523*900524f3Sahl { 524*900524f3Sahl dt_provider_t *pvp; 525*900524f3Sahl char *mfname, *p; 526*900524f3Sahl 527*900524f3Sahl if (fname != NULL) { 528*900524f3Sahl if ((p = strrchr(fname, '/')) != NULL) 529*900524f3Sahl fname = p + 1; 530*900524f3Sahl 531*900524f3Sahl mfname = alloca(strlen(fname) + 1); 532*900524f3Sahl dt_header_fmt_macro(mfname, fname); 533*900524f3Sahl if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n", 534*900524f3Sahl mfname, mfname) < 0) 535*900524f3Sahl return (dt_set_errno(dtp, errno)); 536*900524f3Sahl } 537*900524f3Sahl 538*900524f3Sahl if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0) 539*900524f3Sahl return (-1); 540*900524f3Sahl 541*900524f3Sahl for (pvp = dt_list_next(&dtp->dt_provlist); 542*900524f3Sahl pvp != NULL; pvp = dt_list_next(pvp)) { 543*900524f3Sahl if (dt_header_provider(dtp, pvp, out) != 0) 544*900524f3Sahl return (-1); /* dt_errno is set for us */ 545*900524f3Sahl } 546*900524f3Sahl 547*900524f3Sahl if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0) 548*900524f3Sahl return (dt_set_errno(dtp, errno)); 549*900524f3Sahl 550*900524f3Sahl if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0) 551*900524f3Sahl return (dt_set_errno(dtp, errno)); 552*900524f3Sahl 553*900524f3Sahl return (0); 554*900524f3Sahl } 555