1178479Sjb/* 2178479Sjb * CDDL HEADER START 3178479Sjb * 4178479Sjb * The contents of this file are subject to the terms of the 5178479Sjb * Common Development and Distribution License (the "License"). 6178479Sjb * You may not use this file except in compliance with the License. 7178479Sjb * 8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178479Sjb * or http://www.opensolaris.org/os/licensing. 10178479Sjb * See the License for the specific language governing permissions 11178479Sjb * and limitations under the License. 12178479Sjb * 13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178479Sjb * If applicable, add the following below this CDDL HEADER, with the 16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178479Sjb * 19178479Sjb * CDDL HEADER END 20178479Sjb */ 21178479Sjb 22178479Sjb/* 23210767Srpaulo * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24248708Spfg * Copyright (c) 2011 by Delphix. All rights reserved. 25178479Sjb */ 26178479Sjb 27178479Sjb#include <unistd.h> 28178479Sjb#include <strings.h> 29178479Sjb#include <stdlib.h> 30178479Sjb#include <errno.h> 31178479Sjb#include <assert.h> 32178479Sjb#include <ctype.h> 33178553Sjb#if defined(sun) 34178479Sjb#include <alloca.h> 35178553Sjb#endif 36178479Sjb 37178479Sjb#include <dt_impl.h> 38178479Sjb#include <dt_program.h> 39178479Sjb#include <dt_printf.h> 40178479Sjb#include <dt_provider.h> 41178479Sjb 42178479Sjbdtrace_prog_t * 43178479Sjbdt_program_create(dtrace_hdl_t *dtp) 44178479Sjb{ 45178479Sjb dtrace_prog_t *pgp = dt_zalloc(dtp, sizeof (dtrace_prog_t)); 46178479Sjb 47210767Srpaulo if (pgp != NULL) { 48178479Sjb dt_list_append(&dtp->dt_programs, pgp); 49210767Srpaulo } else { 50178479Sjb (void) dt_set_errno(dtp, EDT_NOMEM); 51210767Srpaulo return (NULL); 52210767Srpaulo } 53178479Sjb 54178479Sjb /* 55178479Sjb * By default, programs start with DOF version 1 so that output files 56178479Sjb * containing DOF are backward compatible. If a program requires new 57178479Sjb * DOF features, the version is increased as needed. 58178479Sjb */ 59178479Sjb pgp->dp_dofversion = DOF_VERSION_1; 60178479Sjb 61178479Sjb return (pgp); 62178479Sjb} 63178479Sjb 64178479Sjbvoid 65178479Sjbdt_program_destroy(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) 66178479Sjb{ 67178479Sjb dt_stmt_t *stp, *next; 68178479Sjb uint_t i; 69178479Sjb 70178479Sjb for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 71178479Sjb next = dt_list_next(stp); 72178479Sjb dtrace_stmt_destroy(dtp, stp->ds_desc); 73178479Sjb dt_free(dtp, stp); 74178479Sjb } 75178479Sjb 76178479Sjb for (i = 0; i < pgp->dp_xrefslen; i++) 77178479Sjb dt_free(dtp, pgp->dp_xrefs[i]); 78178479Sjb 79178479Sjb dt_free(dtp, pgp->dp_xrefs); 80178479Sjb dt_list_delete(&dtp->dt_programs, pgp); 81178479Sjb dt_free(dtp, pgp); 82178479Sjb} 83178479Sjb 84178479Sjb/*ARGSUSED*/ 85178479Sjbvoid 86178479Sjbdtrace_program_info(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 87178479Sjb dtrace_proginfo_t *pip) 88178479Sjb{ 89178479Sjb dt_stmt_t *stp; 90178479Sjb dtrace_actdesc_t *ap; 91178479Sjb dtrace_ecbdesc_t *last = NULL; 92178479Sjb 93178479Sjb if (pip == NULL) 94178479Sjb return; 95178479Sjb 96178479Sjb bzero(pip, sizeof (dtrace_proginfo_t)); 97178479Sjb 98178479Sjb if (dt_list_next(&pgp->dp_stmts) != NULL) { 99178479Sjb pip->dpi_descattr = _dtrace_maxattr; 100178479Sjb pip->dpi_stmtattr = _dtrace_maxattr; 101178479Sjb } else { 102178479Sjb pip->dpi_descattr = _dtrace_defattr; 103178479Sjb pip->dpi_stmtattr = _dtrace_defattr; 104178479Sjb } 105178479Sjb 106178479Sjb for (stp = dt_list_next(&pgp->dp_stmts); stp; stp = dt_list_next(stp)) { 107178479Sjb dtrace_ecbdesc_t *edp = stp->ds_desc->dtsd_ecbdesc; 108178479Sjb 109178479Sjb if (edp == last) 110178479Sjb continue; 111178479Sjb last = edp; 112178479Sjb 113178479Sjb pip->dpi_descattr = 114178479Sjb dt_attr_min(stp->ds_desc->dtsd_descattr, pip->dpi_descattr); 115178479Sjb 116178479Sjb pip->dpi_stmtattr = 117178479Sjb dt_attr_min(stp->ds_desc->dtsd_stmtattr, pip->dpi_stmtattr); 118178479Sjb 119178479Sjb /* 120178479Sjb * If there aren't any actions, account for the fact that 121178479Sjb * recording the epid will generate a record. 122178479Sjb */ 123178479Sjb if (edp->dted_action == NULL) 124178479Sjb pip->dpi_recgens++; 125178479Sjb 126178479Sjb for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 127178479Sjb if (ap->dtad_kind == DTRACEACT_SPECULATE) { 128178479Sjb pip->dpi_speculations++; 129178479Sjb continue; 130178479Sjb } 131178479Sjb 132178479Sjb if (DTRACEACT_ISAGG(ap->dtad_kind)) { 133178479Sjb pip->dpi_recgens -= ap->dtad_arg; 134178479Sjb pip->dpi_aggregates++; 135178479Sjb continue; 136178479Sjb } 137178479Sjb 138178479Sjb if (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind)) 139178479Sjb continue; 140178479Sjb 141178479Sjb if (ap->dtad_kind == DTRACEACT_DIFEXPR && 142178479Sjb ap->dtad_difo->dtdo_rtype.dtdt_kind == 143178479Sjb DIF_TYPE_CTF && 144178479Sjb ap->dtad_difo->dtdo_rtype.dtdt_size == 0) 145178479Sjb continue; 146178479Sjb 147178479Sjb pip->dpi_recgens++; 148178479Sjb } 149178479Sjb } 150178479Sjb} 151178479Sjb 152178479Sjbint 153178479Sjbdtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 154178479Sjb dtrace_proginfo_t *pip) 155178479Sjb{ 156178553Sjb dtrace_enable_io_t args; 157178479Sjb void *dof; 158178479Sjb int n, err; 159178479Sjb 160178479Sjb dtrace_program_info(dtp, pgp, pip); 161178479Sjb 162178479Sjb if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL) 163178479Sjb return (-1); 164178479Sjb 165178553Sjb args.dof = dof; 166178553Sjb args.n_matched = 0; 167178553Sjb n = dt_ioctl(dtp, DTRACEIOC_ENABLE, &args); 168178479Sjb dtrace_dof_destroy(dtp, dof); 169178479Sjb 170178479Sjb if (n == -1) { 171178479Sjb switch (errno) { 172178479Sjb case EINVAL: 173178479Sjb err = EDT_DIFINVAL; 174178479Sjb break; 175178479Sjb case EFAULT: 176178479Sjb err = EDT_DIFFAULT; 177178479Sjb break; 178178479Sjb case E2BIG: 179178479Sjb err = EDT_DIFSIZE; 180178479Sjb break; 181210767Srpaulo case EBUSY: 182210767Srpaulo err = EDT_ENABLING_ERR; 183210767Srpaulo break; 184178479Sjb default: 185178479Sjb err = errno; 186178479Sjb } 187178479Sjb 188178479Sjb return (dt_set_errno(dtp, err)); 189178479Sjb } 190178479Sjb 191178479Sjb if (pip != NULL) 192178553Sjb pip->dpi_matches += args.n_matched; 193178479Sjb 194178479Sjb return (0); 195178479Sjb} 196178479Sjb 197178479Sjbstatic void 198178479Sjbdt_ecbdesc_hold(dtrace_ecbdesc_t *edp) 199178479Sjb{ 200178479Sjb edp->dted_refcnt++; 201178479Sjb} 202178479Sjb 203178479Sjbvoid 204178479Sjbdt_ecbdesc_release(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 205178479Sjb{ 206178479Sjb if (--edp->dted_refcnt > 0) 207178479Sjb return; 208178479Sjb 209178479Sjb dt_difo_free(dtp, edp->dted_pred.dtpdd_difo); 210178479Sjb assert(edp->dted_action == NULL); 211178479Sjb dt_free(dtp, edp); 212178479Sjb} 213178479Sjb 214178479Sjbdtrace_ecbdesc_t * 215178479Sjbdt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp) 216178479Sjb{ 217178479Sjb dtrace_ecbdesc_t *edp; 218178479Sjb 219178479Sjb if ((edp = dt_zalloc(dtp, sizeof (dtrace_ecbdesc_t))) == NULL) { 220178479Sjb (void) dt_set_errno(dtp, EDT_NOMEM); 221178479Sjb return (NULL); 222178479Sjb } 223178479Sjb 224178479Sjb edp->dted_probe = *pdp; 225178479Sjb dt_ecbdesc_hold(edp); 226178479Sjb return (edp); 227178479Sjb} 228178479Sjb 229178479Sjbdtrace_stmtdesc_t * 230178479Sjbdtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp) 231178479Sjb{ 232178479Sjb dtrace_stmtdesc_t *sdp; 233178479Sjb 234178479Sjb if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL) 235178479Sjb return (NULL); 236178479Sjb 237178479Sjb dt_ecbdesc_hold(edp); 238178479Sjb sdp->dtsd_ecbdesc = edp; 239178479Sjb sdp->dtsd_descattr = _dtrace_defattr; 240178479Sjb sdp->dtsd_stmtattr = _dtrace_defattr; 241178479Sjb 242178479Sjb return (sdp); 243178479Sjb} 244178479Sjb 245178479Sjbdtrace_actdesc_t * 246178479Sjbdtrace_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 247178479Sjb{ 248178479Sjb dtrace_actdesc_t *new; 249178479Sjb dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 250178479Sjb 251178479Sjb if ((new = dt_alloc(dtp, sizeof (dtrace_actdesc_t))) == NULL) 252178479Sjb return (NULL); 253178479Sjb 254178479Sjb if (sdp->dtsd_action_last != NULL) { 255178479Sjb assert(sdp->dtsd_action != NULL); 256178479Sjb assert(sdp->dtsd_action_last->dtad_next == NULL); 257178479Sjb sdp->dtsd_action_last->dtad_next = new; 258178479Sjb } else { 259178479Sjb dtrace_actdesc_t *ap = edp->dted_action; 260178479Sjb 261178479Sjb assert(sdp->dtsd_action == NULL); 262178479Sjb sdp->dtsd_action = new; 263178479Sjb 264178479Sjb while (ap != NULL && ap->dtad_next != NULL) 265178479Sjb ap = ap->dtad_next; 266178479Sjb 267178479Sjb if (ap == NULL) 268178479Sjb edp->dted_action = new; 269178479Sjb else 270178479Sjb ap->dtad_next = new; 271178479Sjb } 272178479Sjb 273178479Sjb sdp->dtsd_action_last = new; 274178479Sjb bzero(new, sizeof (dtrace_actdesc_t)); 275178479Sjb new->dtad_uarg = (uintptr_t)sdp; 276178479Sjb 277178479Sjb return (new); 278178479Sjb} 279178479Sjb 280178479Sjbint 281178479Sjbdtrace_stmt_add(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp) 282178479Sjb{ 283178479Sjb dt_stmt_t *stp = dt_alloc(dtp, sizeof (dt_stmt_t)); 284178479Sjb 285178479Sjb if (stp == NULL) 286178479Sjb return (-1); /* errno is set for us */ 287178479Sjb 288178479Sjb dt_list_append(&pgp->dp_stmts, stp); 289178479Sjb stp->ds_desc = sdp; 290178479Sjb 291178479Sjb return (0); 292178479Sjb} 293178479Sjb 294178479Sjbint 295178479Sjbdtrace_stmt_iter(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, 296178479Sjb dtrace_stmt_f *func, void *data) 297178479Sjb{ 298178479Sjb dt_stmt_t *stp, *next; 299178479Sjb int status = 0; 300178479Sjb 301178479Sjb for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL; stp = next) { 302178479Sjb next = dt_list_next(stp); 303178479Sjb if ((status = func(dtp, pgp, stp->ds_desc, data)) != 0) 304178479Sjb break; 305178479Sjb } 306178479Sjb 307178479Sjb return (status); 308178479Sjb} 309178479Sjb 310178479Sjbvoid 311178479Sjbdtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp) 312178479Sjb{ 313178479Sjb dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc; 314178479Sjb 315178479Sjb /* 316178479Sjb * We need to remove any actions that we have on this ECB, and 317178479Sjb * remove our hold on the ECB itself. 318178479Sjb */ 319178479Sjb if (sdp->dtsd_action != NULL) { 320178479Sjb dtrace_actdesc_t *last = sdp->dtsd_action_last; 321178479Sjb dtrace_actdesc_t *ap, *next; 322178479Sjb 323178479Sjb assert(last != NULL); 324178479Sjb 325178479Sjb for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) { 326178479Sjb if (ap == sdp->dtsd_action) 327178479Sjb break; 328178479Sjb 329178479Sjb if (ap->dtad_next == sdp->dtsd_action) 330178479Sjb break; 331178479Sjb } 332178479Sjb 333178479Sjb assert(ap != NULL); 334178479Sjb 335178479Sjb if (ap == edp->dted_action) 336178479Sjb edp->dted_action = last->dtad_next; 337178479Sjb else 338178479Sjb ap->dtad_next = last->dtad_next; 339178479Sjb 340178479Sjb /* 341178479Sjb * We have now removed our action list from its ECB; we can 342178479Sjb * safely destroy the list. 343178479Sjb */ 344178479Sjb last->dtad_next = NULL; 345178479Sjb 346178479Sjb for (ap = sdp->dtsd_action; ap != NULL; ap = next) { 347178479Sjb assert(ap->dtad_uarg == (uintptr_t)sdp); 348178479Sjb dt_difo_free(dtp, ap->dtad_difo); 349178479Sjb next = ap->dtad_next; 350178479Sjb dt_free(dtp, ap); 351178479Sjb } 352178479Sjb } 353178479Sjb 354178479Sjb if (sdp->dtsd_fmtdata != NULL) 355178479Sjb dt_printf_destroy(sdp->dtsd_fmtdata); 356248708Spfg dt_free(dtp, sdp->dtsd_strdata); 357178479Sjb 358178479Sjb dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc); 359178479Sjb dt_free(dtp, sdp); 360178479Sjb} 361178479Sjb 362178479Sjbtypedef struct dt_header_info { 363178479Sjb dtrace_hdl_t *dthi_dtp; /* consumer handle */ 364178479Sjb FILE *dthi_out; /* output file */ 365178479Sjb char *dthi_pmname; /* provider macro name */ 366178479Sjb char *dthi_pfname; /* provider function name */ 367178479Sjb int dthi_empty; /* should we generate empty macros */ 368178479Sjb} dt_header_info_t; 369178479Sjb 370178479Sjbstatic void 371178479Sjbdt_header_fmt_macro(char *buf, const char *str) 372178479Sjb{ 373178479Sjb for (;;) { 374178479Sjb if (islower(*str)) { 375178479Sjb *buf++ = *str++ + 'A' - 'a'; 376178479Sjb } else if (*str == '-') { 377178479Sjb *buf++ = '_'; 378178479Sjb str++; 379178479Sjb } else if (*str == '.') { 380178479Sjb *buf++ = '_'; 381178479Sjb str++; 382178479Sjb } else if ((*buf++ = *str++) == '\0') { 383178479Sjb break; 384178479Sjb } 385178479Sjb } 386178479Sjb} 387178479Sjb 388178479Sjbstatic void 389178479Sjbdt_header_fmt_func(char *buf, const char *str) 390178479Sjb{ 391178479Sjb for (;;) { 392178479Sjb if (*str == '-') { 393178479Sjb *buf++ = '_'; 394178479Sjb *buf++ = '_'; 395178479Sjb str++; 396178479Sjb } else if ((*buf++ = *str++) == '\0') { 397178479Sjb break; 398178479Sjb } 399178479Sjb } 400178479Sjb} 401178479Sjb 402178479Sjb/*ARGSUSED*/ 403178479Sjbstatic int 404178479Sjbdt_header_decl(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 405178479Sjb{ 406178479Sjb dt_header_info_t *infop = data; 407178479Sjb dtrace_hdl_t *dtp = infop->dthi_dtp; 408178479Sjb dt_probe_t *prp = idp->di_data; 409178479Sjb dt_node_t *dnp; 410178479Sjb char buf[DT_TYPE_NAMELEN]; 411178479Sjb char *fname; 412178479Sjb const char *p; 413178479Sjb int i; 414178479Sjb 415178479Sjb p = prp->pr_name; 416178479Sjb for (i = 0; (p = strchr(p, '-')) != NULL; i++) 417178479Sjb p++; 418178479Sjb 419178479Sjb fname = alloca(strlen(prp->pr_name) + 1 + i); 420178479Sjb dt_header_fmt_func(fname, prp->pr_name); 421178479Sjb 422178479Sjb if (fprintf(infop->dthi_out, "extern void __dtrace_%s___%s(", 423178479Sjb infop->dthi_pfname, fname) < 0) 424178479Sjb return (dt_set_errno(dtp, errno)); 425178479Sjb 426178479Sjb for (dnp = prp->pr_nargs, i = 0; dnp != NULL; dnp = dnp->dn_list, i++) { 427178479Sjb if (fprintf(infop->dthi_out, "%s", 428178479Sjb ctf_type_name(dnp->dn_ctfp, dnp->dn_type, 429178479Sjb buf, sizeof (buf))) < 0) 430178479Sjb return (dt_set_errno(dtp, errno)); 431178479Sjb 432178479Sjb if (i + 1 != prp->pr_nargc && 433178479Sjb fprintf(infop->dthi_out, ", ") < 0) 434178479Sjb return (dt_set_errno(dtp, errno)); 435178479Sjb } 436178479Sjb 437178479Sjb if (i == 0 && fprintf(infop->dthi_out, "void") < 0) 438178479Sjb return (dt_set_errno(dtp, errno)); 439178479Sjb 440178479Sjb if (fprintf(infop->dthi_out, ");\n") < 0) 441178479Sjb return (dt_set_errno(dtp, errno)); 442178479Sjb 443184696Srodrigc if (fprintf(infop->dthi_out, 444184696Srodrigc "#ifndef\t__sparc\n" 445184696Srodrigc "extern int __dtraceenabled_%s___%s(void);\n" 446184696Srodrigc "#else\n" 447184696Srodrigc "extern int __dtraceenabled_%s___%s(long);\n" 448184696Srodrigc "#endif\n", 449184696Srodrigc infop->dthi_pfname, fname, infop->dthi_pfname, fname) < 0) 450178479Sjb return (dt_set_errno(dtp, errno)); 451178479Sjb 452178479Sjb return (0); 453178479Sjb} 454178479Sjb 455178479Sjb/*ARGSUSED*/ 456178479Sjbstatic int 457178479Sjbdt_header_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 458178479Sjb{ 459178479Sjb dt_header_info_t *infop = data; 460178479Sjb dtrace_hdl_t *dtp = infop->dthi_dtp; 461178479Sjb dt_probe_t *prp = idp->di_data; 462178479Sjb char *mname, *fname; 463178479Sjb const char *p; 464178479Sjb int i; 465178479Sjb 466178479Sjb p = prp->pr_name; 467178479Sjb for (i = 0; (p = strchr(p, '-')) != NULL; i++) 468178479Sjb p++; 469178479Sjb 470178479Sjb mname = alloca(strlen(prp->pr_name) + 1); 471178479Sjb dt_header_fmt_macro(mname, prp->pr_name); 472178479Sjb 473178479Sjb fname = alloca(strlen(prp->pr_name) + 1 + i); 474178479Sjb dt_header_fmt_func(fname, prp->pr_name); 475178479Sjb 476178479Sjb if (fprintf(infop->dthi_out, "#define\t%s_%s(", 477178479Sjb infop->dthi_pmname, mname) < 0) 478178479Sjb return (dt_set_errno(dtp, errno)); 479178479Sjb 480178479Sjb for (i = 0; i < prp->pr_nargc; i++) { 481178479Sjb if (fprintf(infop->dthi_out, "arg%d", i) < 0) 482178479Sjb return (dt_set_errno(dtp, errno)); 483178479Sjb 484178479Sjb if (i + 1 != prp->pr_nargc && 485178479Sjb fprintf(infop->dthi_out, ", ") < 0) 486178479Sjb return (dt_set_errno(dtp, errno)); 487178479Sjb } 488178479Sjb 489178479Sjb if (!infop->dthi_empty) { 490178479Sjb if (fprintf(infop->dthi_out, ") \\\n\t") < 0) 491178479Sjb return (dt_set_errno(dtp, errno)); 492178479Sjb 493178479Sjb if (fprintf(infop->dthi_out, "__dtrace_%s___%s(", 494178479Sjb infop->dthi_pfname, fname) < 0) 495178479Sjb return (dt_set_errno(dtp, errno)); 496178479Sjb 497178479Sjb for (i = 0; i < prp->pr_nargc; i++) { 498178479Sjb if (fprintf(infop->dthi_out, "arg%d", i) < 0) 499178479Sjb return (dt_set_errno(dtp, errno)); 500178479Sjb 501178479Sjb if (i + 1 != prp->pr_nargc && 502178479Sjb fprintf(infop->dthi_out, ", ") < 0) 503178479Sjb return (dt_set_errno(dtp, errno)); 504178479Sjb } 505178479Sjb } 506178479Sjb 507178479Sjb if (fprintf(infop->dthi_out, ")\n") < 0) 508178479Sjb return (dt_set_errno(dtp, errno)); 509178479Sjb 510178479Sjb if (!infop->dthi_empty) { 511184696Srodrigc if (fprintf(infop->dthi_out, 512184696Srodrigc "#ifndef\t__sparc\n" 513184696Srodrigc "#define\t%s_%s_ENABLED() \\\n" 514184696Srodrigc "\t__dtraceenabled_%s___%s()\n" 515184696Srodrigc "#else\n" 516184696Srodrigc "#define\t%s_%s_ENABLED() \\\n" 517184696Srodrigc "\t__dtraceenabled_%s___%s(0)\n" 518184696Srodrigc "#endif\n", 519184696Srodrigc infop->dthi_pmname, mname, 520184696Srodrigc infop->dthi_pfname, fname, 521184696Srodrigc infop->dthi_pmname, mname, 522184696Srodrigc infop->dthi_pfname, fname) < 0) 523178479Sjb return (dt_set_errno(dtp, errno)); 524178479Sjb 525178479Sjb } else { 526178479Sjb if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() (0)\n", 527178479Sjb infop->dthi_pmname, mname) < 0) 528178479Sjb return (dt_set_errno(dtp, errno)); 529178479Sjb } 530178479Sjb 531178479Sjb return (0); 532178479Sjb} 533178479Sjb 534178479Sjbstatic int 535178479Sjbdt_header_provider(dtrace_hdl_t *dtp, dt_provider_t *pvp, FILE *out) 536178479Sjb{ 537178479Sjb dt_header_info_t info; 538178479Sjb const char *p; 539178479Sjb int i; 540178479Sjb 541178479Sjb if (pvp->pv_flags & DT_PROVIDER_IMPL) 542178479Sjb return (0); 543178479Sjb 544178479Sjb /* 545178479Sjb * Count the instances of the '-' character since we'll need to double 546178479Sjb * those up. 547178479Sjb */ 548178479Sjb p = pvp->pv_desc.dtvd_name; 549178479Sjb for (i = 0; (p = strchr(p, '-')) != NULL; i++) 550178479Sjb p++; 551178479Sjb 552178479Sjb info.dthi_dtp = dtp; 553178479Sjb info.dthi_out = out; 554178479Sjb info.dthi_empty = 0; 555178479Sjb 556178479Sjb info.dthi_pmname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1); 557178479Sjb dt_header_fmt_macro(info.dthi_pmname, pvp->pv_desc.dtvd_name); 558178479Sjb 559178479Sjb info.dthi_pfname = alloca(strlen(pvp->pv_desc.dtvd_name) + 1 + i); 560178479Sjb dt_header_fmt_func(info.dthi_pfname, pvp->pv_desc.dtvd_name); 561178479Sjb 562212092Srpaulo#ifdef __FreeBSD__ 563212092Srpaulo if (fprintf(out, "#include <sys/sdt.h>\n\n") < 0) 564212092Srpaulo return (dt_set_errno(dtp, errno)); 565212092Srpaulo#endif 566178479Sjb if (fprintf(out, "#if _DTRACE_VERSION\n\n") < 0) 567178479Sjb return (dt_set_errno(dtp, errno)); 568178479Sjb 569178479Sjb if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 570178479Sjb return (-1); /* dt_errno is set for us */ 571178479Sjb if (fprintf(out, "\n\n") < 0) 572178479Sjb return (dt_set_errno(dtp, errno)); 573178479Sjb if (dt_idhash_iter(pvp->pv_probes, dt_header_decl, &info) != 0) 574178479Sjb return (-1); /* dt_errno is set for us */ 575178479Sjb 576178479Sjb if (fprintf(out, "\n#else\n\n") < 0) 577178479Sjb return (dt_set_errno(dtp, errno)); 578178479Sjb 579178479Sjb info.dthi_empty = 1; 580178479Sjb 581178479Sjb if (dt_idhash_iter(pvp->pv_probes, dt_header_probe, &info) != 0) 582178479Sjb return (-1); /* dt_errno is set for us */ 583178479Sjb 584178479Sjb if (fprintf(out, "\n#endif\n\n") < 0) 585178479Sjb return (dt_set_errno(dtp, errno)); 586178479Sjb 587178479Sjb return (0); 588178479Sjb} 589178479Sjb 590178479Sjbint 591178479Sjbdtrace_program_header(dtrace_hdl_t *dtp, FILE *out, const char *fname) 592178479Sjb{ 593178479Sjb dt_provider_t *pvp; 594178479Sjb char *mfname, *p; 595178479Sjb 596178479Sjb if (fname != NULL) { 597178479Sjb if ((p = strrchr(fname, '/')) != NULL) 598178479Sjb fname = p + 1; 599178479Sjb 600178479Sjb mfname = alloca(strlen(fname) + 1); 601178479Sjb dt_header_fmt_macro(mfname, fname); 602178479Sjb if (fprintf(out, "#ifndef\t_%s\n#define\t_%s\n\n", 603178479Sjb mfname, mfname) < 0) 604178479Sjb return (dt_set_errno(dtp, errno)); 605178479Sjb } 606178479Sjb 607178479Sjb if (fprintf(out, "#include <unistd.h>\n\n") < 0) 608178479Sjb return (-1); 609178479Sjb 610178479Sjb if (fprintf(out, "#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n") < 0) 611178479Sjb return (-1); 612178479Sjb 613178479Sjb for (pvp = dt_list_next(&dtp->dt_provlist); 614178479Sjb pvp != NULL; pvp = dt_list_next(pvp)) { 615178479Sjb if (dt_header_provider(dtp, pvp, out) != 0) 616178479Sjb return (-1); /* dt_errno is set for us */ 617178479Sjb } 618178479Sjb 619178479Sjb if (fprintf(out, "\n#ifdef\t__cplusplus\n}\n#endif\n") < 0) 620178479Sjb return (dt_set_errno(dtp, errno)); 621178479Sjb 622178479Sjb if (fname != NULL && fprintf(out, "\n#endif\t/* _%s */\n", mfname) < 0) 623178479Sjb return (dt_set_errno(dtp, errno)); 624178479Sjb 625178479Sjb return (0); 626178479Sjb} 627