⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtrace.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident	"@(#)dtrace.c	1.15	04/12/18 SMI"#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <dtrace.h>#include <stdlib.h>#include <stdarg.h>#include <stdio.h>#include <strings.h>#include <unistd.h>#include <limits.h>#include <fcntl.h>#include <errno.h>#include <signal.h>#include <alloca.h>#include <libgen.h>#include <libproc.h>typedef struct dtrace_cmd {	void (*dc_func)(struct dtrace_cmd *);	/* function to compile arg */	dtrace_probespec_t dc_spec;		/* probe specifier context */	char *dc_arg;				/* argument from main argv */	const char *dc_name;			/* name for error messages */	const char *dc_desc;			/* desc for error messages */	dtrace_prog_t *dc_prog;			/* program compiled from arg */} dtrace_cmd_t;#define	DMODE_VERS	0	/* display version information and exit (-V) */#define	DMODE_EXEC	1	/* compile program for enabling (-a/e/E) */#define	DMODE_ANON	2	/* compile program for anonymous tracing (-A) */#define	DMODE_LINK	3	/* compile program for linking with ELF (-G) */#define	DMODE_LIST	4	/* compile program and list probes (-l) */#define	E_SUCCESS	0#define	E_ERROR		1#define	E_USAGE		2static const char DTRACE_OPTSTR[] =	"3:6:aAb:c:CD:ef:FGHi:I:lL:m:n:o:p:P:qs:SU:vVwx:X:Z";static int g_fd;static char **g_argv;static int g_argc;static char **g_objv;static int g_objc;static dtrace_cmd_t *g_cmdv;static int g_cmdc;static struct ps_prochandle **g_psv;static int g_psc;static int g_pslive;static char *g_pname;static int g_quiet;static int g_flowindent;static int g_intr;static int g_impatient;static int g_newline;static int g_total;static int g_cflags;static int g_oflags;static int g_verbose;static int g_exec = 1;static int g_mode = DMODE_EXEC;static int g_status = E_SUCCESS;static int g_grabanon = 0;static const char *g_ofile = NULL;static FILE *g_ofp = stdout;static dtrace_hdl_t *g_dtp;static char *g_etcfile = "/etc/system";static const char *g_etcbegin = "* vvvv Added by DTrace";static const char *g_etcend = "* ^^^^ Added by DTrace";static const char *g_etc[] =  {"*","* The following forceload directives were added by dtrace(1M) to allow for","* tracing during boot.  If these directives are removed, the system will","* continue to function, but tracing will not occur during boot as desired.","* To remove these directives (and this block comment) automatically, run","* \"dtrace -A\" without additional arguments.  See the \"Anonymous Tracing\"","* chapter of the Solaris Dynamic Tracing Guide for details.","*",NULL };static intusage(FILE *fp){	static const char predact[] = "[[ predicate ] action ]";	(void) fprintf(fp, "Usage: %s [-32|-64] [-aACeFGHlqSvVwZ] "	    "[-b bufsz] [-c cmd] [-D name[=def]]\n\t[-I path] [-L path] "	    "[-o output] [-p pid] [-s script] [-U name]\n\t"	    "[-x opt[=val]] [-X a|c|s|t]\n\n"	    "\t[-P provider %s]\n"	    "\t[-m [ provider: ] module %s]\n"	    "\t[-f [[ provider: ] module: ] func %s]\n"	    "\t[-n [[[ provider: ] module: ] func: ] name %s]\n"	    "\t[-i probe-id %s] [ args ... ]\n\n", g_pname,	    predact, predact, predact, predact, predact);	(void) fprintf(fp, "\tpredicate -> '/' D-expression '/'\n");	(void) fprintf(fp, "\t   action -> '{' D-statements '}'\n");	(void) fprintf(fp, "\n"	    "\t-32 generate 32-bit D programs and ELF files\n"	    "\t-64 generate 64-bit D programs and ELF files\n\n"	    "\t-a  claim anonymous tracing state\n"	    "\t-A  generate driver.conf(4) directives for anonymous tracing\n"	    "\t-b  set trace buffer size\n"	    "\t-c  run specified command and exit upon its completion\n"	    "\t-C  run cpp(1) preprocessor on script files\n"	    "\t-D  define symbol when invoking preprocessor\n"	    "\t-e  exit after compiling request but prior to enabling probes\n"	    "\t-f  enable or list probes matching the specified function name\n"	    "\t-F  coalesce trace output by function\n"	    "\t-G  generate an ELF file containing embedded dtrace program\n"	    "\t-H  print included files when invoking preprocessor\n"	    "\t-i  enable or list probes matching the specified probe id\n"	    "\t-I  add include directory to preprocessor search path\n"	    "\t-l  list probes matching specified criteria\n"	    "\t-L  add library directory to library search path\n"	    "\t-m  enable or list probes matching the specified module name\n"	    "\t-n  enable or list probes matching the specified probe name\n"	    "\t-o  set output file\n"	    "\t-p  grab specified process-ID and cache its symbol tables\n"	    "\t-P  enable or list probes matching the specified provider name\n"	    "\t-q  set quiet mode (only output explicitly traced data)\n"	    "\t-s  enable or list probes according to the specified D script\n"	    "\t-S  print D compiler intermediate code\n"	    "\t-U  undefine symbol when invoking preprocessor\n"	    "\t-v  set verbose mode (report program stability attributes)\n"	    "\t-V  report DTrace API version\n"	    "\t-w  permit destructive actions\n"	    "\t-x  enable or modify compiler and tracing options\n"	    "\t-X  specify ISO C conformance settings for preprocessor\n"	    "\t-Z  permit probe descriptions that match zero probes\n");	return (E_USAGE);}static voidverror(const char *fmt, va_list ap){	int error = errno;	(void) fprintf(stderr, "%s: ", g_pname);	(void) vfprintf(stderr, fmt, ap);	if (fmt[strlen(fmt) - 1] != '\n')		(void) fprintf(stderr, ": %s\n", strerror(error));}/*PRINTFLIKE1*/static voidfatal(const char *fmt, ...){	va_list ap;	va_start(ap, fmt);	verror(fmt, ap);	va_end(ap);	exit(E_ERROR);}/*PRINTFLIKE1*/static voiddfatal(const char *fmt, ...){	va_list ap;	va_start(ap, fmt);	(void) fprintf(stderr, "%s: ", g_pname);	if (fmt != NULL)		(void) vfprintf(stderr, fmt, ap);	va_end(ap);	if (fmt != NULL && fmt[strlen(fmt) - 1] != '\n') {		(void) fprintf(stderr, ": %s\n",		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));	} else if (fmt == NULL) {		(void) fprintf(stderr, "%s\n",		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));	}	exit(E_ERROR);}/*PRINTFLIKE1*/static voiderror(const char *fmt, ...){	va_list ap;	va_start(ap, fmt);	verror(fmt, ap);	va_end(ap);}/*PRINTFLIKE1*/static voidnotice(const char *fmt, ...){	va_list ap;	if (g_quiet)		return; /* -q or quiet pragma suppresses notice()s */	va_start(ap, fmt);	verror(fmt, ap);	va_end(ap);}/*PRINTFLIKE1*/static voidoprintf(const char *fmt, ...){	va_list ap;	int n;	va_start(ap, fmt);	n = vfprintf(g_ofp, fmt, ap);	va_end(ap);	if (n < 0) {		if (errno != EINTR) {			fatal("failed to write to %s",			    g_ofile ? g_ofile : "<stdout>");		}		clearerr(g_ofp);	}}static char **make_argv(char *s){	const char *ws = "\f\n\r\t\v ";	char **argv = malloc(sizeof (char *) * (strlen(s) / 2 + 1));	int argc = 0;	char *p = s;	if (argv == NULL)		return (NULL);	for (p = strtok(s, ws); p != NULL; p = strtok(NULL, ws))		argv[argc++] = p;	if (argc == 0)		argv[argc++] = s;	argv[argc] = NULL;	return (argv);}static voidlist_probes(void){	dtrace_probedesc_t probe;	bzero(&probe, sizeof (probe));	while (ioctl(g_fd, DTRACEIOC_PROBES, &probe) != -1) {		oprintf("%5d %10s %17s %33s %s\n", probe.dtpd_id,		    probe.dtpd_provider, probe.dtpd_mod,		    probe.dtpd_func, probe.dtpd_name);		probe.dtpd_id++;	}}static voiddof_prune(const char *fname){	struct stat sbuf;	size_t sz, i, j, mark, len;	char *buf;	int msg = 0, fd;	if ((fd = open(fname, O_RDONLY)) == -1) {		/*		 * This is okay only if the file doesn't exist at all.		 */		if (errno != ENOENT)			fatal("failed to open %s", fname);		return;	}	if (fstat(fd, &sbuf) == -1)		fatal("failed to fstat %s", fname);	if ((buf = malloc((sz = sbuf.st_size) + 1)) == NULL)		fatal("failed to allocate memory for %s", fname);	if (read(fd, buf, sz) != sz)		fatal("failed to read %s", fname);	buf[sz] = '\0';	(void) close(fd);	if ((fd = open(fname, O_WRONLY | O_TRUNC)) == -1)		fatal("failed to open %s for writing", fname);	len = strlen("dof-data-");	for (mark = 0, i = 0; i < sz; i++) {		if (strncmp(&buf[i], "dof-data-", len) != 0)			continue;		/*		 * This is only a match if it's in the 0th column.		 */		if (i != 0 && buf[i - 1] != '\n')			continue;		if (msg++ == 0) {			error("cleaned up old anonymous "			    "enabling in %s\n", fname);		}		/*		 * We have a match.  First write out our data up until now.		 */		if (i != mark) {			if (write(fd, &buf[mark], i - mark) != i - mark)				fatal("failed to write to %s", fname);		}		/*		 * Now scan forward until we scan past a newline.		 */		for (j = i; j < sz && buf[j] != '\n'; j++)			continue;		/*		 * Reset our mark.		 */		if ((mark = j + 1) >= sz)			break;		i = j;	}	if (mark < sz) {		if (write(fd, &buf[mark], sz - mark) != sz - mark)			fatal("failed to write to %s", fname);	}	(void) close(fd);	free(buf);}static voidetcsystem_prune(void){	struct stat sbuf;	size_t sz;	char *buf, *start, *end;	int fd;	char *fname = g_etcfile, *tmpname;	if ((fd = open(fname, O_RDONLY)) == -1)		fatal("failed to open %s", fname);	if (fstat(fd, &sbuf) == -1)		fatal("failed to fstat %s", fname);	if ((buf = malloc((sz = sbuf.st_size) + 1)) == NULL)		fatal("failed to allocate memory for %s", fname);	if (read(fd, buf, sz) != sz)		fatal("failed to read %s", fname);	buf[sz] = '\0';	(void) close(fd);	if ((start = strstr(buf, g_etcbegin)) == NULL)		goto out;	if (strlen(buf) != sz) {		fatal("embedded nul byte in %s; manual repair of %s "		    "required\n", fname, fname);	}	if (strstr(start + 1, g_etcbegin) != NULL) {		fatal("multiple start sentinels in %s; manual repair of %s "		    "required\n", fname, fname);	}	if ((end = strstr(buf, g_etcend)) == NULL) {		fatal("missing end sentinel in %s; manual repair of %s "		    "required\n", fname, fname);	}	if (start > end) {		fatal("end sentinel preceeds start sentinel in %s; manual "		    "repair of %s required\n", fname, fname);	}	end += strlen(g_etcend) + 1;	bcopy(end, start, strlen(end) + 1);	tmpname = alloca(sz = strlen(fname) + 80);	(void) snprintf(tmpname, sz, "%s.dtrace.%d", fname, getpid());	if ((fd = open(tmpname,	    O_WRONLY | O_CREAT | O_EXCL, sbuf.st_mode)) == -1)		fatal("failed to create %s", tmpname);	if (write(fd, buf, strlen(buf)) < strlen(buf)) {		(void) unlink(tmpname);		fatal("failed to write to %s", tmpname);	}	(void) close(fd);	if (chown(tmpname, sbuf.st_uid, sbuf.st_gid) != 0) {		(void) unlink(tmpname);		fatal("failed to chown(2) %s to uid %d, gid %d", tmpname,		    (int)sbuf.st_uid, (int)sbuf.st_gid);	}	if (rename(tmpname, fname) == -1)		fatal("rename of %s to %s failed", tmpname, fname);	error("cleaned up forceload directives in %s\n", fname);out:	free(buf);}static voidetcsystem_add(void){	const char *mods[20];	int nmods, line;	if ((g_ofp = fopen(g_ofile = g_etcfile, "a")) == NULL)		fatal("failed to open output file '%s'", g_ofile);	oprintf("%s\n", g_etcbegin);	for (line = 0; g_etc[line] != NULL; line++)		oprintf("%s\n", g_etc[line]);	nmods = dtrace_provider_modules(g_dtp, mods,	    sizeof (mods) / sizeof (char *) - 1);	if (nmods >= sizeof (mods) / sizeof (char *))		fatal("unexpectedly large number of modules!");	mods[nmods++] = "dtrace";	for (line = 0; line < nmods; line++)		oprintf("forceload: drv/%s\n", mods[line]);	oprintf("%s\n", g_etcend);	if (fclose(g_ofp) == EOF)		fatal("failed to close output file '%s'", g_ofile);	error("added forceload directives to %s\n", g_ofile);}/* * Execute the specified program by enabling the corresponding instrumentation. * If -e has been specified, we get the program info but do not enable it.  If * -v has been specified, we print a stability report for the program. */static void

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -