usdtheadergen.c   [plain text]


/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2019 Apple, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <dtrace.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>

static const char OPTSTR[] =
	"Cn:o:s:";

static const char *g_ofile = NULL;
static FILE *g_ofp = NULL;

static int g_cflags = DTRACE_C_ZDEFS;
static const int g_oflags = DTRACE_O_NODEV;

static dtrace_hdl_t *g_dtp;

static void
oprintf(const char *fmt, ...)
{
	va_list ap;
	int n;

	if (g_ofp == NULL)
		return;

	va_start(ap, fmt);
	n = vfprintf(g_ofp, fmt, ap);
	va_end(ap);

	if (n < 0) {
		if (errno != EINTR) {
			fprintf(stderr, "failed to write to %s\n",
			    g_ofile ? g_ofile : "<stdout>");
			exit(1);
		}
		clearerr(g_ofp);
	}
}

int main(int argc, char *argv[])
{
	char c;
	int err;

	g_ofp = stdout;

	if ((g_dtp = dtrace_open(DTRACE_VERSION, g_oflags, &err)) == NULL) {
		fprintf(stderr,"failed to initialize dtrace: %s\n",
			dtrace_errmsg(NULL, err));
		return (1);
	}

	dtrace_setopt(g_dtp, "argref", NULL);
	dtrace_setopt(g_dtp, "nolibs", NULL);

	while ((c = getopt(argc, argv, OPTSTR)) != -1) {
		switch (c) {
		case 'o':
			g_ofile = optarg;
			break;
		}
	}
	optind = 1;

	if (g_ofile && ((g_ofp = fopen(g_ofile, "w")) == NULL)) {
		fprintf(stderr, "failed to open header file '%s'", g_ofile);
		return (1);
	}

	while ((c = getopt(argc, argv, OPTSTR)) != -1) {
		switch (c) {
		case 'C':
			g_cflags |= DTRACE_C_CPP;
			break;
		case 'n':
			if (dtrace_program_strcompile(g_dtp, optarg, DTRACE_PROBESPEC_NAME, g_cflags, argc, argv) == NULL) {
				fprintf(stderr, "invalid probe specifier %s\n", optarg);
				(void) fprintf(stderr, "%s\n",
				    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
				return (1);
			}
			break;
		case 's':
		{
			FILE *fp;
			if ((fp = fopen(optarg, "r")) == NULL) {
				fprintf(stderr, "failed to open %s", optarg);
				return (1);
			}
			if (dtrace_program_fcompile(g_dtp, fp,
			    g_cflags, argc, argv) == NULL) {
				fprintf(stderr, "failed to compile script %s\n", optarg);
				(void) fprintf(stderr, "%s\n",
				    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
				return (1);
			}
			break;
		}
		}
	}

	oprintf("/*\n * Generated by dtrace(1M).\n */\n\n");
	if (dtrace_program_header(g_dtp, g_ofp, g_ofile) != 0 ||
		    fclose(g_ofp) == EOF) {
			fprintf(stderr, "failed to create header file %s\n", g_ofile);
			(void) fprintf(stderr, "%s\n",
			    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
			return (1);
	}
	dtrace_close(g_dtp);

	return (0);
}