16ff6d951SJohn Birrell /* 26ff6d951SJohn Birrell * CDDL HEADER START 36ff6d951SJohn Birrell * 46ff6d951SJohn Birrell * The contents of this file are subject to the terms of the 56ff6d951SJohn Birrell * Common Development and Distribution License (the "License"). 66ff6d951SJohn Birrell * You may not use this file except in compliance with the License. 76ff6d951SJohn Birrell * 86ff6d951SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96ff6d951SJohn Birrell * or http://www.opensolaris.org/os/licensing. 106ff6d951SJohn Birrell * See the License for the specific language governing permissions 116ff6d951SJohn Birrell * and limitations under the License. 126ff6d951SJohn Birrell * 136ff6d951SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 146ff6d951SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156ff6d951SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 166ff6d951SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 176ff6d951SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 186ff6d951SJohn Birrell * 196ff6d951SJohn Birrell * CDDL HEADER END 206ff6d951SJohn Birrell */ 216ff6d951SJohn Birrell 226ff6d951SJohn Birrell /* 231670a1c2SRui Paulo * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 246ff6d951SJohn Birrell */ 256ff6d951SJohn Birrell 266ff6d951SJohn Birrell #include <unistd.h> 276ff6d951SJohn Birrell #include <strings.h> 286ff6d951SJohn Birrell #include <stdlib.h> 296ff6d951SJohn Birrell #include <errno.h> 306ff6d951SJohn Birrell #include <assert.h> 316ff6d951SJohn Birrell #include <ctype.h> 32df5c121dSJohn Birrell #if defined(sun) 336ff6d951SJohn Birrell #include <alloca.h> 34df5c121dSJohn Birrell #endif 356ff6d951SJohn Birrell 366ff6d951SJohn Birrell #include <dt_impl.h> 376ff6d951SJohn Birrell #include <dt_program.h> 386ff6d951SJohn Birrell #include <dt_printf.h> 396ff6d951SJohn Birrell #include <dt_provider.h> 406ff6d951SJohn Birrell 416ff6d951SJohn Birrell dtrace_prog_t * 426ff6d951SJohn Birrell dt_program_create(dtrace_hdl_t *dtp) 436ff6d951SJohn Birrell { 446ff6d951SJohn Birrell dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t)); 456ff6d951SJohn Birrell 461670a1c2SRui Paulo if (pgp != NULL) { 476ff6d951SJohn Birrell dt_list_append(&dtp->dt_programs, pgp); 481670a1c2SRui Paulo } else { 496ff6d951SJohn Birrell (void) dt_set_errno(dtp, EDT_NOMEM); 501670a1c2SRui Paulo return (NULL); 511670a1c2SRui Paulo } 526ff6d951SJohn Birrell 536ff6d951SJohn Birrell /* 546ff6d951SJohn Birrell * By default, programs start with DOF version 1 so that output files 556ff6d951SJohn Birrell * containing DOF are backward compatible. If a program requires new 566ff6d951SJohn Birrell * DOF features, the version is increased as needed. 576ff6d951SJohn Birrell */ 586ff6d951SJohn Birrell pgp->dp_dofversion = DOF_VERSION_1; 596ff6d951SJohn Birrell 606ff6d951SJohn Birrell return (pgp); 616ff6d951SJohn Birrell } 626ff6d951SJohn Birrell 636ff6d951SJohn Birrell void 646ff6d951SJohn Birrell dt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) 656ff6d951SJohn Birrell { 666ff6d951SJohn Birrell dt_stmt_t *stp, *next; 676ff6d951SJohn Birrell uint_t i; 686ff6d951SJohn Birrell 696ff6d951SJohn Birrell for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 706ff6d951SJohn Birrell next = dt_list_next(stp); 716ff6d951SJohn Birrell dtrace_stmt_destroy(dtp, stp->ds_desc); 726ff6d951SJohn Birrell dt_free(dtp, stp); 736ff6d951SJohn Birrell } 746ff6d951SJohn Birrell 756ff6d951SJohn Birrell for (i = 0; i < pgp->dp_xrefslen; i++) 766ff6d951SJohn Birrell dt_free(dtp, pgp->dp_xrefs[i]); 776ff6d951SJohn Birrell 786ff6d951SJohn Birrell dt_free(dtp, pgp->dp_xrefs); 796ff6d951SJohn Birrell dt_list_delete(&dtp->dt_programs, pgp); 806ff6d951SJohn Birrell dt_free(dtp, pgp); 816ff6d951SJohn Birrell } 826ff6d951SJohn Birrell 836ff6d951SJohn Birrell /*ARGSUSED*/ 846ff6d951SJohn Birrell void 856ff6d951SJohn Birrell dtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 866ff6d951SJohn Birrell dtrace_proginfo_t *pip) 876ff6d951SJohn Birrell { 886ff6d951SJohn Birrell dt_stmt_t *stp; 896ff6d951SJohn Birrell dtrace_actdesc_t *ap; 906ff6d951SJohn Birrell dtrace_ecbdesc_t *last = NULL; 916ff6d951SJohn Birrell 926ff6d951SJohn Birrell if (pip == NULL) 936ff6d951SJohn Birrell return; 946ff6d951SJohn Birrell 956ff6d951SJohn Birrell bzero(pip, sizeof (dtrace_proginfo_t)); 966ff6d951SJohn Birrell 976ff6d951SJohn Birrell if (dt_list_next(&pgp->dp_stmts) != NULL) { 986ff6d951SJohn Birrell pip->dpi_descattr = _dtrace_maxattr; 996ff6d951SJohn Birrell pip->dpi_stmtattr = _dtrace_maxattr; 1006ff6d951SJohn Birrell } else { 1016ff6d951SJohn Birrell pip->dpi_descattr = _dtrace_defattr; 1026ff6d951SJohn Birrell pip->dpi_stmtattr = _dtrace_defattr; 1036ff6d951SJohn Birrell } 1046ff6d951SJohn Birrell 1056ff6d951SJohn Birrell for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) { 1066ff6d951SJohn Birrell dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc; 1076ff6d951SJohn Birrell 1086ff6d951SJohn Birrell if (edp == last) 1096ff6d951SJohn Birrell continue; 1106ff6d951SJohn Birrell last = edp; 1116ff6d951SJohn Birrell 1126ff6d951SJohn Birrell pip->dpi_descattr = 1136ff6d951SJohn Birrell dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr); 1146ff6d951SJohn Birrell 1156ff6d951SJohn Birrell pip->dpi_stmtattr = 1166ff6d951SJohn Birrell dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr); 1176ff6d951SJohn Birrell 1186ff6d951SJohn Birrell /* 1196ff6d951SJohn Birrell * If there aren't any actions, account for the fact that 1206ff6d951SJohn Birrell * recording the epid will generate a record. 1216ff6d951SJohn Birrell */ 1226ff6d951SJohn Birrell if (edp->dted_action == NULL) 1236ff6d951SJohn Birrell pip->dpi_recgens++; 1246ff6d951SJohn Birrell 1256ff6d951SJohn Birrell for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 1266ff6d951SJohn Birrell if (ap->dtad_kind == DTRACEACT_SPECULATE) { 1276ff6d951SJohn Birrell pip->dpi_speculations++; 1286ff6d951SJohn Birrell continue; 1296ff6d951SJohn Birrell } 1306ff6d951SJohn Birrell 1316ff6d951SJohn Birrell if (DTRACEACT_ISAGG(ap->dtad_kind)) { 1326ff6d951SJohn Birrell pip->dpi_recgens -= ap->dtad_arg; 1336ff6d951SJohn Birrell pip->dpi_aggregates++; 1346ff6d951SJohn Birrell continue; 1356ff6d951SJohn Birrell } 1366ff6d951SJohn Birrell 1376ff6d951SJohn Birrell if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind)) 1386ff6d951SJohn Birrell continue; 1396ff6d951SJohn Birrell 1406ff6d951SJohn Birrell if (ap->dtad_kind == DTRACEACT_DIFEXPR && 1416ff6d951SJohn Birrell ap->dtad_difo->dtdo_rtype.dtdt_kind == 1426ff6d951SJohn Birrell DIF_TYPE_CTF && 1436ff6d951SJohn Birrell ap->dtad_difo->dtdo_rtype.dtdt_size == 0) 1446ff6d951SJohn Birrell continue; 1456ff6d951SJohn Birrell 1466ff6d951SJohn Birrell pip->dpi_recgens++; 1476ff6d951SJohn Birrell } 1486ff6d951SJohn Birrell } 1496ff6d951SJohn Birrell } 1506ff6d951SJohn Birrell 1516ff6d951SJohn Birrell int 1526ff6d951SJohn Birrell dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 1536ff6d951SJohn Birrell dtrace_proginfo_t *pip) 1546ff6d951SJohn Birrell { 155df5c121dSJohn Birrell dtrace_enable_io_t args; 1566ff6d951SJohn Birrell void *dof; 1576ff6d951SJohn Birrell int n, err; 1586ff6d951SJohn Birrell 1596ff6d951SJohn Birrell dtrace_program_info(dtp, pgp, pip); 1606ff6d951SJohn Birrell 1616ff6d951SJohn Birrell if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL) 1626ff6d951SJohn Birrell return (-1); 1636ff6d951SJohn Birrell 164df5c121dSJohn Birrell args.dof = dof; 165df5c121dSJohn Birrell args.n_matched = 0; 166df5c121dSJohn Birrell n = dt_ioctl(dtp, DTRACEIOC_ENABLE, &args); 1676ff6d951SJohn Birrell dtrace_dof_destroy(dtp, dof); 1686ff6d951SJohn Birrell 1696ff6d951SJohn Birrell if (n == -1) { 1706ff6d951SJohn Birrell switch (errno) { 1716ff6d951SJohn Birrell case EINVAL: 1726ff6d951SJohn Birrell err = EDT_DIFINVAL; 1736ff6d951SJohn Birrell break; 1746ff6d951SJohn Birrell case EFAULT: 1756ff6d951SJohn Birrell err = EDT_DIFFAULT; 1766ff6d951SJohn Birrell break; 1776ff6d951SJohn Birrell case E2BIG: 1786ff6d951SJohn Birrell err = EDT_DIFSIZE; 1796ff6d951SJohn Birrell break; 1801670a1c2SRui Paulo case EBUSY: 1811670a1c2SRui Paulo err = EDT_ENABLING_ERR; 1821670a1c2SRui Paulo break; 1836ff6d951SJohn Birrell default: 1846ff6d951SJohn Birrell err = errno; 1856ff6d951SJohn Birrell } 1866ff6d951SJohn Birrell 1876ff6d951SJohn Birrell return (dt_set_errno(dtp, err)); 1886ff6d951SJohn Birrell } 1896ff6d951SJohn Birrell 1906ff6d951SJohn Birrell if (pip != NULL) 191df5c121dSJohn Birrell pip->dpi_matches += args.n_matched; 1926ff6d951SJohn Birrell 1936ff6d951SJohn Birrell return (0); 1946ff6d951SJohn Birrell } 1956ff6d951SJohn Birrell 1966ff6d951SJohn Birrell static void 1976ff6d951SJohn Birrell dt_ecbdesc_hold(dtrace_ecbdesc_t *edp) 1986ff6d951SJohn Birrell { 1996ff6d951SJohn Birrell edp->dted_refcnt++; 2006ff6d951SJohn Birrell } 2016ff6d951SJohn Birrell 2026ff6d951SJohn Birrell void 2036ff6d951SJohn Birrell dt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 2046ff6d951SJohn Birrell { 2056ff6d951SJohn Birrell if (--edp->dted_refcnt > 0) 2066ff6d951SJohn Birrell return; 2076ff6d951SJohn Birrell 2086ff6d951SJohn Birrell dt_difo_free(dtp, edp->dted_pred.dtpdd_difo); 2096ff6d951SJohn Birrell assert(edp->dted_action == NULL); 2106ff6d951SJohn Birrell dt_free(dtp, edp); 2116ff6d951SJohn Birrell } 2126ff6d951SJohn Birrell 2136ff6d951SJohn Birrell dtrace_ecbdesc_t * 2146ff6d951SJohn Birrell dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp) 2156ff6d951SJohn Birrell { 2166ff6d951SJohn Birrell dtrace_ecbdesc_t *edp; 2176ff6d951SJohn Birrell 2186ff6d951SJohn Birrell if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) { 2196ff6d951SJohn Birrell (void) dt_set_errno(dtp, EDT_NOMEM); 2206ff6d951SJohn Birrell return (NULL); 2216ff6d951SJohn Birrell } 2226ff6d951SJohn Birrell 2236ff6d951SJohn Birrell edp->dted_probe = *pdp; 2246ff6d951SJohn Birrell dt_ecbdesc_hold(edp); 2256ff6d951SJohn Birrell return (edp); 2266ff6d951SJohn Birrell } 2276ff6d951SJohn Birrell 2286ff6d951SJohn Birrell dtrace_stmtdesc_t * 2296ff6d951SJohn Birrell dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 2306ff6d951SJohn Birrell { 2316ff6d951SJohn Birrell dtrace_stmtdesc_t *sdp; 2326ff6d951SJohn Birrell 2336ff6d951SJohn Birrell if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL) 2346ff6d951SJohn Birrell return (NULL); 2356ff6d951SJohn Birrell 2366ff6d951SJohn Birrell dt_ecbdesc_hold(edp); 2376ff6d951SJohn Birrell sdp->dtsd_ecbdesc = edp; 2386ff6d951SJohn Birrell sdp->dtsd_descattr = _dtrace_defattr; 2396ff6d951SJohn Birrell sdp->dtsd_stmtattr = _dtrace_defattr; 2406ff6d951SJohn Birrell 2416ff6d951SJohn Birrell return (sdp); 2426ff6d951SJohn Birrell } 2436ff6d951SJohn Birrell 2446ff6d951SJohn Birrell dtrace_actdesc_t * 2456ff6d951SJohn Birrell dtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 2466ff6d951SJohn Birrell { 2476ff6d951SJohn Birrell dtrace_actdesc_t *new; 2486ff6d951SJohn Birrell dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 2496ff6d951SJohn Birrell 2506ff6d951SJohn Birrell if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL) 2516ff6d951SJohn Birrell return (NULL); 2526ff6d951SJohn Birrell 2536ff6d951SJohn Birrell if (sdp->dtsd_action_last != NULL) { 2546ff6d951SJohn Birrell assert(sdp->dtsd_action != NULL); 2556ff6d951SJohn Birrell assert(sdp->dtsd_action_last->dtad_next == NULL); 2566ff6d951SJohn Birrell sdp->dtsd_action_last->dtad_next = new; 2576ff6d951SJohn Birrell } else { 2586ff6d951SJohn Birrell dtrace_actdesc_t *ap = edp->dted_action; 2596ff6d951SJohn Birrell 2606ff6d951SJohn Birrell assert(sdp->dtsd_action == NULL); 2616ff6d951SJohn Birrell sdp->dtsd_action = new; 2626ff6d951SJohn Birrell 2636ff6d951SJohn Birrell while (ap != NULL && ap->dtad_next != NULL) 2646ff6d951SJohn Birrell ap = ap->dtad_next; 2656ff6d951SJohn Birrell 2666ff6d951SJohn Birrell if (ap == NULL) 2676ff6d951SJohn Birrell edp->dted_action = new; 2686ff6d951SJohn Birrell else 2696ff6d951SJohn Birrell ap->dtad_next = new; 2706ff6d951SJohn Birrell } 2716ff6d951SJohn Birrell 2726ff6d951SJohn Birrell sdp->dtsd_action_last = new; 2736ff6d951SJohn Birrell bzero(new, sizeof (dtrace_actdesc_t)); 2746ff6d951SJohn Birrell new->dtad_uarg = (uintptr_t)sdp; 2756ff6d951SJohn Birrell 2766ff6d951SJohn Birrell return (new); 2776ff6d951SJohn Birrell } 2786ff6d951SJohn Birrell 2796ff6d951SJohn Birrell int 2806ff6d951SJohn Birrell dtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp) 2816ff6d951SJohn Birrell { 2826ff6d951SJohn Birrell dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t)); 2836ff6d951SJohn Birrell 2846ff6d951SJohn Birrell if (stp == NULL) 2856ff6d951SJohn Birrell return (-1); /* errno is set for us */ 2866ff6d951SJohn Birrell 2876ff6d951SJohn Birrell dt_list_append(&pgp->dp_stmts, stp); 2886ff6d951SJohn Birrell stp->ds_desc = sdp; 2896ff6d951SJohn Birrell 2906ff6d951SJohn Birrell return (0); 2916ff6d951SJohn Birrell } 2926ff6d951SJohn Birrell 2936ff6d951SJohn Birrell int 2946ff6d951SJohn Birrell dtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 2956ff6d951SJohn Birrell dtrace_stmt_f *func, void *data) 2966ff6d951SJohn Birrell { 2976ff6d951SJohn Birrell dt_stmt_t *stp, *next; 2986ff6d951SJohn Birrell int status = 0; 2996ff6d951SJohn Birrell 3006ff6d951SJohn Birrell for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 3016ff6d951SJohn Birrell next = dt_list_next(stp); 3026ff6d951SJohn Birrell if ((status = func(dtp, pgp, stp->ds_desc, data)) != 0) 3036ff6d951SJohn Birrell break; 3046ff6d951SJohn Birrell } 3056ff6d951SJohn Birrell 3066ff6d951SJohn Birrell return (status); 3076ff6d951SJohn Birrell } 3086ff6d951SJohn Birrell 3096ff6d951SJohn Birrell void 3106ff6d951SJohn Birrell dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 3116ff6d951SJohn Birrell { 3126ff6d951SJohn Birrell dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 3136ff6d951SJohn Birrell 3146ff6d951SJohn Birrell /* 3156ff6d951SJohn Birrell * We need to remove any actions that we have on this ECB, and 3166ff6d951SJohn Birrell * remove our hold on the ECB itself. 3176ff6d951SJohn Birrell */ 3186ff6d951SJohn Birrell if (sdp->dtsd_action != NULL) { 3196ff6d951SJohn Birrell dtrace_actdesc_t *last = sdp->dtsd_action_last; 3206ff6d951SJohn Birrell dtrace_actdesc_t *ap, *next; 3216ff6d951SJohn Birrell 3226ff6d951SJohn Birrell assert(last != NULL); 3236ff6d951SJohn Birrell 3246ff6d951SJohn Birrell for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 3256ff6d951SJohn Birrell if (ap == sdp->dtsd_action) 3266ff6d951SJohn Birrell break; 3276ff6d951SJohn Birrell 3286ff6d951SJohn Birrell if (ap->dtad_next == sdp->dtsd_action) 3296ff6d951SJohn Birrell break; 3306ff6d951SJohn Birrell } 3316ff6d951SJohn Birrell 3326ff6d951SJohn Birrell assert(ap != NULL); 3336ff6d951SJohn Birrell 3346ff6d951SJohn Birrell if (ap == edp->dted_action) 3356ff6d951SJohn Birrell edp->dted_action = last->dtad_next; 3366ff6d951SJohn Birrell else 3376ff6d951SJohn Birrell ap->dtad_next = last->dtad_next; 3386ff6d951SJohn Birrell 3396ff6d951SJohn Birrell /* 3406ff6d951SJohn Birrell * We have now removed our action list from its ECB; we can 3416ff6d951SJohn Birrell * safely destroy the list. 3426ff6d951SJohn Birrell */ 3436ff6d951SJohn Birrell last->dtad_next = NULL; 3446ff6d951SJohn Birrell 3456ff6d951SJohn Birrell for (ap = sdp->dtsd_action; ap != NULL; ap = next) { 3466ff6d951SJohn Birrell assert(ap->dtad_uarg == (uintptr_t)sdp); 3476ff6d951SJohn Birrell dt_difo_free(dtp, ap->dtad_difo); 3486ff6d951SJohn Birrell next = ap->dtad_next; 3496ff6d951SJohn Birrell dt_free(dtp, ap); 3506ff6d951SJohn Birrell } 3516ff6d951SJohn Birrell } 3526ff6d951SJohn Birrell 3536ff6d951SJohn Birrell if (sdp->dtsd_fmtdata != NULL) 3546ff6d951SJohn Birrell dt_printf_destroy(sdp->dtsd_fmtdata); 3556ff6d951SJohn Birrell 3566ff6d951SJohn Birrell dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc); 3576ff6d951SJohn Birrell dt_free(dtp, sdp); 3586ff6d951SJohn Birrell } 3596ff6d951SJohn Birrell 3606ff6d951SJohn Birrell typedef struct dt_header_info { 3616ff6d951SJohn Birrell dtrace_hdl_t *dthi_dtp; /* consumer handle */ 3626ff6d951SJohn Birrell FILE *dthi_out; /* output file */ 3636ff6d951SJohn Birrell char *dthi_pmname; /* provider macro name */ 3646ff6d951SJohn Birrell char *dthi_pfname; /* provider function name */ 3656ff6d951SJohn Birrell int dthi_empty; /* should we generate empty macros */ 3666ff6d951SJohn Birrell } dt_header_info_t; 3676ff6d951SJohn Birrell 3686ff6d951SJohn Birrell static void 3696ff6d951SJohn Birrell dt_header_fmt_macro(char *buf, const char *str) 3706ff6d951SJohn Birrell { 3716ff6d951SJohn Birrell for (;;) { 3726ff6d951SJohn Birrell if (islower(*str)) { 3736ff6d951SJohn Birrell *buf++ = *str++ + 'A' - 'a'; 3746ff6d951SJohn Birrell } else if (*str == '-') { 3756ff6d951SJohn Birrell *buf++ = '_'; 3766ff6d951SJohn Birrell str++; 3776ff6d951SJohn Birrell } else if (*str == '.') { 3786ff6d951SJohn Birrell *buf++ = '_'; 3796ff6d951SJohn Birrell str++; 3806ff6d951SJohn Birrell } else if ((*buf++ = *str++) == '\0') { 3816ff6d951SJohn Birrell break; 3826ff6d951SJohn Birrell } 3836ff6d951SJohn Birrell } 3846ff6d951SJohn Birrell } 3856ff6d951SJohn Birrell 3866ff6d951SJohn Birrell static void 3876ff6d951SJohn Birrell dt_header_fmt_func(char *buf, const char *str) 3886ff6d951SJohn Birrell { 3896ff6d951SJohn Birrell for (;;) { 3906ff6d951SJohn Birrell if (*str == '-') { 3916ff6d951SJohn Birrell *buf++ = '_'; 3926ff6d951SJohn Birrell *buf++ = '_'; 3936ff6d951SJohn Birrell str++; 3946ff6d951SJohn Birrell } else if ((*buf++ = *str++) == '\0') { 3956ff6d951SJohn Birrell break; 3966ff6d951SJohn Birrell } 3976ff6d951SJohn Birrell } 3986ff6d951SJohn Birrell } 3996ff6d951SJohn Birrell 4006ff6d951SJohn Birrell /*ARGSUSED*/ 4016ff6d951SJohn Birrell static int 4026ff6d951SJohn Birrell dt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 4036ff6d951SJohn Birrell { 4046ff6d951SJohn Birrell dt_header_info_t *infop = data; 4056ff6d951SJohn Birrell dtrace_hdl_t *dtp = infop->dthi_dtp; 4066ff6d951SJohn Birrell dt_probe_t *prp = idp->di_data; 4076ff6d951SJohn Birrell dt_node_t *dnp; 4086ff6d951SJohn Birrell char buf[DT_TYPE_NAMELEN]; 4096ff6d951SJohn Birrell char *fname; 4106ff6d951SJohn Birrell const char *p; 4116ff6d951SJohn Birrell int i; 4126ff6d951SJohn Birrell 4136ff6d951SJohn Birrell p = prp->pr_name; 4146ff6d951SJohn Birrell for (i = 0; (p = strchr(p, '-')) != NULL; i++) 4156ff6d951SJohn Birrell p++; 4166ff6d951SJohn Birrell 4176ff6d951SJohn Birrell fname = alloca(strlen(prp->pr_name) + 1 + i); 4186ff6d951SJohn Birrell dt_header_fmt_func(fname, prp->pr_name); 4196ff6d951SJohn Birrell 4206ff6d951SJohn Birrell if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(", 4216ff6d951SJohn Birrell infop->dthi_pfname, fname) < 0) 4226ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4236ff6d951SJohn Birrell 4246ff6d951SJohn Birrell for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) { 4256ff6d951SJohn Birrell if (fprintf(infop->dthi_out, "%s", 4266ff6d951SJohn Birrell ctf_type_name(dnp->dn_ctfp, dnp->dn_type, 4276ff6d951SJohn Birrell buf, sizeof (buf))) < 0) 4286ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4296ff6d951SJohn Birrell 4306ff6d951SJohn Birrell if (i + 1 != prp->pr_nargc && 4316ff6d951SJohn Birrell fprintf(infop->dthi_out, ", ") < 0) 4326ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4336ff6d951SJohn Birrell } 4346ff6d951SJohn Birrell 4356ff6d951SJohn Birrell if (i == 0 && fprintf(infop->dthi_out, "void") < 0) 4366ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4376ff6d951SJohn Birrell 4386ff6d951SJohn Birrell if (fprintf(infop->dthi_out, ");\n") < 0) 4396ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4406ff6d951SJohn Birrell 44156b35563SCraig Rodrigues if (fprintf(infop->dthi_out, 44256b35563SCraig Rodrigues "#ifndef\t__sparc\n" 44356b35563SCraig Rodrigues "extern int __dtraceenabled_%s___%s(void);\n" 44456b35563SCraig Rodrigues "#else\n" 44556b35563SCraig Rodrigues "extern int __dtraceenabled_%s___%s(long);\n" 44656b35563SCraig Rodrigues "#endif\n", 44756b35563SCraig Rodrigues infop->dthi_pfname, fname, infop->dthi_pfname, fname) < 0) 4486ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4496ff6d951SJohn Birrell 4506ff6d951SJohn Birrell return (0); 4516ff6d951SJohn Birrell } 4526ff6d951SJohn Birrell 4536ff6d951SJohn Birrell /*ARGSUSED*/ 4546ff6d951SJohn Birrell static int 4556ff6d951SJohn Birrell dt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 4566ff6d951SJohn Birrell { 4576ff6d951SJohn Birrell dt_header_info_t *infop = data; 4586ff6d951SJohn Birrell dtrace_hdl_t *dtp = infop->dthi_dtp; 4596ff6d951SJohn Birrell dt_probe_t *prp = idp->di_data; 4606ff6d951SJohn Birrell char *mname, *fname; 4616ff6d951SJohn Birrell const char *p; 4626ff6d951SJohn Birrell int i; 4636ff6d951SJohn Birrell 4646ff6d951SJohn Birrell p = prp->pr_name; 4656ff6d951SJohn Birrell for (i = 0; (p = strchr(p, '-')) != NULL; i++) 4666ff6d951SJohn Birrell p++; 4676ff6d951SJohn Birrell 4686ff6d951SJohn Birrell mname = alloca(strlen(prp->pr_name) + 1); 4696ff6d951SJohn Birrell dt_header_fmt_macro(mname, prp->pr_name); 4706ff6d951SJohn Birrell 4716ff6d951SJohn Birrell fname = alloca(strlen(prp->pr_name) + 1 + i); 4726ff6d951SJohn Birrell dt_header_fmt_func(fname, prp->pr_name); 4736ff6d951SJohn Birrell 4746ff6d951SJohn Birrell if (fprintf(infop->dthi_out, "#define\t%s_%s(", 4756ff6d951SJohn Birrell infop->dthi_pmname, mname) < 0) 4766ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4776ff6d951SJohn Birrell 4786ff6d951SJohn Birrell for (i = 0; i < prp->pr_nargc; i++) { 4796ff6d951SJohn Birrell if (fprintf(infop->dthi_out, "arg%d", i) < 0) 4806ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4816ff6d951SJohn Birrell 4826ff6d951SJohn Birrell if (i + 1 != prp->pr_nargc && 4836ff6d951SJohn Birrell fprintf(infop->dthi_out, ", ") < 0) 4846ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4856ff6d951SJohn Birrell } 4866ff6d951SJohn Birrell 4876ff6d951SJohn Birrell if (!infop->dthi_empty) { 4886ff6d951SJohn Birrell if (fprintf(infop->dthi_out, ") \\\n\t") < 0) 4896ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4906ff6d951SJohn Birrell 4916ff6d951SJohn Birrell if (fprintf(infop->dthi_out, "__dtrace_%s___%s(", 4926ff6d951SJohn Birrell infop->dthi_pfname, fname) < 0) 4936ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4946ff6d951SJohn Birrell 4956ff6d951SJohn Birrell for (i = 0; i < prp->pr_nargc; i++) { 4966ff6d951SJohn Birrell if (fprintf(infop->dthi_out, "arg%d", i) < 0) 4976ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 4986ff6d951SJohn Birrell 4996ff6d951SJohn Birrell if (i + 1 != prp->pr_nargc && 5006ff6d951SJohn Birrell fprintf(infop->dthi_out, ", ") < 0) 5016ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 5026ff6d951SJohn Birrell } 5036ff6d951SJohn Birrell } 5046ff6d951SJohn Birrell 5056ff6d951SJohn Birrell if (fprintf(infop->dthi_out, ")\n") < 0) 5066ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 5076ff6d951SJohn Birrell 5086ff6d951SJohn Birrell if (!infop->dthi_empty) { 50956b35563SCraig Rodrigues if (fprintf(infop->dthi_out, 51056b35563SCraig Rodrigues "#ifndef\t__sparc\n" 51156b35563SCraig Rodrigues "#define\t%s_%s_ENABLED() \\\n" 51256b35563SCraig Rodrigues "\t__dtraceenabled_%s___%s()\n" 51356b35563SCraig Rodrigues "#else\n" 51456b35563SCraig Rodrigues "#define\t%s_%s_ENABLED() \\\n" 51556b35563SCraig Rodrigues "\t__dtraceenabled_%s___%s(0)\n" 51656b35563SCraig Rodrigues "#endif\n", 51756b35563SCraig Rodrigues infop->dthi_pmname, mname, 51856b35563SCraig Rodrigues infop->dthi_pfname, fname, 51956b35563SCraig Rodrigues infop->dthi_pmname, mname, 5206ff6d951SJohn Birrell infop->dthi_pfname, fname) < 0) 5216ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 52256b35563SCraig Rodrigues 5236ff6d951SJohn Birrell } else { 5246ff6d951SJohn Birrell if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() (0)\n", 5256ff6d951SJohn Birrell infop->dthi_pmname, mname) < 0) 5266ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 5276ff6d951SJohn Birrell } 5286ff6d951SJohn Birrell 5296ff6d951SJohn Birrell return (0); 5306ff6d951SJohn Birrell } 5316ff6d951SJohn Birrell 5326ff6d951SJohn Birrell static int 5336ff6d951SJohn Birrell dt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out) 5346ff6d951SJohn Birrell { 5356ff6d951SJohn Birrell dt_header_info_t info; 5366ff6d951SJohn Birrell const char *p; 5376ff6d951SJohn Birrell int i; 5386ff6d951SJohn Birrell 5396ff6d951SJohn Birrell if (pvp->pv_flags & DT_PROVIDER_IMPL) 5406ff6d951SJohn Birrell return (0); 5416ff6d951SJohn Birrell 5426ff6d951SJohn Birrell /* 5436ff6d951SJohn Birrell * Count the instances of the '-' character since we'll need to double 5446ff6d951SJohn Birrell * those up. 5456ff6d951SJohn Birrell */ 5466ff6d951SJohn Birrell p = pvp->pv_desc.dtvd_name; 5476ff6d951SJohn Birrell for (i = 0; (p = strchr(p, '-')) != NULL; i++) 5486ff6d951SJohn Birrell p++; 5496ff6d951SJohn Birrell 5506ff6d951SJohn Birrell info.dthi_dtp = dtp; 5516ff6d951SJohn Birrell info.dthi_out = out; 5526ff6d951SJohn Birrell info.dthi_empty = 0; 5536ff6d951SJohn Birrell 5546ff6d951SJohn Birrell info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1); 5556ff6d951SJohn Birrell dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name); 5566ff6d951SJohn Birrell 5576ff6d951SJohn Birrell info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i); 5586ff6d951SJohn Birrell dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name); 5596ff6d951SJohn Birrell 560*8f7264f0SRui Paulo #ifdef __FreeBSD__ 561*8f7264f0SRui Paulo if (fprintf(out, "#include <sys/sdt.h>\n\n") < 0) 562*8f7264f0SRui Paulo return (dt_set_errno(dtp, errno)); 563*8f7264f0SRui Paulo #endif 5646ff6d951SJohn Birrell if (fprintf(out, "#if _DTRACE_VERSION\n\n") < 0) 5656ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 5666ff6d951SJohn Birrell 5676ff6d951SJohn Birrell if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 5686ff6d951SJohn Birrell return (-1); /* dt_errno is set for us */ 5696ff6d951SJohn Birrell if (fprintf(out, "\n\n") < 0) 5706ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 5716ff6d951SJohn Birrell if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0) 5726ff6d951SJohn Birrell return (-1); /* dt_errno is set for us */ 5736ff6d951SJohn Birrell 5746ff6d951SJohn Birrell if (fprintf(out, "\n#else\n\n") < 0) 5756ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 5766ff6d951SJohn Birrell 5776ff6d951SJohn Birrell info.dthi_empty = 1; 5786ff6d951SJohn Birrell 5796ff6d951SJohn Birrell if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 5806ff6d951SJohn Birrell return (-1); /* dt_errno is set for us */ 5816ff6d951SJohn Birrell 5826ff6d951SJohn Birrell if (fprintf(out, "\n#endif\n\n") < 0) 5836ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 5846ff6d951SJohn Birrell 5856ff6d951SJohn Birrell return (0); 5866ff6d951SJohn Birrell } 5876ff6d951SJohn Birrell 5886ff6d951SJohn Birrell int 5896ff6d951SJohn Birrell dtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname) 5906ff6d951SJohn Birrell { 5916ff6d951SJohn Birrell dt_provider_t *pvp; 5926ff6d951SJohn Birrell char *mfname, *p; 5936ff6d951SJohn Birrell 5946ff6d951SJohn Birrell if (fname != NULL) { 5956ff6d951SJohn Birrell if ((p = strrchr(fname, '/')) != NULL) 5966ff6d951SJohn Birrell fname = p + 1; 5976ff6d951SJohn Birrell 5986ff6d951SJohn Birrell mfname = alloca(strlen(fname) + 1); 5996ff6d951SJohn Birrell dt_header_fmt_macro(mfname, fname); 6006ff6d951SJohn Birrell if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n", 6016ff6d951SJohn Birrell mfname, mfname) < 0) 6026ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 6036ff6d951SJohn Birrell } 6046ff6d951SJohn Birrell 6056ff6d951SJohn Birrell if (fprintf(out, "#include <unistd.h>\n\n") < 0) 6066ff6d951SJohn Birrell return (-1); 6076ff6d951SJohn Birrell 6086ff6d951SJohn Birrell if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0) 6096ff6d951SJohn Birrell return (-1); 6106ff6d951SJohn Birrell 6116ff6d951SJohn Birrell for (pvp = dt_list_next(&dtp->dt_provlist); 6126ff6d951SJohn Birrell pvp != NULL; pvp = dt_list_next(pvp)) { 6136ff6d951SJohn Birrell if (dt_header_provider(dtp, pvp, out) != 0) 6146ff6d951SJohn Birrell return (-1); /* dt_errno is set for us */ 6156ff6d951SJohn Birrell } 6166ff6d951SJohn Birrell 6176ff6d951SJohn Birrell if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0) 6186ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 6196ff6d951SJohn Birrell 6206ff6d951SJohn Birrell if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0) 6216ff6d951SJohn Birrell return (dt_set_errno(dtp, errno)); 6226ff6d951SJohn Birrell 6236ff6d951SJohn Birrell return (0); 6246ff6d951SJohn Birrell } 625