xref: /freebsd/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c (revision 02e9120893770924227138ba49df1edb3896112a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Copyright (c) 2012 by Delphix. All rights reserved.
28  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
29  */
30 
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/wait.h>
34 
35 #include <dtrace.h>
36 #include <stdlib.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <strings.h>
41 #include <unistd.h>
42 #include <limits.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <signal.h>
46 #ifdef illumos
47 #include <alloca.h>
48 #endif
49 #include <libgen.h>
50 #ifdef illumos
51 #include <libproc.h>
52 #endif
53 #ifdef __FreeBSD__
54 #include <locale.h>
55 #include <spawn.h>
56 #endif
57 
58 typedef struct dtrace_cmd {
59 	void (*dc_func)(struct dtrace_cmd *);	/* function to compile arg */
60 	dtrace_probespec_t dc_spec;		/* probe specifier context */
61 	char *dc_arg;				/* argument from main argv */
62 	const char *dc_name;			/* name for error messages */
63 	const char *dc_desc;			/* desc for error messages */
64 	dtrace_prog_t *dc_prog;			/* program compiled from arg */
65 	char dc_ofile[PATH_MAX];		/* derived output file name */
66 } dtrace_cmd_t;
67 
68 #define	DMODE_VERS	0	/* display version information and exit (-V) */
69 #define	DMODE_EXEC	1	/* compile program for enabling (-a/e/E) */
70 #define	DMODE_ANON	2	/* compile program for anonymous tracing (-A) */
71 #define	DMODE_LINK	3	/* compile program for linking with ELF (-G) */
72 #define	DMODE_LIST	4	/* compile program and list probes (-l) */
73 #define	DMODE_HEADER	5	/* compile program for headergen (-h) */
74 
75 #define	E_SUCCESS	0
76 #define	E_ERROR		1
77 #define	E_USAGE		2
78 
79 static const char DTRACE_OPTSTR[] =
80 	"3:6:aAb:Bc:CdD:ef:FGhHi:I:lL:m:n:o:p:P:qs:SU:vVwx:X:Z";
81 
82 static char **g_argv;
83 static int g_argc;
84 static char **g_objv;
85 static int g_objc;
86 static dtrace_cmd_t *g_cmdv;
87 static int g_cmdc;
88 static struct ps_prochandle **g_psv;
89 static int g_psc;
90 static int g_pslive;
91 static char *g_pname;
92 static int g_quiet;
93 static int g_flowindent;
94 static int g_intr;
95 static int g_impatient;
96 static int g_newline;
97 #ifdef __FreeBSD__
98 static int g_siginfo;
99 #endif
100 static int g_total;
101 static int g_cflags;
102 static int g_oflags;
103 static int g_verbose;
104 static int g_exec = 1;
105 static int g_mode = DMODE_EXEC;
106 static int g_status = E_SUCCESS;
107 static int g_grabanon = 0;
108 static const char *g_ofile = NULL;
109 static FILE *g_ofp;
110 static dtrace_hdl_t *g_dtp;
111 #ifdef illumos
112 static char *g_etcfile = "/etc/system";
113 static const char *g_etcbegin = "* vvvv Added by DTrace";
114 static const char *g_etcend = "* ^^^^ Added by DTrace";
115 
116 static const char *g_etc[] =  {
117 "*",
118 "* The following forceload directives were added by dtrace(1M) to allow for",
119 "* tracing during boot.  If these directives are removed, the system will",
120 "* continue to function, but tracing will not occur during boot as desired.",
121 "* To remove these directives (and this block comment) automatically, run",
122 "* \"dtrace -A\" without additional arguments.  See the \"Anonymous Tracing\"",
123 "* chapter of the Solaris Dynamic Tracing Guide for details.",
124 "*",
125 NULL };
126 #endif
127 
128 static int
129 usage(FILE *fp)
130 {
131 	static const char predact[] = "[[ predicate ] action ]";
132 
133 	(void) fprintf(fp, "Usage: %s [-32|-64] [-aACdeFGhHlqSvVwZ] "
134 	    "[-b bufsz] [-c cmd] [-D name[=def]]\n\t[-I path] [-L path] "
135 	    "[-o output] [-p pid] [-s script] [-U name]\n\t"
136 	    "[-x opt[=val]] [-X a|c|s|t]\n\n"
137 	    "\t[-P provider %s]\n"
138 	    "\t[-m [ provider: ] module %s]\n"
139 	    "\t[-f [[ provider: ] module: ] func %s]\n"
140 	    "\t[-n [[[ provider: ] module: ] func: ] name %s]\n"
141 	    "\t[-i probe-id %s] [ args ... ]\n\n", g_pname,
142 	    predact, predact, predact, predact, predact);
143 
144 	(void) fprintf(fp, "\tpredicate -> '/' D-expression '/'\n");
145 	(void) fprintf(fp, "\t   action -> '{' D-statements '}'\n");
146 
147 	(void) fprintf(fp, "\n"
148 	    "\t-32 generate 32-bit D programs and ELF files\n"
149 	    "\t-64 generate 64-bit D programs and ELF files\n\n"
150 	    "\t-a  claim anonymous tracing state\n"
151 	    "\t-A  generate driver.conf(4) directives for anonymous tracing\n"
152 	    "\t-b  set trace buffer size\n"
153 	    "\t-c  run specified command and exit upon its completion\n"
154 	    "\t-C  run cpp(1) preprocessor on script files\n"
155 	    "\t-d  dump script after syntactic transformations\n"
156 	    "\t-D  define symbol when invoking preprocessor\n"
157 	    "\t-e  exit after compiling request but prior to enabling probes\n"
158 	    "\t-f  enable or list probes matching the specified function name\n"
159 	    "\t-F  coalesce trace output by function\n"
160 	    "\t-G  generate an ELF file containing embedded dtrace program\n"
161 	    "\t-h  generate a header file with definitions for static probes\n"
162 	    "\t-H  print included files when invoking preprocessor\n"
163 	    "\t-i  enable or list probes matching the specified probe id\n"
164 	    "\t-I  add include directory to preprocessor search path\n"
165 	    "\t-l  list probes matching specified criteria\n"
166 	    "\t-L  add library directory to library search path\n"
167 	    "\t-m  enable or list probes matching the specified module name\n"
168 	    "\t-n  enable or list probes matching the specified probe name\n"
169 	    "\t-o  set output file\n"
170 	    "\t-p  grab specified process-ID and cache its symbol tables\n"
171 	    "\t-P  enable or list probes matching the specified provider name\n"
172 	    "\t-q  set quiet mode (only output explicitly traced data)\n"
173 	    "\t-s  enable or list probes according to the specified D script\n"
174 	    "\t-S  print D compiler intermediate code\n"
175 	    "\t-U  undefine symbol when invoking preprocessor\n"
176 	    "\t-v  set verbose mode (report stability attributes, arguments)\n"
177 	    "\t-V  report DTrace API version\n"
178 	    "\t-w  permit destructive actions\n"
179 	    "\t-x  enable or modify compiler and tracing options\n"
180 	    "\t-X  specify ISO C conformance settings for preprocessor\n"
181 	    "\t-Z  permit probe descriptions that match zero probes\n");
182 
183 	return (E_USAGE);
184 }
185 
186 static void
187 verror(const char *fmt, va_list ap)
188 {
189 	int error = errno;
190 
191 	(void) fprintf(stderr, "%s: ", g_pname);
192 	(void) vfprintf(stderr, fmt, ap);
193 
194 	if (fmt[strlen(fmt) - 1] != '\n')
195 		(void) fprintf(stderr, ": %s\n", strerror(error));
196 }
197 
198 /*PRINTFLIKE1*/
199 static void
200 fatal(const char *fmt, ...)
201 {
202 	va_list ap;
203 
204 	va_start(ap, fmt);
205 	verror(fmt, ap);
206 	va_end(ap);
207 
208 	/*
209 	 * Close the DTrace handle to ensure that any controlled processes are
210 	 * correctly restored and continued.
211 	 */
212 	if (g_dtp)
213 		dtrace_close(g_dtp);
214 
215 	exit(E_ERROR);
216 }
217 
218 /*PRINTFLIKE1*/
219 static void
220 dfatal(const char *fmt, ...)
221 {
222 #if !defined(illumos) && defined(NEED_ERRLOC)
223 	char *p_errfile = NULL;
224 	int errline = 0;
225 #endif
226 	va_list ap;
227 
228 	va_start(ap, fmt);
229 
230 	(void) fprintf(stderr, "%s: ", g_pname);
231 	if (fmt != NULL)
232 		(void) vfprintf(stderr, fmt, ap);
233 
234 	va_end(ap);
235 
236 	if (fmt != NULL && fmt[strlen(fmt) - 1] != '\n') {
237 		(void) fprintf(stderr, ": %s\n",
238 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
239 	} else if (fmt == NULL) {
240 		(void) fprintf(stderr, "%s\n",
241 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
242 	}
243 #if !defined(illumos) && defined(NEED_ERRLOC)
244 	dt_get_errloc(g_dtp, &p_errfile, &errline);
245 	if (p_errfile != NULL)
246 		printf("File '%s', line %d\n", p_errfile, errline);
247 #endif
248 
249 	/*
250 	 * Close the DTrace handle to ensure that any controlled processes are
251 	 * correctly restored and continued.
252 	 */
253 	dtrace_close(g_dtp);
254 
255 	exit(E_ERROR);
256 }
257 
258 /*PRINTFLIKE1*/
259 static void
260 error(const char *fmt, ...)
261 {
262 	va_list ap;
263 
264 	va_start(ap, fmt);
265 	verror(fmt, ap);
266 	va_end(ap);
267 }
268 
269 /*PRINTFLIKE1*/
270 static void
271 notice(const char *fmt, ...)
272 {
273 	va_list ap;
274 
275 	if (g_quiet)
276 		return; /* -q or quiet pragma suppresses notice()s */
277 
278 	va_start(ap, fmt);
279 	verror(fmt, ap);
280 	va_end(ap);
281 }
282 
283 /*PRINTFLIKE1*/
284 static void
285 oprintf(const char *fmt, ...)
286 {
287 	va_list ap;
288 	int n;
289 
290 	if (g_ofp == NULL)
291 		return;
292 
293 	va_start(ap, fmt);
294 	n = vfprintf(g_ofp, fmt, ap);
295 	va_end(ap);
296 
297 	if (n < 0) {
298 		if (errno != EINTR) {
299 			fatal("failed to write to %s",
300 			    g_ofile ? g_ofile : "<stdout>");
301 		}
302 		clearerr(g_ofp);
303 	}
304 }
305 
306 static char **
307 make_argv(char *s)
308 {
309 	const char *ws = "\f\n\r\t\v ";
310 	char **argv = malloc(sizeof (char *) * (strlen(s) / 2 + 1));
311 	int argc = 0;
312 	char *p = s;
313 
314 	if (argv == NULL)
315 		return (NULL);
316 
317 	for (p = strtok(s, ws); p != NULL; p = strtok(NULL, ws))
318 		argv[argc++] = p;
319 
320 	if (argc == 0)
321 		argv[argc++] = s;
322 
323 	argv[argc] = NULL;
324 	return (argv);
325 }
326 
327 static void
328 dof_prune(const char *fname)
329 {
330 	struct stat sbuf;
331 	size_t sz, i, j, mark, len;
332 	char *buf;
333 	int msg = 0, fd;
334 
335 	if ((fd = open(fname, O_RDONLY)) == -1) {
336 		/*
337 		 * This is okay only if the file doesn't exist at all.
338 		 */
339 		if (errno != ENOENT)
340 			fatal("failed to open %s", fname);
341 		return;
342 	}
343 
344 	if (fstat(fd, &sbuf) == -1)
345 		fatal("failed to fstat %s", fname);
346 
347 	if ((buf = malloc((sz = sbuf.st_size) + 1)) == NULL)
348 		fatal("failed to allocate memory for %s", fname);
349 
350 	if (read(fd, buf, sz) != sz)
351 		fatal("failed to read %s", fname);
352 
353 	buf[sz] = '\0';
354 	(void) close(fd);
355 
356 	if ((fd = open(fname, O_WRONLY | O_TRUNC)) == -1)
357 		fatal("failed to open %s for writing", fname);
358 
359 	len = strlen("dof-data-");
360 
361 	for (mark = 0, i = 0; i < sz; i++) {
362 		if (strncmp(&buf[i], "dof-data-", len) != 0)
363 			continue;
364 
365 		/*
366 		 * This is only a match if it's in the 0th column.
367 		 */
368 		if (i != 0 && buf[i - 1] != '\n')
369 			continue;
370 
371 		if (msg++ == 0) {
372 			error("cleaned up old anonymous "
373 			    "enabling in %s\n", fname);
374 		}
375 
376 		/*
377 		 * We have a match.  First write out our data up until now.
378 		 */
379 		if (i != mark) {
380 			if (write(fd, &buf[mark], i - mark) != i - mark)
381 				fatal("failed to write to %s", fname);
382 		}
383 
384 		/*
385 		 * Now scan forward until we scan past a newline.
386 		 */
387 		for (j = i; j < sz && buf[j] != '\n'; j++)
388 			continue;
389 
390 		/*
391 		 * Reset our mark.
392 		 */
393 		if ((mark = j + 1) >= sz)
394 			break;
395 
396 		i = j;
397 	}
398 
399 	if (mark < sz) {
400 		if (write(fd, &buf[mark], sz - mark) != sz - mark)
401 			fatal("failed to write to %s", fname);
402 	}
403 
404 	(void) close(fd);
405 	free(buf);
406 }
407 
408 #ifdef __FreeBSD__
409 /*
410  * Use nextboot(8) to tell the loader to load DTrace kernel modules during
411  * the next boot of the system. The nextboot(8) configuration is removed during
412  * boot, so it will not persist indefinitely.
413  */
414 static void
415 bootdof_add(void)
416 {
417 	char * const nbargv[] = {
418 		"nextboot", "-a",
419 		"-e", "dtraceall_load=\"YES\"",
420 		"-e", "dtrace_dof_load=\"YES\"",
421 		"-e", "dtrace_dof_name=\"/boot/dtrace.dof\"",
422 		"-e", "dtrace_dof_type=\"dtrace_dof\"",
423 		NULL,
424 	};
425 	pid_t child;
426 	int err, status;
427 
428 	err = posix_spawnp(&child, "nextboot", NULL, NULL, nbargv,
429 	    NULL);
430 	if (err != 0) {
431 		error("failed to execute nextboot: %s", strerror(err));
432 		exit(E_ERROR);
433 	}
434 
435 	if (waitpid(child, &status, 0) != child)
436 		fatal("waiting for nextboot");
437 	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
438 		error("nextboot returned with status %d", status);
439 		exit(E_ERROR);
440 	}
441 }
442 #else
443 static void
444 etcsystem_prune(void)
445 {
446 	struct stat sbuf;
447 	size_t sz;
448 	char *buf, *start, *end;
449 	int fd;
450 	char *fname = g_etcfile, *tmpname;
451 
452 	if ((fd = open(fname, O_RDONLY)) == -1)
453 		fatal("failed to open %s", fname);
454 
455 	if (fstat(fd, &sbuf) == -1)
456 		fatal("failed to fstat %s", fname);
457 
458 	if ((buf = malloc((sz = sbuf.st_size) + 1)) == NULL)
459 		fatal("failed to allocate memory for %s", fname);
460 
461 	if (read(fd, buf, sz) != sz)
462 		fatal("failed to read %s", fname);
463 
464 	buf[sz] = '\0';
465 	(void) close(fd);
466 
467 	if ((start = strstr(buf, g_etcbegin)) == NULL)
468 		goto out;
469 
470 	if (strlen(buf) != sz) {
471 		fatal("embedded nul byte in %s; manual repair of %s "
472 		    "required\n", fname, fname);
473 	}
474 
475 	if (strstr(start + 1, g_etcbegin) != NULL) {
476 		fatal("multiple start sentinels in %s; manual repair of %s "
477 		    "required\n", fname, fname);
478 	}
479 
480 	if ((end = strstr(buf, g_etcend)) == NULL) {
481 		fatal("missing end sentinel in %s; manual repair of %s "
482 		    "required\n", fname, fname);
483 	}
484 
485 	if (start > end) {
486 		fatal("end sentinel preceeds start sentinel in %s; manual "
487 		    "repair of %s required\n", fname, fname);
488 	}
489 
490 	end += strlen(g_etcend) + 1;
491 	bcopy(end, start, strlen(end) + 1);
492 
493 	tmpname = alloca(sz = strlen(fname) + 80);
494 	(void) snprintf(tmpname, sz, "%s.dtrace.%d", fname, getpid());
495 
496 	if ((fd = open(tmpname,
497 	    O_WRONLY | O_CREAT | O_EXCL, sbuf.st_mode)) == -1)
498 		fatal("failed to create %s", tmpname);
499 
500 	if (write(fd, buf, strlen(buf)) < strlen(buf)) {
501 		(void) unlink(tmpname);
502 		fatal("failed to write to %s", tmpname);
503 	}
504 
505 	(void) close(fd);
506 
507 	if (chown(tmpname, sbuf.st_uid, sbuf.st_gid) != 0) {
508 		(void) unlink(tmpname);
509 		fatal("failed to chown(2) %s to uid %d, gid %d", tmpname,
510 		    (int)sbuf.st_uid, (int)sbuf.st_gid);
511 	}
512 
513 	if (rename(tmpname, fname) == -1)
514 		fatal("rename of %s to %s failed", tmpname, fname);
515 
516 	error("cleaned up forceload directives in %s\n", fname);
517 out:
518 	free(buf);
519 }
520 
521 static void
522 etcsystem_add(void)
523 {
524 	const char *mods[20];
525 	int nmods, line;
526 
527 	if ((g_ofp = fopen(g_ofile = g_etcfile, "a")) == NULL)
528 		fatal("failed to open output file '%s'", g_ofile);
529 
530 	oprintf("%s\n", g_etcbegin);
531 
532 	for (line = 0; g_etc[line] != NULL; line++)
533 		oprintf("%s\n", g_etc[line]);
534 
535 	nmods = dtrace_provider_modules(g_dtp, mods,
536 	    sizeof (mods) / sizeof (char *) - 1);
537 
538 	if (nmods >= sizeof (mods) / sizeof (char *))
539 		fatal("unexpectedly large number of modules!");
540 
541 	mods[nmods++] = "dtrace";
542 
543 	for (line = 0; line < nmods; line++)
544 		oprintf("forceload: drv/%s\n", mods[line]);
545 
546 	oprintf("%s\n", g_etcend);
547 
548 	if (fclose(g_ofp) == EOF)
549 		fatal("failed to close output file '%s'", g_ofile);
550 
551 	error("added forceload directives to %s\n", g_ofile);
552 }
553 #endif /* !__FreeBSD__ */
554 
555 static void
556 print_probe_info(const dtrace_probeinfo_t *p)
557 {
558 	char buf[BUFSIZ];
559 	char *user;
560 	int i;
561 
562 	oprintf("\n\tProbe Description Attributes\n");
563 
564 	oprintf("\t\tIdentifier Names: %s\n",
565 	    dtrace_stability_name(p->dtp_attr.dtat_name));
566 	oprintf("\t\tData Semantics:   %s\n",
567 	    dtrace_stability_name(p->dtp_attr.dtat_data));
568 	oprintf("\t\tDependency Class: %s\n",
569 	    dtrace_class_name(p->dtp_attr.dtat_class));
570 
571 	oprintf("\n\tArgument Attributes\n");
572 
573 	oprintf("\t\tIdentifier Names: %s\n",
574 	    dtrace_stability_name(p->dtp_arga.dtat_name));
575 	oprintf("\t\tData Semantics:   %s\n",
576 	    dtrace_stability_name(p->dtp_arga.dtat_data));
577 	oprintf("\t\tDependency Class: %s\n",
578 	    dtrace_class_name(p->dtp_arga.dtat_class));
579 
580 	oprintf("\n\tArgument Types\n");
581 
582 	for (i = 0; i < p->dtp_argc; i++) {
583 		if (p->dtp_argv[i].dtt_flags & DTT_FL_USER)
584 			user = "userland ";
585 		else
586 			user = "";
587 		if (ctf_type_name(p->dtp_argv[i].dtt_ctfp,
588 		    p->dtp_argv[i].dtt_type, buf, sizeof (buf)) == NULL)
589 			(void) strlcpy(buf, "(unknown)", sizeof (buf));
590 		oprintf("\t\targs[%d]: %s%s\n", i, user, buf);
591 	}
592 
593 	if (p->dtp_argc == 0)
594 		oprintf("\t\tNone\n");
595 
596 	oprintf("\n");
597 }
598 
599 /*ARGSUSED*/
600 static int
601 info_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
602     dtrace_stmtdesc_t *stp, dtrace_ecbdesc_t **last)
603 {
604 	dtrace_ecbdesc_t *edp = stp->dtsd_ecbdesc;
605 	dtrace_probedesc_t *pdp = &edp->dted_probe;
606 	dtrace_probeinfo_t p;
607 
608 	if (edp == *last)
609 		return (0);
610 
611 	oprintf("\n%s:%s:%s:%s\n",
612 	    pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name);
613 
614 	if (dtrace_probe_info(dtp, pdp, &p) == 0)
615 		print_probe_info(&p);
616 
617 	*last = edp;
618 	return (0);
619 }
620 
621 /*
622  * Execute the specified program by enabling the corresponding instrumentation.
623  * If -e has been specified, we get the program info but do not enable it.  If
624  * -v has been specified, we print a stability report for the program.
625  */
626 static void
627 exec_prog(const dtrace_cmd_t *dcp)
628 {
629 	dtrace_ecbdesc_t *last = NULL;
630 	dtrace_proginfo_t dpi;
631 
632 	if (!g_exec) {
633 		dtrace_program_info(g_dtp, dcp->dc_prog, &dpi);
634 	} else if (dtrace_program_exec(g_dtp, dcp->dc_prog, &dpi) == -1) {
635 		dfatal("failed to enable '%s'", dcp->dc_name);
636 	} else {
637 		notice("%s '%s' matched %u probe%s\n",
638 		    dcp->dc_desc, dcp->dc_name,
639 		    dpi.dpi_matches, dpi.dpi_matches == 1 ? "" : "s");
640 	}
641 
642 	if (g_verbose) {
643 		oprintf("\nStability attributes for %s %s:\n",
644 		    dcp->dc_desc, dcp->dc_name);
645 
646 		oprintf("\n\tMinimum Probe Description Attributes\n");
647 		oprintf("\t\tIdentifier Names: %s\n",
648 		    dtrace_stability_name(dpi.dpi_descattr.dtat_name));
649 		oprintf("\t\tData Semantics:   %s\n",
650 		    dtrace_stability_name(dpi.dpi_descattr.dtat_data));
651 		oprintf("\t\tDependency Class: %s\n",
652 		    dtrace_class_name(dpi.dpi_descattr.dtat_class));
653 
654 		oprintf("\n\tMinimum Statement Attributes\n");
655 
656 		oprintf("\t\tIdentifier Names: %s\n",
657 		    dtrace_stability_name(dpi.dpi_stmtattr.dtat_name));
658 		oprintf("\t\tData Semantics:   %s\n",
659 		    dtrace_stability_name(dpi.dpi_stmtattr.dtat_data));
660 		oprintf("\t\tDependency Class: %s\n",
661 		    dtrace_class_name(dpi.dpi_stmtattr.dtat_class));
662 
663 		if (!g_exec) {
664 			(void) dtrace_stmt_iter(g_dtp, dcp->dc_prog,
665 			    (dtrace_stmt_f *)info_stmt, &last);
666 		} else
667 			oprintf("\n");
668 	}
669 
670 	g_total += dpi.dpi_matches;
671 }
672 
673 /*
674  * Print out the specified DOF buffer as a set of ASCII bytes appropriate for
675  * storing in a driver.conf(4) file associated with the dtrace driver.
676  */
677 static void
678 anon_prog(const dtrace_cmd_t *dcp, dof_hdr_t *dof, int n)
679 {
680 	const uchar_t *p, *q;
681 
682 	if (dof == NULL)
683 		dfatal("failed to create DOF image for '%s'", dcp->dc_name);
684 
685 	p = (uchar_t *)dof;
686 	q = p + dof->dofh_filesz;
687 
688 #ifdef __FreeBSD__
689 	/*
690 	 * On FreeBSD, the DOF file is read directly during boot - just write
691 	 * two hex characters per byte.
692 	 */
693 	oprintf("dof-data-%d=", n);
694 
695 	while (p < q)
696 		oprintf("%02x", *p++);
697 
698 	oprintf("\n");
699 #else
700 	oprintf("dof-data-%d=0x%x", n, *p++);
701 
702 	while (p < q)
703 		oprintf(",0x%x", *p++);
704 
705 	oprintf(";\n");
706 #endif
707 
708 	dtrace_dof_destroy(g_dtp, dof);
709 }
710 
711 /*
712  * Link the specified D program in DOF form into an ELF file for use in either
713  * helpers, userland provider definitions, or both.  If -o was specified, that
714  * path is used as the output file name.  If -o wasn't specified and the input
715  * program is from a script whose name is %.d, use basename(%.o) as the output
716  * file name.  Otherwise we use "d.out" as the default output file name.
717  */
718 static void
719 link_prog(dtrace_cmd_t *dcp)
720 {
721 	char *p;
722 
723 	if (g_cmdc == 1 && g_ofile != NULL) {
724 		(void) strlcpy(dcp->dc_ofile, g_ofile, sizeof (dcp->dc_ofile));
725 	} else if ((p = strrchr(dcp->dc_arg, '.')) != NULL &&
726 	    strcmp(p, ".d") == 0) {
727 		p[0] = '\0'; /* strip .d suffix */
728 		(void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile),
729 		    "%s.o", basename(dcp->dc_arg));
730 	} else if (g_cmdc > 1) {
731 		(void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile),
732 		    "d.out.%td", dcp - g_cmdv);
733 	} else {
734 		(void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile),
735 		    "d.out");
736 	}
737 
738 	if (dtrace_program_link(g_dtp, dcp->dc_prog, DTRACE_D_PROBES,
739 	    dcp->dc_ofile, g_objc, g_objv) != 0)
740 		dfatal("failed to link %s %s", dcp->dc_desc, dcp->dc_name);
741 }
742 
743 /*ARGSUSED*/
744 static int
745 list_probe(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *arg)
746 {
747 	dtrace_probeinfo_t p;
748 
749 	oprintf("%5d %10s %17s %33s %s\n", pdp->dtpd_id,
750 	    pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name);
751 
752 	if (g_verbose && dtrace_probe_info(dtp, pdp, &p) == 0)
753 		print_probe_info(&p);
754 
755 	if (g_intr != 0)
756 		return (1);
757 
758 	return (0);
759 }
760 
761 /*ARGSUSED*/
762 static int
763 list_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp,
764     dtrace_stmtdesc_t *stp, dtrace_ecbdesc_t **last)
765 {
766 	dtrace_ecbdesc_t *edp = stp->dtsd_ecbdesc;
767 
768 	if (edp == *last)
769 		return (0);
770 
771 	if (dtrace_probe_iter(g_dtp, &edp->dted_probe, list_probe, NULL) != 0) {
772 		error("failed to match %s:%s:%s:%s: %s\n",
773 		    edp->dted_probe.dtpd_provider, edp->dted_probe.dtpd_mod,
774 		    edp->dted_probe.dtpd_func, edp->dted_probe.dtpd_name,
775 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
776 	}
777 
778 	*last = edp;
779 	return (0);
780 }
781 
782 /*
783  * List the probes corresponding to the specified program by iterating over
784  * each statement and then matching probes to the statement probe descriptions.
785  */
786 static void
787 list_prog(const dtrace_cmd_t *dcp)
788 {
789 	dtrace_ecbdesc_t *last = NULL;
790 
791 	(void) dtrace_stmt_iter(g_dtp, dcp->dc_prog,
792 	    (dtrace_stmt_f *)list_stmt, &last);
793 }
794 
795 static void
796 compile_file(dtrace_cmd_t *dcp)
797 {
798 	char *arg0;
799 	FILE *fp;
800 
801 	if ((fp = fopen(dcp->dc_arg, "r")) == NULL)
802 		fatal("failed to open %s", dcp->dc_arg);
803 
804 	arg0 = g_argv[0];
805 	g_argv[0] = dcp->dc_arg;
806 
807 	if ((dcp->dc_prog = dtrace_program_fcompile(g_dtp, fp,
808 	    g_cflags, g_argc, g_argv)) == NULL)
809 		dfatal("failed to compile script %s", dcp->dc_arg);
810 
811 	g_argv[0] = arg0;
812 	(void) fclose(fp);
813 
814 	dcp->dc_desc = "script";
815 	dcp->dc_name = dcp->dc_arg;
816 }
817 
818 static void
819 compile_str(dtrace_cmd_t *dcp)
820 {
821 	char *p;
822 
823 	if ((dcp->dc_prog = dtrace_program_strcompile(g_dtp, dcp->dc_arg,
824 	    dcp->dc_spec, g_cflags | DTRACE_C_PSPEC, g_argc, g_argv)) == NULL)
825 		dfatal("invalid probe specifier %s", dcp->dc_arg);
826 
827 	if ((p = strpbrk(dcp->dc_arg, "{/;")) != NULL)
828 		*p = '\0'; /* crop name for reporting */
829 
830 	dcp->dc_desc = "description";
831 	dcp->dc_name = dcp->dc_arg;
832 }
833 
834 /*ARGSUSED*/
835 static void
836 prochandler(struct ps_prochandle *P, const char *msg, void *arg)
837 {
838 #ifdef illumos
839 	const psinfo_t *prp = Ppsinfo(P);
840 	int pid = Pstatus(P)->pr_pid;
841 	char name[SIG2STR_MAX];
842 #else
843 	int wstatus = proc_getwstat(P);
844 	int pid = proc_getpid(P);
845 #endif
846 
847 	if (msg != NULL) {
848 		notice("pid %d: %s\n", pid, msg);
849 		return;
850 	}
851 
852 #ifdef illumos
853 	switch (Pstate(P)) {
854 #else
855 	switch (proc_state(P)) {
856 #endif
857 	case PS_UNDEAD:
858 #ifdef illumos
859 		/*
860 		 * Ideally we would like to always report pr_wstat here, but it
861 		 * isn't possible given current /proc semantics.  If we grabbed
862 		 * the process, Ppsinfo() will either fail or return a zeroed
863 		 * psinfo_t depending on how far the parent is in reaping it.
864 		 * When /proc provides a stable pr_wstat in the status file,
865 		 * this code can be improved by examining this new pr_wstat.
866 		 */
867 		if (prp != NULL && WIFSIGNALED(prp->pr_wstat)) {
868 			notice("pid %d terminated by %s\n", pid,
869 			    proc_signame(WTERMSIG(prp->pr_wstat),
870 			    name, sizeof (name)));
871 #else
872 		if (WIFSIGNALED(wstatus)) {
873 			notice("pid %d terminated by %d\n", pid,
874 			    WTERMSIG(wstatus));
875 #endif
876 #ifdef illumos
877 		} else if (prp != NULL && WEXITSTATUS(prp->pr_wstat) != 0) {
878 			notice("pid %d exited with status %d\n",
879 			    pid, WEXITSTATUS(prp->pr_wstat));
880 #else
881 		} else if (WEXITSTATUS(wstatus) != 0) {
882 			notice("pid %d exited with status %d\n",
883 			    pid, WEXITSTATUS(wstatus));
884 #endif
885 		} else {
886 			notice("pid %d has exited\n", pid);
887 		}
888 		g_pslive--;
889 		break;
890 
891 	case PS_LOST:
892 		notice("pid %d exec'd a set-id or unobservable program\n", pid);
893 		g_pslive--;
894 		break;
895 	}
896 }
897 
898 /*ARGSUSED*/
899 static int
900 errhandler(const dtrace_errdata_t *data, void *arg)
901 {
902 	error(data->dteda_msg);
903 	return (DTRACE_HANDLE_OK);
904 }
905 
906 /*ARGSUSED*/
907 static int
908 drophandler(const dtrace_dropdata_t *data, void *arg)
909 {
910 	error(data->dtdda_msg);
911 	return (DTRACE_HANDLE_OK);
912 }
913 
914 /*ARGSUSED*/
915 static int
916 setopthandler(const dtrace_setoptdata_t *data, void *arg)
917 {
918 	if (strcmp(data->dtsda_option, "quiet") == 0)
919 		g_quiet = data->dtsda_newval != DTRACEOPT_UNSET;
920 
921 	if (strcmp(data->dtsda_option, "flowindent") == 0)
922 		g_flowindent = data->dtsda_newval != DTRACEOPT_UNSET;
923 
924 	return (DTRACE_HANDLE_OK);
925 }
926 
927 #define	BUFDUMPHDR(hdr) \
928 	(void) printf("%s: %s%s\n", g_pname, hdr, strlen(hdr) > 0 ? ":" : "");
929 
930 #define	BUFDUMPSTR(ptr, field) \
931 	(void) printf("%s: %20s => ", g_pname, #field);	\
932 	if ((ptr)->field != NULL) {			\
933 		const char *c = (ptr)->field;		\
934 		(void) printf("\"");			\
935 		do {					\
936 			if (*c == '\n') {		\
937 				(void) printf("\\n");	\
938 				continue;		\
939 			}				\
940 							\
941 			(void) printf("%c", *c);	\
942 		} while (*c++ != '\0');			\
943 		(void) printf("\"\n");			\
944 	} else {					\
945 		(void) printf("<NULL>\n");		\
946 	}
947 
948 #define	BUFDUMPASSTR(ptr, field, str) \
949 	(void) printf("%s: %20s => %s\n", g_pname, #field, str);
950 
951 #define	BUFDUMP(ptr, field) \
952 	(void) printf("%s: %20s => %lld\n", g_pname, #field, \
953 	    (long long)(ptr)->field);
954 
955 #define	BUFDUMPPTR(ptr, field) \
956 	(void) printf("%s: %20s => %s\n", g_pname, #field, \
957 	    (ptr)->field != NULL ? "<non-NULL>" : "<NULL>");
958 
959 /*ARGSUSED*/
960 static int
961 bufhandler(const dtrace_bufdata_t *bufdata, void *arg)
962 {
963 	const dtrace_aggdata_t *agg = bufdata->dtbda_aggdata;
964 	const dtrace_recdesc_t *rec = bufdata->dtbda_recdesc;
965 	const dtrace_probedesc_t *pd;
966 	uint32_t flags = bufdata->dtbda_flags;
967 	char buf[512], *c = buf, *end = c + sizeof (buf);
968 	int i, printed;
969 
970 	struct {
971 		const char *name;
972 		uint32_t value;
973 	} flagnames[] = {
974 	    { "AGGVAL",		DTRACE_BUFDATA_AGGVAL },
975 	    { "AGGKEY",		DTRACE_BUFDATA_AGGKEY },
976 	    { "AGGFORMAT",	DTRACE_BUFDATA_AGGFORMAT },
977 	    { "AGGLAST",	DTRACE_BUFDATA_AGGLAST },
978 	    { "???",		UINT32_MAX },
979 	    { NULL }
980 	};
981 
982 	if (bufdata->dtbda_probe != NULL) {
983 		pd = bufdata->dtbda_probe->dtpda_pdesc;
984 	} else if (agg != NULL) {
985 		pd = agg->dtada_pdesc;
986 	} else {
987 		pd = NULL;
988 	}
989 
990 	BUFDUMPHDR(">>> Called buffer handler");
991 	BUFDUMPHDR("");
992 
993 	BUFDUMPHDR("  dtrace_bufdata");
994 	BUFDUMPSTR(bufdata, dtbda_buffered);
995 	BUFDUMPPTR(bufdata, dtbda_probe);
996 	BUFDUMPPTR(bufdata, dtbda_aggdata);
997 	BUFDUMPPTR(bufdata, dtbda_recdesc);
998 
999 	(void) snprintf(c, end - c, "0x%x ", bufdata->dtbda_flags);
1000 	c += strlen(c);
1001 
1002 	for (i = 0, printed = 0; flagnames[i].name != NULL; i++) {
1003 		if (!(flags & flagnames[i].value))
1004 			continue;
1005 
1006 		(void) snprintf(c, end - c,
1007 		    "%s%s", printed++ ? " | " : "(", flagnames[i].name);
1008 		c += strlen(c);
1009 		flags &= ~flagnames[i].value;
1010 	}
1011 
1012 	if (printed)
1013 		(void) snprintf(c, end - c, ")");
1014 
1015 	BUFDUMPASSTR(bufdata, dtbda_flags, buf);
1016 	BUFDUMPHDR("");
1017 
1018 	if (pd != NULL) {
1019 		BUFDUMPHDR("  dtrace_probedesc");
1020 		BUFDUMPSTR(pd, dtpd_provider);
1021 		BUFDUMPSTR(pd, dtpd_mod);
1022 		BUFDUMPSTR(pd, dtpd_func);
1023 		BUFDUMPSTR(pd, dtpd_name);
1024 		BUFDUMPHDR("");
1025 	}
1026 
1027 	if (rec != NULL) {
1028 		BUFDUMPHDR("  dtrace_recdesc");
1029 		BUFDUMP(rec, dtrd_action);
1030 		BUFDUMP(rec, dtrd_size);
1031 
1032 		if (agg != NULL) {
1033 			uint8_t *data;
1034 			int lim = rec->dtrd_size;
1035 
1036 			(void) sprintf(buf, "%d (data: ", rec->dtrd_offset);
1037 			c = buf + strlen(buf);
1038 
1039 			if (lim > sizeof (uint64_t))
1040 				lim = sizeof (uint64_t);
1041 
1042 			data = (uint8_t *)agg->dtada_data + rec->dtrd_offset;
1043 
1044 			for (i = 0; i < lim; i++) {
1045 				(void) snprintf(c, end - c, "%s%02x",
1046 				    i == 0 ? "" : " ", *data++);
1047 				c += strlen(c);
1048 			}
1049 
1050 			(void) snprintf(c, end - c,
1051 			    "%s)", lim < rec->dtrd_size ? " ..." : "");
1052 			BUFDUMPASSTR(rec, dtrd_offset, buf);
1053 		} else {
1054 			BUFDUMP(rec, dtrd_offset);
1055 		}
1056 
1057 		BUFDUMPHDR("");
1058 	}
1059 
1060 	if (agg != NULL) {
1061 		dtrace_aggdesc_t *desc = agg->dtada_desc;
1062 
1063 		BUFDUMPHDR("  dtrace_aggdesc");
1064 		BUFDUMPSTR(desc, dtagd_name);
1065 		BUFDUMP(desc, dtagd_varid);
1066 		BUFDUMP(desc, dtagd_id);
1067 		BUFDUMP(desc, dtagd_nrecs);
1068 		BUFDUMPHDR("");
1069 	}
1070 
1071 	return (DTRACE_HANDLE_OK);
1072 }
1073 
1074 /*ARGSUSED*/
1075 static int
1076 chewrec(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg)
1077 {
1078 	dtrace_actkind_t act;
1079 	uintptr_t addr;
1080 
1081 	if (rec == NULL) {
1082 		/*
1083 		 * We have processed the final record; output the newline if
1084 		 * we're not in quiet mode.
1085 		 */
1086 		if (!g_quiet)
1087 			oprintf("\n");
1088 
1089 		return (DTRACE_CONSUME_NEXT);
1090 	}
1091 
1092 	act = rec->dtrd_action;
1093 	addr = (uintptr_t)data->dtpda_data;
1094 
1095 	if (act == DTRACEACT_EXIT) {
1096 		g_status = *((uint32_t *)addr);
1097 		return (DTRACE_CONSUME_NEXT);
1098 	}
1099 
1100 	return (DTRACE_CONSUME_THIS);
1101 }
1102 
1103 /*ARGSUSED*/
1104 static int
1105 chew(const dtrace_probedata_t *data, void *arg)
1106 {
1107 	dtrace_probedesc_t *pd = data->dtpda_pdesc;
1108 	processorid_t cpu = data->dtpda_cpu;
1109 	static int heading;
1110 
1111 	if (g_impatient) {
1112 		g_newline = 0;
1113 		return (DTRACE_CONSUME_ABORT);
1114 	}
1115 
1116 	if (heading == 0) {
1117 		if (!g_flowindent) {
1118 			if (!g_quiet) {
1119 				oprintf("%3s %6s %32s\n",
1120 				    "CPU", "ID", "FUNCTION:NAME");
1121 			}
1122 		} else {
1123 			oprintf("%3s %-41s\n", "CPU", "FUNCTION");
1124 		}
1125 		heading = 1;
1126 	}
1127 
1128 	if (!g_flowindent) {
1129 		if (!g_quiet) {
1130 			char name[DTRACE_FUNCNAMELEN + DTRACE_NAMELEN + 2];
1131 
1132 			(void) snprintf(name, sizeof (name), "%s:%s",
1133 			    pd->dtpd_func, pd->dtpd_name);
1134 
1135 			oprintf("%3d %6d %32s ", cpu, pd->dtpd_id, name);
1136 		}
1137 	} else {
1138 		int indent = data->dtpda_indent;
1139 		char *name;
1140 		size_t len;
1141 
1142 		if (data->dtpda_flow == DTRACEFLOW_NONE) {
1143 			len = indent + DTRACE_FUNCNAMELEN + DTRACE_NAMELEN + 5;
1144 			name = alloca(len);
1145 			(void) snprintf(name, len, "%*s%s%s:%s", indent, "",
1146 			    data->dtpda_prefix, pd->dtpd_func,
1147 			    pd->dtpd_name);
1148 		} else {
1149 			len = indent + DTRACE_FUNCNAMELEN + 5;
1150 			name = alloca(len);
1151 			(void) snprintf(name, len, "%*s%s%s", indent, "",
1152 			    data->dtpda_prefix, pd->dtpd_func);
1153 		}
1154 
1155 		oprintf("%3d %-41s ", cpu, name);
1156 	}
1157 
1158 	return (DTRACE_CONSUME_THIS);
1159 }
1160 
1161 static void
1162 go(void)
1163 {
1164 	int i;
1165 
1166 	struct {
1167 		char *name;
1168 		char *optname;
1169 		dtrace_optval_t val;
1170 	} bufs[] = {
1171 		{ "buffer size", "bufsize" },
1172 		{ "aggregation size", "aggsize" },
1173 		{ "speculation size", "specsize" },
1174 		{ "dynamic variable size", "dynvarsize" },
1175 		{ NULL }
1176 	}, rates[] = {
1177 		{ "cleaning rate", "cleanrate" },
1178 		{ "status rate", "statusrate" },
1179 		{ NULL }
1180 	};
1181 
1182 	for (i = 0; bufs[i].name != NULL; i++) {
1183 		if (dtrace_getopt(g_dtp, bufs[i].optname, &bufs[i].val) == -1)
1184 			fatal("couldn't get option %s", bufs[i].optname);
1185 	}
1186 
1187 	for (i = 0; rates[i].name != NULL; i++) {
1188 		if (dtrace_getopt(g_dtp, rates[i].optname, &rates[i].val) == -1)
1189 			fatal("couldn't get option %s", rates[i].optname);
1190 	}
1191 
1192 	if (dtrace_go(g_dtp) == -1)
1193 		dfatal("could not enable tracing");
1194 
1195 	for (i = 0; bufs[i].name != NULL; i++) {
1196 		dtrace_optval_t j = 0, mul = 10;
1197 		dtrace_optval_t nsize;
1198 
1199 		if (bufs[i].val == DTRACEOPT_UNSET)
1200 			continue;
1201 
1202 		(void) dtrace_getopt(g_dtp, bufs[i].optname, &nsize);
1203 
1204 		if (nsize == DTRACEOPT_UNSET || nsize == 0)
1205 			continue;
1206 
1207 		if (nsize >= bufs[i].val - sizeof (uint64_t))
1208 			continue;
1209 
1210 		for (; (INT64_C(1) << mul) <= nsize; j++, mul += 10)
1211 			continue;
1212 
1213 		if (!(nsize & ((INT64_C(1) << (mul - 10)) - 1))) {
1214 			error("%s lowered to %lld%c\n", bufs[i].name,
1215 			    (long long)nsize >> (mul - 10), " kmgtpe"[j]);
1216 		} else {
1217 			error("%s lowered to %lld bytes\n", bufs[i].name,
1218 			    (long long)nsize);
1219 		}
1220 	}
1221 
1222 	for (i = 0; rates[i].name != NULL; i++) {
1223 		dtrace_optval_t nval;
1224 		char *dir;
1225 
1226 		if (rates[i].val == DTRACEOPT_UNSET)
1227 			continue;
1228 
1229 		(void) dtrace_getopt(g_dtp, rates[i].optname, &nval);
1230 
1231 		if (nval == DTRACEOPT_UNSET || nval == 0)
1232 			continue;
1233 
1234 		if (rates[i].val == nval)
1235 			continue;
1236 
1237 		dir = nval > rates[i].val ? "reduced" : "increased";
1238 
1239 		if (nval <= NANOSEC && (NANOSEC % nval) == 0) {
1240 			error("%s %s to %lld hz\n", rates[i].name, dir,
1241 			    (long long)NANOSEC / (long long)nval);
1242 			continue;
1243 		}
1244 
1245 		if ((nval % NANOSEC) == 0) {
1246 			error("%s %s to once every %lld seconds\n",
1247 			    rates[i].name, dir,
1248 			    (long long)nval / (long long)NANOSEC);
1249 			continue;
1250 		}
1251 
1252 		error("%s %s to once every %lld nanoseconds\n",
1253 		    rates[i].name, dir, (long long)nval);
1254 	}
1255 }
1256 
1257 /*ARGSUSED*/
1258 static void
1259 intr(int signo)
1260 {
1261 	if (!g_intr)
1262 		g_newline = 1;
1263 
1264 	if (g_intr++)
1265 		g_impatient = 1;
1266 }
1267 
1268 #ifdef __FreeBSD__
1269 static void
1270 siginfo(int signo __unused)
1271 {
1272 
1273 	g_siginfo++;
1274 	g_newline = 1;
1275 }
1276 #endif
1277 
1278 static void
1279 installsighands(void)
1280 {
1281 	struct sigaction act, oact;
1282 
1283 	(void) sigemptyset(&act.sa_mask);
1284 	act.sa_flags = 0;
1285 	act.sa_handler = intr;
1286 
1287 	if (sigaction(SIGINT, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
1288 		(void) sigaction(SIGINT, &act, NULL);
1289 
1290 	if (sigaction(SIGTERM, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
1291 		(void) sigaction(SIGTERM, &act, NULL);
1292 
1293 #ifdef __FreeBSD__
1294 	if (sigaction(SIGPIPE, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
1295 		(void) sigaction(SIGPIPE, &act, NULL);
1296 
1297 	if (sigaction(SIGUSR1, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
1298 		(void) sigaction(SIGUSR1, &act, NULL);
1299 
1300 	act.sa_handler = siginfo;
1301 	if (sigaction(SIGINFO, NULL, &oact) == 0 && oact.sa_handler != SIG_IGN)
1302 		(void) sigaction(SIGINFO, &act, NULL);
1303 #endif
1304 }
1305 
1306 int
1307 main(int argc, char *argv[])
1308 {
1309 	dtrace_bufdesc_t buf;
1310 	dtrace_status_t status[2];
1311 	dtrace_optval_t opt;
1312 	dtrace_cmd_t *dcp;
1313 
1314 	g_ofp = stdout;
1315 	int done = 0, mode = 0;
1316 	int err, i, c;
1317 	char *p, **v;
1318 	struct ps_prochandle *P;
1319 	pid_t pid;
1320 
1321 #ifdef __FreeBSD__
1322 	/* For %'d and the like. */
1323 	(void) setlocale(LC_NUMERIC, "");
1324 
1325 	/* For %T. */
1326 	(void) setlocale(LC_TIME, "");
1327 #endif
1328 
1329 	g_pname = basename(argv[0]);
1330 
1331 	if (argc == 1)
1332 		return (usage(stderr));
1333 
1334 	if ((g_argv = malloc(sizeof (char *) * argc)) == NULL ||
1335 	    (g_cmdv = malloc(sizeof (dtrace_cmd_t) * argc)) == NULL ||
1336 	    (g_psv = malloc(sizeof (struct ps_prochandle *) * argc)) == NULL)
1337 		fatal("failed to allocate memory for arguments");
1338 
1339 	g_argv[g_argc++] = argv[0];	/* propagate argv[0] to D as $0/$$0 */
1340 	argv[0] = g_pname;		/* rewrite argv[0] for getopt errors */
1341 
1342 	bzero(status, sizeof (status));
1343 	bzero(&buf, sizeof (buf));
1344 
1345 	/*
1346 	 * Make an initial pass through argv[] processing any arguments that
1347 	 * affect our behavior mode (g_mode) and flags used for dtrace_open().
1348 	 * We also accumulate arguments that are not affiliated with getopt
1349 	 * options into g_argv[], and abort if any invalid options are found.
1350 	 */
1351 	for (optind = 1; optind < argc; optind++) {
1352 		while ((c = getopt(argc, argv, DTRACE_OPTSTR)) != -1) {
1353 			switch (c) {
1354 			case '3':
1355 				if (strcmp(optarg, "2") != 0) {
1356 					(void) fprintf(stderr,
1357 					    "%s: illegal option -- 3%s\n",
1358 					    argv[0], optarg);
1359 					return (usage(stderr));
1360 				}
1361 				g_oflags &= ~DTRACE_O_LP64;
1362 				g_oflags |= DTRACE_O_ILP32;
1363 				break;
1364 
1365 			case '6':
1366 				if (strcmp(optarg, "4") != 0) {
1367 					(void) fprintf(stderr,
1368 					    "%s: illegal option -- 6%s\n",
1369 					    argv[0], optarg);
1370 					return (usage(stderr));
1371 				}
1372 				g_oflags &= ~DTRACE_O_ILP32;
1373 				g_oflags |= DTRACE_O_LP64;
1374 				break;
1375 
1376 			case 'a':
1377 				g_grabanon++; /* also checked in pass 2 below */
1378 				break;
1379 
1380 			case 'A':
1381 				g_mode = DMODE_ANON;
1382 				g_exec = 0;
1383 				mode++;
1384 				break;
1385 
1386 			case 'e':
1387 				g_exec = 0;
1388 				done = 1;
1389 				break;
1390 
1391 			case 'h':
1392 				g_mode = DMODE_HEADER;
1393 				g_oflags |= DTRACE_O_NODEV;
1394 				g_cflags |= DTRACE_C_ZDEFS; /* -h implies -Z */
1395 				g_exec = 0;
1396 				mode++;
1397 				break;
1398 
1399 			case 'G':
1400 				g_mode = DMODE_LINK;
1401 				g_oflags |= DTRACE_O_NODEV;
1402 				g_cflags |= DTRACE_C_ZDEFS; /* -G implies -Z */
1403 				g_exec = 0;
1404 				mode++;
1405 				break;
1406 
1407 			case 'l':
1408 				g_mode = DMODE_LIST;
1409 				g_cflags |= DTRACE_C_ZDEFS; /* -l implies -Z */
1410 				mode++;
1411 				break;
1412 
1413 			case 'V':
1414 				g_mode = DMODE_VERS;
1415 				mode++;
1416 				break;
1417 
1418 			default:
1419 				if (strchr(DTRACE_OPTSTR, c) == NULL)
1420 					return (usage(stderr));
1421 			}
1422 		}
1423 
1424 		if (optind < argc)
1425 			g_argv[g_argc++] = argv[optind];
1426 	}
1427 
1428 	if (mode > 1) {
1429 		(void) fprintf(stderr, "%s: only one of the [-AGhlV] options "
1430 		    "can be specified at a time\n", g_pname);
1431 		return (E_USAGE);
1432 	}
1433 
1434 	if (g_mode == DMODE_VERS)
1435 		return (printf("%s: %s\n", g_pname, _dtrace_version) <= 0);
1436 
1437 	/*
1438 	 * If we're in linker mode and the data model hasn't been specified,
1439 	 * we try to guess the appropriate setting by examining the object
1440 	 * files. We ignore certain errors since we'll catch them later when
1441 	 * we actually process the object files.
1442 	 */
1443 	if (g_mode == DMODE_LINK &&
1444 	    (g_oflags & (DTRACE_O_ILP32 | DTRACE_O_LP64)) == 0 &&
1445 	    elf_version(EV_CURRENT) != EV_NONE) {
1446 		int fd;
1447 		Elf *elf;
1448 		GElf_Ehdr ehdr;
1449 
1450 		for (i = 1; i < g_argc; i++) {
1451 			if ((fd = open64(g_argv[i], O_RDONLY)) == -1)
1452 				break;
1453 
1454 			if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
1455 				(void) close(fd);
1456 				break;
1457 			}
1458 
1459 			if (elf_kind(elf) != ELF_K_ELF ||
1460 			    gelf_getehdr(elf, &ehdr) == NULL) {
1461 				(void) close(fd);
1462 				(void) elf_end(elf);
1463 				break;
1464 			}
1465 
1466 			(void) close(fd);
1467 			(void) elf_end(elf);
1468 
1469 			if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
1470 				if (g_oflags & DTRACE_O_ILP32) {
1471 					fatal("can't mix 32-bit and 64-bit "
1472 					    "object files\n");
1473 				}
1474 				g_oflags |= DTRACE_O_LP64;
1475 			} else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
1476 				if (g_oflags & DTRACE_O_LP64) {
1477 					fatal("can't mix 32-bit and 64-bit "
1478 					    "object files\n");
1479 				}
1480 				g_oflags |= DTRACE_O_ILP32;
1481 			} else {
1482 				break;
1483 			}
1484 		}
1485 	}
1486 
1487 	/*
1488 	 * Open libdtrace.  If we are not actually going to be enabling any
1489 	 * instrumentation attempt to reopen libdtrace using DTRACE_O_NODEV.
1490 	 */
1491 	while ((g_dtp = dtrace_open(DTRACE_VERSION, g_oflags, &err)) == NULL) {
1492 		if (!(g_oflags & DTRACE_O_NODEV) && !g_exec && !g_grabanon) {
1493 			g_oflags |= DTRACE_O_NODEV;
1494 			continue;
1495 		}
1496 
1497 		fatal("failed to initialize dtrace: %s\n",
1498 		    dtrace_errmsg(NULL, err));
1499 	}
1500 
1501 #if defined(__i386__)
1502 	/* XXX The 32-bit seems to need more buffer space by default -sson */
1503 	(void) dtrace_setopt(g_dtp, "bufsize", "12m");
1504 	(void) dtrace_setopt(g_dtp, "aggsize", "12m");
1505 #else
1506 	(void) dtrace_setopt(g_dtp, "bufsize", "4m");
1507 	(void) dtrace_setopt(g_dtp, "aggsize", "4m");
1508 #endif
1509 	(void) dtrace_setopt(g_dtp, "temporal", "yes");
1510 
1511 	/*
1512 	 * If -G is specified, enable -xlink=dynamic and -xunodefs to permit
1513 	 * references to undefined symbols to remain as unresolved relocations.
1514 	 * If -A is specified, enable -xlink=primary to permit static linking
1515 	 * only to kernel symbols that are defined in a primary kernel module.
1516 	 */
1517 	if (g_mode == DMODE_LINK) {
1518 		(void) dtrace_setopt(g_dtp, "linkmode", "dynamic");
1519 		(void) dtrace_setopt(g_dtp, "unodefs", NULL);
1520 
1521 		/*
1522 		 * Use the remaining arguments as the list of object files
1523 		 * when in linker mode.
1524 		 */
1525 		g_objc = g_argc - 1;
1526 		g_objv = g_argv + 1;
1527 
1528 		/*
1529 		 * We still use g_argv[0], the name of the executable.
1530 		 */
1531 		g_argc = 1;
1532 	} else if (g_mode == DMODE_ANON)
1533 		(void) dtrace_setopt(g_dtp, "linkmode", "primary");
1534 
1535 	/*
1536 	 * Now that we have libdtrace open, make a second pass through argv[]
1537 	 * to perform any dtrace_setopt() calls and change any compiler flags.
1538 	 * We also accumulate any program specifications into our g_cmdv[] at
1539 	 * this time; these will compiled as part of the fourth processing pass.
1540 	 */
1541 	for (optind = 1; optind < argc; optind++) {
1542 		while ((c = getopt(argc, argv, DTRACE_OPTSTR)) != -1) {
1543 			switch (c) {
1544 			case 'a':
1545 				if (dtrace_setopt(g_dtp, "grabanon", 0) != 0)
1546 					dfatal("failed to set -a");
1547 				break;
1548 
1549 			case 'b':
1550 				if (dtrace_setopt(g_dtp,
1551 				    "bufsize", optarg) != 0)
1552 					dfatal("failed to set -b %s", optarg);
1553 				break;
1554 
1555 			case 'B':
1556 				g_ofp = NULL;
1557 				break;
1558 
1559 			case 'C':
1560 				g_cflags |= DTRACE_C_CPP;
1561 				break;
1562 
1563 			case 'd':
1564 				g_cflags |= DTRACE_C_SUGAR;
1565 				break;
1566 
1567 			case 'D':
1568 				if (dtrace_setopt(g_dtp, "define", optarg) != 0)
1569 					dfatal("failed to set -D %s", optarg);
1570 				break;
1571 
1572 			case 'f':
1573 				dcp = &g_cmdv[g_cmdc++];
1574 				dcp->dc_func = compile_str;
1575 				dcp->dc_spec = DTRACE_PROBESPEC_FUNC;
1576 				dcp->dc_arg = optarg;
1577 				break;
1578 
1579 			case 'F':
1580 				if (dtrace_setopt(g_dtp, "flowindent", 0) != 0)
1581 					dfatal("failed to set -F");
1582 				break;
1583 
1584 			case 'H':
1585 				if (dtrace_setopt(g_dtp, "cpphdrs", 0) != 0)
1586 					dfatal("failed to set -H");
1587 				break;
1588 
1589 			case 'i':
1590 				dcp = &g_cmdv[g_cmdc++];
1591 				dcp->dc_func = compile_str;
1592 				dcp->dc_spec = DTRACE_PROBESPEC_NAME;
1593 				dcp->dc_arg = optarg;
1594 				break;
1595 
1596 			case 'I':
1597 				if (dtrace_setopt(g_dtp, "incdir", optarg) != 0)
1598 					dfatal("failed to set -I %s", optarg);
1599 				break;
1600 
1601 			case 'L':
1602 				if (dtrace_setopt(g_dtp, "libdir", optarg) != 0)
1603 					dfatal("failed to set -L %s", optarg);
1604 				break;
1605 
1606 			case 'm':
1607 				dcp = &g_cmdv[g_cmdc++];
1608 				dcp->dc_func = compile_str;
1609 				dcp->dc_spec = DTRACE_PROBESPEC_MOD;
1610 				dcp->dc_arg = optarg;
1611 				break;
1612 
1613 			case 'n':
1614 				dcp = &g_cmdv[g_cmdc++];
1615 				dcp->dc_func = compile_str;
1616 				dcp->dc_spec = DTRACE_PROBESPEC_NAME;
1617 				dcp->dc_arg = optarg;
1618 				break;
1619 
1620 			case 'P':
1621 				dcp = &g_cmdv[g_cmdc++];
1622 				dcp->dc_func = compile_str;
1623 				dcp->dc_spec = DTRACE_PROBESPEC_PROVIDER;
1624 				dcp->dc_arg = optarg;
1625 				break;
1626 
1627 			case 'q':
1628 				if (dtrace_setopt(g_dtp, "quiet", 0) != 0)
1629 					dfatal("failed to set -q");
1630 				break;
1631 
1632 			case 'o':
1633 				g_ofile = optarg;
1634 				break;
1635 
1636 			case 's':
1637 				dcp = &g_cmdv[g_cmdc++];
1638 				dcp->dc_func = compile_file;
1639 				dcp->dc_spec = DTRACE_PROBESPEC_NONE;
1640 				dcp->dc_arg = optarg;
1641 				break;
1642 
1643 			case 'S':
1644 				g_cflags |= DTRACE_C_DIFV;
1645 				break;
1646 
1647 			case 'U':
1648 				if (dtrace_setopt(g_dtp, "undef", optarg) != 0)
1649 					dfatal("failed to set -U %s", optarg);
1650 				break;
1651 
1652 			case 'v':
1653 				g_verbose++;
1654 				break;
1655 
1656 			case 'w':
1657 				if (dtrace_setopt(g_dtp, "destructive", 0) != 0)
1658 					dfatal("failed to set -w");
1659 				break;
1660 
1661 			case 'x':
1662 				if ((p = strchr(optarg, '=')) != NULL)
1663 					*p++ = '\0';
1664 
1665 				if (dtrace_setopt(g_dtp, optarg, p) != 0)
1666 					dfatal("failed to set -x %s", optarg);
1667 				break;
1668 
1669 			case 'X':
1670 				if (dtrace_setopt(g_dtp, "stdc", optarg) != 0)
1671 					dfatal("failed to set -X %s", optarg);
1672 				break;
1673 
1674 			case 'Z':
1675 				g_cflags |= DTRACE_C_ZDEFS;
1676 				break;
1677 
1678 			default:
1679 				if (strchr(DTRACE_OPTSTR, c) == NULL)
1680 					return (usage(stderr));
1681 			}
1682 		}
1683 	}
1684 
1685 	if (g_ofp == NULL && g_mode != DMODE_EXEC) {
1686 		(void) fprintf(stderr, "%s: -B not valid in combination"
1687 		    " with [-AGl] options\n", g_pname);
1688 		return (E_USAGE);
1689 	}
1690 
1691 	if (g_ofp == NULL && g_ofile != NULL) {
1692 		(void) fprintf(stderr, "%s: -B not valid in combination"
1693 		    " with -o option\n", g_pname);
1694 		return (E_USAGE);
1695 	}
1696 
1697 	/*
1698 	 * In our third pass we handle any command-line options related to
1699 	 * grabbing or creating victim processes.  The behavior of these calls
1700 	 * may been affected by any library options set by the second pass.
1701 	 */
1702 	for (optind = 1; optind < argc; optind++) {
1703 		while ((c = getopt(argc, argv, DTRACE_OPTSTR)) != -1) {
1704 			switch (c) {
1705 			case 'c':
1706 				if ((v = make_argv(optarg)) == NULL)
1707 					fatal("failed to allocate memory");
1708 
1709 				P = dtrace_proc_create(g_dtp, v[0], v, NULL, NULL);
1710 				if (P == NULL)
1711 					dfatal(NULL); /* dtrace_errmsg() only */
1712 
1713 				g_psv[g_psc++] = P;
1714 				free(v);
1715 				break;
1716 
1717 			case 'p':
1718 				errno = 0;
1719 				pid = strtol(optarg, &p, 10);
1720 
1721 				if (errno != 0 || p == optarg || p[0] != '\0')
1722 					fatal("invalid pid: %s\n", optarg);
1723 
1724 				P = dtrace_proc_grab(g_dtp, pid, 0);
1725 				if (P == NULL)
1726 					dfatal(NULL); /* dtrace_errmsg() only */
1727 
1728 				g_psv[g_psc++] = P;
1729 				break;
1730 			}
1731 		}
1732 	}
1733 
1734 	/*
1735 	 * In our fourth pass we finish g_cmdv[] by calling dc_func to convert
1736 	 * each string or file specification into a compiled program structure.
1737 	 */
1738 	for (i = 0; i < g_cmdc; i++)
1739 		g_cmdv[i].dc_func(&g_cmdv[i]);
1740 
1741 	if (g_mode != DMODE_LIST) {
1742 		if (dtrace_handle_err(g_dtp, &errhandler, NULL) == -1)
1743 			dfatal("failed to establish error handler");
1744 
1745 		if (dtrace_handle_drop(g_dtp, &drophandler, NULL) == -1)
1746 			dfatal("failed to establish drop handler");
1747 
1748 		if (dtrace_handle_proc(g_dtp, &prochandler, NULL) == -1)
1749 			dfatal("failed to establish proc handler");
1750 
1751 		if (dtrace_handle_setopt(g_dtp, &setopthandler, NULL) == -1)
1752 			dfatal("failed to establish setopt handler");
1753 
1754 		if (g_ofp == NULL &&
1755 		    dtrace_handle_buffered(g_dtp, &bufhandler, NULL) == -1)
1756 			dfatal("failed to establish buffered handler");
1757 	}
1758 
1759 	(void) dtrace_getopt(g_dtp, "flowindent", &opt);
1760 	g_flowindent = opt != DTRACEOPT_UNSET;
1761 
1762 	(void) dtrace_getopt(g_dtp, "grabanon", &opt);
1763 	g_grabanon = opt != DTRACEOPT_UNSET;
1764 
1765 	(void) dtrace_getopt(g_dtp, "quiet", &opt);
1766 	g_quiet = opt != DTRACEOPT_UNSET;
1767 
1768 	/*
1769 	 * Now make a fifth and final pass over the options that have been
1770 	 * turned into programs and saved in g_cmdv[], performing any mode-
1771 	 * specific processing.  If g_mode is DMODE_EXEC, we will break out
1772 	 * of the switch() and continue on to the data processing loop.  For
1773 	 * other modes, we will exit dtrace once mode-specific work is done.
1774 	 */
1775 	switch (g_mode) {
1776 	case DMODE_EXEC:
1777 		if (g_ofile != NULL && (g_ofp = fopen(g_ofile, "a")) == NULL)
1778 			fatal("failed to open output file '%s'", g_ofile);
1779 
1780 		for (i = 0; i < g_cmdc; i++)
1781 			exec_prog(&g_cmdv[i]);
1782 
1783 		if (done && !g_grabanon) {
1784 			dtrace_close(g_dtp);
1785 			return (g_status);
1786 		}
1787 		break;
1788 
1789 	case DMODE_ANON:
1790 		if (g_ofile == NULL)
1791 #ifdef illumos
1792 			g_ofile = "/kernel/drv/dtrace.conf";
1793 #else
1794 			/*
1795 			 * On FreeBSD, anonymous DOF data is written to
1796 			 * the DTrace DOF file.
1797 			 */
1798 			g_ofile = "/boot/dtrace.dof";
1799 #endif
1800 
1801 		dof_prune(g_ofile); /* strip out any old DOF directives */
1802 #ifdef illumos
1803 		etcsystem_prune(); /* string out any forceload directives */
1804 #endif
1805 
1806 		if (g_cmdc == 0) {
1807 			dtrace_close(g_dtp);
1808 			return (g_status);
1809 		}
1810 
1811 		if ((g_ofp = fopen(g_ofile, "a")) == NULL)
1812 			fatal("failed to open output file '%s'", g_ofile);
1813 
1814 		for (i = 0; i < g_cmdc; i++) {
1815 			anon_prog(&g_cmdv[i],
1816 			    dtrace_dof_create(g_dtp, g_cmdv[i].dc_prog, 0), i);
1817 		}
1818 
1819 		/*
1820 		 * Dump out the DOF corresponding to the error handler and the
1821 		 * current options as the final DOF property in the .conf file.
1822 		 */
1823 		anon_prog(NULL, dtrace_geterr_dof(g_dtp), i++);
1824 		anon_prog(NULL, dtrace_getopt_dof(g_dtp), i++);
1825 
1826 		if (fclose(g_ofp) == EOF)
1827 			fatal("failed to close output file '%s'", g_ofile);
1828 
1829 		/*
1830 		 * These messages would use notice() rather than error(), but
1831 		 * we don't want them suppressed when -A is run on a D program
1832 		 * that itself contains a #pragma D option quiet.
1833 		 */
1834 		error("saved anonymous enabling in %s\n", g_ofile);
1835 
1836 #ifdef __FreeBSD__
1837 		bootdof_add();
1838 #else
1839 		etcsystem_add();
1840 		error("run update_drv(1M) or reboot to enable changes\n");
1841 #endif
1842 
1843 		dtrace_close(g_dtp);
1844 		return (g_status);
1845 
1846 	case DMODE_LINK:
1847 		if (g_cmdc == 0) {
1848 			(void) fprintf(stderr, "%s: -G requires one or more "
1849 			    "scripts or enabling options\n", g_pname);
1850 			dtrace_close(g_dtp);
1851 			return (E_USAGE);
1852 		}
1853 
1854 		for (i = 0; i < g_cmdc; i++)
1855 			link_prog(&g_cmdv[i]);
1856 
1857 		if (g_cmdc > 1 && g_ofile != NULL) {
1858 			char **objv = alloca(g_cmdc * sizeof (char *));
1859 
1860 			for (i = 0; i < g_cmdc; i++)
1861 				objv[i] = g_cmdv[i].dc_ofile;
1862 
1863 			if (dtrace_program_link(g_dtp, NULL, DTRACE_D_PROBES,
1864 			    g_ofile, g_cmdc, objv) != 0)
1865 				dfatal(NULL); /* dtrace_errmsg() only */
1866 		}
1867 
1868 		dtrace_close(g_dtp);
1869 		return (g_status);
1870 
1871 	case DMODE_LIST:
1872 		if (g_ofile != NULL && (g_ofp = fopen(g_ofile, "a")) == NULL)
1873 			fatal("failed to open output file '%s'", g_ofile);
1874 
1875 		installsighands();
1876 
1877 		oprintf("%5s %10s %17s %33s %s\n",
1878 		    "ID", "PROVIDER", "MODULE", "FUNCTION", "NAME");
1879 
1880 		for (i = 0; i < g_cmdc; i++)
1881 			list_prog(&g_cmdv[i]);
1882 
1883 		if (g_cmdc == 0)
1884 			(void) dtrace_probe_iter(g_dtp, NULL, list_probe, NULL);
1885 
1886 		dtrace_close(g_dtp);
1887 		return (g_status);
1888 
1889 	case DMODE_HEADER:
1890 		if (g_cmdc == 0) {
1891 			(void) fprintf(stderr, "%s: -h requires one or more "
1892 			    "scripts or enabling options\n", g_pname);
1893 			dtrace_close(g_dtp);
1894 			return (E_USAGE);
1895 		}
1896 
1897 		if (g_ofile == NULL) {
1898 			char *p;
1899 
1900 			if (g_cmdc > 1) {
1901 				(void) fprintf(stderr, "%s: -h requires an "
1902 				    "output file if multiple scripts are "
1903 				    "specified\n", g_pname);
1904 				dtrace_close(g_dtp);
1905 				return (E_USAGE);
1906 			}
1907 
1908 			if ((p = strrchr(g_cmdv[0].dc_arg, '.')) == NULL ||
1909 			    strcmp(p, ".d") != 0) {
1910 				(void) fprintf(stderr, "%s: -h requires an "
1911 				    "output file if no scripts are "
1912 				    "specified\n", g_pname);
1913 				dtrace_close(g_dtp);
1914 				return (E_USAGE);
1915 			}
1916 
1917 			p[0] = '\0'; /* strip .d suffix */
1918 			g_ofile = p = g_cmdv[0].dc_ofile;
1919 			(void) snprintf(p, sizeof (g_cmdv[0].dc_ofile),
1920 			    "%s.h", basename(g_cmdv[0].dc_arg));
1921 		}
1922 
1923 		if ((g_ofp = fopen(g_ofile, "w")) == NULL)
1924 			fatal("failed to open header file '%s'", g_ofile);
1925 
1926 		oprintf("/*\n * Generated by dtrace(1M).\n */\n\n");
1927 
1928 		if (dtrace_program_header(g_dtp, g_ofp, g_ofile) != 0 ||
1929 		    fclose(g_ofp) == EOF)
1930 			dfatal("failed to create header file %s", g_ofile);
1931 
1932 		dtrace_close(g_dtp);
1933 		return (g_status);
1934 	}
1935 
1936 	/*
1937 	 * If -a and -Z were not specified and no probes have been matched, no
1938 	 * probe criteria was specified on the command line and we abort.
1939 	 */
1940 	if (g_total == 0 && !g_grabanon && !(g_cflags & DTRACE_C_ZDEFS))
1941 		dfatal("no probes %s\n", g_cmdc ? "matched" : "specified");
1942 
1943 	/*
1944 	 * Start tracing.  Once we dtrace_go(), reload any options that affect
1945 	 * our globals in case consuming anonymous state has changed them.
1946 	 */
1947 	go();
1948 
1949 	(void) dtrace_getopt(g_dtp, "flowindent", &opt);
1950 	g_flowindent = opt != DTRACEOPT_UNSET;
1951 
1952 	(void) dtrace_getopt(g_dtp, "grabanon", &opt);
1953 	g_grabanon = opt != DTRACEOPT_UNSET;
1954 
1955 	(void) dtrace_getopt(g_dtp, "quiet", &opt);
1956 	g_quiet = opt != DTRACEOPT_UNSET;
1957 
1958 	(void) dtrace_getopt(g_dtp, "destructive", &opt);
1959 	if (opt != DTRACEOPT_UNSET)
1960 		notice("allowing destructive actions\n");
1961 
1962 	installsighands();
1963 
1964 	/*
1965 	 * Now that tracing is active and we are ready to consume trace data,
1966 	 * continue any grabbed or created processes, setting them running
1967 	 * using the /proc control mechanism inside of libdtrace.
1968 	 */
1969 	for (i = 0; i < g_psc; i++)
1970 		dtrace_proc_continue(g_dtp, g_psv[i]);
1971 
1972 	g_pslive = g_psc; /* count for prochandler() */
1973 
1974 	do {
1975 		if (!g_intr && !done)
1976 			dtrace_sleep(g_dtp);
1977 
1978 #ifdef __FreeBSD__
1979 		if (g_siginfo) {
1980 			(void)dtrace_aggregate_print(g_dtp, g_ofp, NULL);
1981 			g_siginfo = 0;
1982 		}
1983 #endif
1984 
1985 		if (g_newline) {
1986 			/*
1987 			 * Output a newline just to make the output look
1988 			 * slightly cleaner.  Note that we do this even in
1989 			 * "quiet" mode...
1990 			 */
1991 			oprintf("\n");
1992 			g_newline = 0;
1993 		}
1994 
1995 		if (done || g_intr || (g_psc != 0 && g_pslive == 0)) {
1996 			done = 1;
1997 			if (dtrace_stop(g_dtp) == -1)
1998 				dfatal("couldn't stop tracing");
1999 		}
2000 
2001 		switch (dtrace_work(g_dtp, g_ofp, chew, chewrec, NULL)) {
2002 		case DTRACE_WORKSTATUS_DONE:
2003 			done = 1;
2004 			break;
2005 		case DTRACE_WORKSTATUS_OKAY:
2006 			break;
2007 		default:
2008 			if (!g_impatient && dtrace_errno(g_dtp) != EINTR)
2009 				dfatal("processing aborted");
2010 		}
2011 
2012 		if (g_ofp != NULL && fflush(g_ofp) == EOF)
2013 			clearerr(g_ofp);
2014 	} while (!done);
2015 
2016 	oprintf("\n");
2017 
2018 	if (!g_impatient) {
2019 		if (dtrace_aggregate_print(g_dtp, g_ofp, NULL) == -1 &&
2020 		    dtrace_errno(g_dtp) != EINTR)
2021 			dfatal("failed to print aggregations");
2022 	}
2023 
2024 	dtrace_close(g_dtp);
2025 	return (g_status);
2026 }
2027