1235457Sgnn#!/bin/sh
2211557Srpaulo#
3211557Srpaulo# dtruss - print process system call time details.
4211557Srpaulo#          Written using DTrace (Solaris 10 3/05).
5211557Srpaulo#
6211557Srpaulo# $Id: dtruss 9 2007-08-07 10:21:07Z brendan $
7211557Srpaulo#
8211557Srpaulo# USAGE: dtruss [-acdeflhoLs] [-t syscall] { -p PID | -n name | command }
9211557Srpaulo#
10211557Srpaulo#		-p PID		# examine this PID
11211557Srpaulo#		-n name		# examine this process name
12211557Srpaulo#		-t syscall	# examine this syscall only
13211557Srpaulo#		-a		# print all details
14211557Srpaulo#		-c		# print system call counts
15211557Srpaulo#		-d		# print relative timestamps (us)
16211557Srpaulo#		-e		# print elapsed times (us)
17211557Srpaulo#		-f		# follow children as they are forked
18211557Srpaulo#		-l		# force printing of pid/lwpid per line
19211557Srpaulo#		-o		# print on cpu times (us)
20211557Srpaulo#		-s		# print stack backtraces
21211557Srpaulo#		-L		# don't print pid/lwpid per line
22211557Srpaulo#		-b bufsize	# dynamic variable buf size (default is "4m")
23211557Srpaulo#  eg,
24211557Srpaulo#		dtruss df -h	# run and examine the "df -h" command
25211557Srpaulo#		dtruss -p 1871	# examine PID 1871
26211557Srpaulo#		dtruss -n tar	# examine all processes called "tar"
27211557Srpaulo#		dtruss -f test.sh	# run test.sh and follow children
28211557Srpaulo#
29211557Srpaulo# See the man page dtruss(1M) for further details.
30211557Srpaulo#
31211557Srpaulo# SEE ALSO: procsystime    # DTraceToolkit
32211557Srpaulo#           dapptrace      # DTraceToolkit
33211557Srpaulo#           truss
34211557Srpaulo#
35211557Srpaulo# COPYRIGHT: Copyright (c) 2005, 2006, 2007 Brendan Gregg.
36211557Srpaulo#
37211557Srpaulo# CDDL HEADER START
38211557Srpaulo#
39211557Srpaulo#  The contents of this file are subject to the terms of the
40211557Srpaulo#  Common Development and Distribution License, Version 1.0 only
41211557Srpaulo#  (the "License").  You may not use this file except in compliance
42211557Srpaulo#  with the License.
43211557Srpaulo#
44211557Srpaulo#  You can obtain a copy of the license at Docs/cddl1.txt
45211557Srpaulo#  or http://www.opensolaris.org/os/licensing.
46211557Srpaulo#  See the License for the specific language governing permissions
47211557Srpaulo#  and limitations under the License.
48211557Srpaulo#
49211557Srpaulo# CDDL HEADER END
50211557Srpaulo#
51211557Srpaulo# TODO: Track signals, more output formatting.
52211557Srpaulo#
53211557Srpaulo# 29-Apr-2005   Brendan Gregg   Created this.
54211557Srpaulo# 09-May-2005      "      " 	Fixed evaltime (thanks Adam L.)
55211557Srpaulo# 16-May-2005	   "      "	Added -t syscall tracing.
56211557Srpaulo# 17-Jun-2005	   "      "	Added -s stack backtraces.
57211557Srpaulo# 17-Jun-2005	   "      "	Last update.
58211557Srpaulo# 29-Jun-2007	   "      "	Used progenyof() (thanks Aaron Gutman).
59211557Srpaulo# 06-Aug-2007	   "      "	Various updates.
60211557Srpaulo#
61211557Srpaulo
62211557Srpaulo
63211557Srpaulo##############################
64211557Srpaulo# --- Process Arguments ---
65211557Srpaulo#
66211557Srpaulo
67211557Srpaulo### Default variables
68211557Srpauloopt_pid=0; opt_name=0; pid=0; pname="."; opt_elapsed=0; opt_cpu=0
69211557Srpauloopt_counts=0; opt_relative=0; opt_printid=0; opt_follow=0; opt_command=0
70211557Srpaulocommand=""; opt_buf=0; buf="4m"; opt_trace=0; trace="."; opt_stack=0
71211557Srpaulo
72211557Srpaulo### Process options
73211557Srpaulowhile getopts ab:cdefhln:op:st:L name
74211557Srpaulodo
75211557Srpaulo        case $name in
76211557Srpaulo	b)	opt_buf=1; buf=$OPTARG ;;
77211557Srpaulo        p)      opt_pid=1; pid=$OPTARG ;;
78211557Srpaulo        n)      opt_name=1; pname=$OPTARG ;;
79211557Srpaulo        t)      opt_trace=1; trace=$OPTARG ;;
80211557Srpaulo	a)	opt_counts=1; opt_relative=1; opt_elapsed=1; opt_follow=1
81211557Srpaulo		opt_printid=1; opt_cpu=1 ;;
82211557Srpaulo	c)	opt_counts=1 ;;
83211557Srpaulo	d)	opt_relative=1 ;;
84211557Srpaulo	e)	opt_elapsed=1 ;;
85211557Srpaulo	f)	opt_follow=1 ;;
86211557Srpaulo	l)	opt_printid=1 ;;
87211557Srpaulo	o)	opt_cpu=1 ;;
88211557Srpaulo	L)	opt_printid=-1 ;;
89211557Srpaulo	s)	opt_stack=-1 ;;
90211557Srpaulo        h|?)    cat <<-END >&2
91211557Srpaulo		USAGE: dtruss [-acdefholLs] [-t syscall] { -p PID | -n name | command }
92211557Srpaulo
93211557Srpaulo		          -p PID          # examine this PID
94211557Srpaulo		          -n name         # examine this process name
95211557Srpaulo		          -t syscall      # examine this syscall only
96211557Srpaulo		          -a              # print all details
97211557Srpaulo		          -c              # print syscall counts
98211557Srpaulo		          -d              # print relative times (us)
99211557Srpaulo		          -e              # print elapsed times (us)
100211557Srpaulo		          -f              # follow children (-p or cmd only)
101211557Srpaulo		          -l              # force printing pid/lwpid
102211557Srpaulo		          -o              # print on cpu times
103211557Srpaulo		          -s              # print stack backtraces
104211557Srpaulo		          -L              # don't print pid/lwpid
105211557Srpaulo		          -b bufsize      # dynamic variable buf size
106211557Srpaulo		   eg,
107211557Srpaulo		       dtruss df -h       # run and examine "df -h"
108211557Srpaulo		       dtruss -p 1871     # examine PID 1871
109211557Srpaulo		       dtruss -n tar      # examine all processes called "tar"
110211557Srpaulo		       dtruss -f test.sh  # run test.sh and follow children
111211557Srpaulo		END
112211557Srpaulo		exit 1
113211557Srpaulo        esac
114211557Srpaulodone
115211557Srpauloshift `expr $OPTIND - 1`
116211557Srpaulo
117211557Srpaulo### Option logic
118211557Srpauloif [ $opt_pid -eq 0 -a $opt_name -eq 0 ]; then
119211557Srpaulo	opt_command=1
120211557Srpaulo	if [ "$*" = "" ]; then
121211557Srpaulo		$0 -h
122211557Srpaulo		exit
123211557Srpaulo	fi
124211557Srpaulo	command="$*"	# yes, I meant $*!
125211557Srpaulofi
126211557Srpauloif [ $opt_follow -eq 1 -o $opt_name -eq 1 ]; then
127211557Srpaulo	if [ $opt_printid -ne -1 ]; then
128211557Srpaulo		opt_printid=1
129211557Srpaulo	else
130211557Srpaulo		opt_printid=0
131211557Srpaulo	fi
132211557Srpaulofi
133211557Srpauloif [ $opt_follow -eq 1 -a $opt_name -eq 1 ]; then
134211557Srpaulo	echo "ERROR: -f option cannot be used with -n (use -p or cmd instead)."
135211557Srpaulo	exit 1
136211557Srpaulofi
137211557Srpaulo
138211557Srpaulo### Option translation
139211557Srpauloif [ "$trace" = "exec" ]; then trace="exece"; fi
140211557Srpauloif [ "$trace" = "time" ]; then trace="gtime"; fi
141211557Srpauloif [ "$trace" = "exit" ]; then trace="rexit"; fi
142211557Srpaulo
143211557Srpaulo
144211557Srpaulo#################################
145211557Srpaulo# --- Main Program, DTrace ---
146211557Srpaulo#
147211557Srpaulo
148211557Srpaulo### Define D Script
149211557Srpaulodtrace='
150211557Srpaulo#pragma D option quiet
151211557Srpaulo#pragma D option switchrate=10
152211557Srpaulo 
153211557Srpaulo/*
154211557Srpaulo * Command line arguments
155211557Srpaulo */
156211557Srpauloinline int OPT_command   = '$opt_command';
157211557Srpauloinline int OPT_follow    = '$opt_follow';
158211557Srpauloinline int OPT_printid   = '$opt_printid';
159211557Srpauloinline int OPT_relative  = '$opt_relative';
160211557Srpauloinline int OPT_elapsed   = '$opt_elapsed';
161211557Srpauloinline int OPT_cpu       = '$opt_cpu';
162211557Srpauloinline int OPT_counts    = '$opt_counts';
163211557Srpauloinline int OPT_pid       = '$opt_pid';
164211557Srpauloinline int OPT_name      = '$opt_name';
165211557Srpauloinline int OPT_trace     = '$opt_trace';
166211557Srpauloinline int OPT_stack     = '$opt_stack';
167211557Srpauloinline string NAME       = "'$pname'";
168211557Srpauloinline string TRACE      = "'$trace'";
169211557Srpaulo
170211557Srpaulodtrace:::BEGIN 
171211557Srpaulo{
172211557Srpaulo	/* print header */
173211557Srpaulo	OPT_printid  ? printf("%-9s  ", "PID/LWP") : 1;
174211557Srpaulo	OPT_relative ? printf("%8s ", "RELATIVE") : 1;
175211557Srpaulo	OPT_elapsed  ? printf("%7s ", "ELAPSD") : 1;
176211557Srpaulo	OPT_cpu      ? printf("%6s ", "CPU") : 1;
177211557Srpaulo	printf("SYSCALL(args) \t\t = return\n");
178211557Srpaulo}
179211557Srpaulo
180211557Srpaulo/*
181211557Srpaulo * Save syscall entry info
182211557Srpaulo */
183211557Srpaulosyscall:::entry
184211557Srpaulo/((OPT_command || OPT_pid) && pid == $target) || 
185211557Srpaulo (OPT_name && execname == NAME) ||
186211557Srpaulo (OPT_follow && progenyof($target))/
187211557Srpaulo{
188211557Srpaulo	/* set start details */
189211557Srpaulo	self->start = timestamp;
190211557Srpaulo	self->vstart = vtimestamp;
191211557Srpaulo	self->arg0 = arg0;
192211557Srpaulo	self->arg1 = arg1;
193211557Srpaulo	self->arg2 = arg2;
194211557Srpaulo
195211557Srpaulo	/* count occurances */
196211557Srpaulo	OPT_counts == 1 ? @Counts[probefunc] = count() : 1;
197211557Srpaulo}
198211557Srpaulo
199211557Srpaulo/*
200211557Srpaulo * Follow children
201211557Srpaulo */
202211557Srpaulosyscall::fork*:return
203211557Srpaulo/(OPT_follow && progenyof($target)) && (!OPT_trace || (TRACE == probefunc))/
204211557Srpaulo{
205211557Srpaulo	/* print output */
206211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
207211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
208211557Srpaulo	OPT_relative ? printf("%8d:  ", vtimestamp/1000) : 1;
209211557Srpaulo	OPT_elapsed  ? printf("%7d:  ", 0) : 1;
210211557Srpaulo	OPT_cpu      ? printf("%6d ", 0) : 1;
211211557Srpaulo	printf("%s(0x%X, 0x%X, 0x%X)\t\t = %d %s%d\n", probefunc,
212211557Srpaulo	    self->arg0, self->arg1, self->arg2, (int)arg0, self->code,
213211557Srpaulo	    (int)errno);
214211557Srpaulo}
215211557Srpaulo
216211557Srpaulo/*
217211557Srpaulo * Check for syscall tracing
218211557Srpaulo */
219211557Srpaulosyscall:::entry
220211557Srpaulo/OPT_trace && probefunc != TRACE/
221211557Srpaulo{
222211557Srpaulo	/* drop info */
223211557Srpaulo	self->start = 0;
224211557Srpaulo	self->vstart = 0;
225211557Srpaulo	self->arg0 = 0;
226211557Srpaulo	self->arg1 = 0;
227211557Srpaulo	self->arg2 = 0;
228211557Srpaulo}
229211557Srpaulo
230211557Srpaulo/*
231211557Srpaulo * Print return data
232211557Srpaulo */
233211557Srpaulo
234211557Srpaulo/*
235211557Srpaulo * The following code is written in an intentionally repetative way.
236211557Srpaulo * The first versions had no code redundancies, but performed badly during
237211557Srpaulo * benchmarking. The priority here is speed, not cleverness. I know there
238211557Srpaulo * are many obvious shortcuts to this code, I have tried them. This style has
239211557Srpaulo * shown in benchmarks to be the fastest (fewest probes fired, fewest actions).
240211557Srpaulo */
241211557Srpaulo
242211557Srpaulo/* print 3 args, return as hex */
243238125Semastesyscall::sigprocmask:return
244211557Srpaulo/self->start/
245211557Srpaulo{
246211557Srpaulo	/* calculate elapsed time */
247211557Srpaulo	this->elapsed = timestamp - self->start;
248211557Srpaulo	self->start = 0;
249211557Srpaulo	this->cpu = vtimestamp - self->vstart;
250211557Srpaulo	self->vstart = 0;
251211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
252211557Srpaulo 
253211557Srpaulo	/* print optional fields */
254211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
255211557Srpaulo	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
256211557Srpaulo	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
257211557Srpaulo	OPT_cpu ? printf("%6d ", this->cpu/1000) : 1;
258211557Srpaulo 
259211557Srpaulo	/* print main data */
260211557Srpaulo	printf("%s(0x%X, 0x%X, 0x%X)\t\t = 0x%X %s%d\n", probefunc,
261211557Srpaulo	    (int)self->arg0, self->arg1, self->arg2, (int)arg0,
262211557Srpaulo	    self->code, (int)errno);
263211557Srpaulo	OPT_stack ? ustack()    : 1;
264211557Srpaulo	OPT_stack ? trace("\n") : 1;
265211557Srpaulo	self->arg0 = 0;
266211557Srpaulo	self->arg1 = 0;
267211557Srpaulo	self->arg2 = 0;
268211557Srpaulo}
269211557Srpaulo
270211557Srpaulo/* print 3 args, arg0 as a string */
271238125Semastesyscall::access*:return,
272211557Srpaulosyscall::stat*:return, 
273211557Srpaulosyscall::lstat*:return, 
274238125Semastesyscall::readlink*:return,
275238125Semastesyscall::open*:return
276211557Srpaulo/self->start/
277211557Srpaulo{
278211557Srpaulo	/* calculate elapsed time */
279211557Srpaulo	this->elapsed = timestamp - self->start;
280211557Srpaulo	self->start = 0;
281211557Srpaulo	this->cpu = vtimestamp - self->vstart;
282211557Srpaulo	self->vstart = 0;
283211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
284211557Srpaulo 
285211557Srpaulo	/* print optional fields */
286211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
287211557Srpaulo	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
288211557Srpaulo	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
289211557Srpaulo	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
290211557Srpaulo 
291211557Srpaulo	/* print main data */
292211557Srpaulo	printf("%s(\"%S\", 0x%X, 0x%X)\t\t = %d %s%d\n", probefunc,
293211557Srpaulo	    copyinstr(self->arg0), self->arg1, self->arg2, (int)arg0,
294211557Srpaulo	    self->code, (int)errno);
295211557Srpaulo	OPT_stack ? ustack()    : 1;
296211557Srpaulo	OPT_stack ? trace("\n") : 1;
297211557Srpaulo	self->arg0 = 0;
298211557Srpaulo	self->arg1 = 0;
299211557Srpaulo	self->arg2 = 0;
300211557Srpaulo}
301211557Srpaulo
302211557Srpaulo/* print 3 args, arg1 as a string */
303211557Srpaulosyscall::write:return,
304211557Srpaulosyscall::pwrite:return,
305211557Srpaulosyscall::*read*:return
306211557Srpaulo/self->start/
307211557Srpaulo{
308211557Srpaulo	/* calculate elapsed time */
309211557Srpaulo	this->elapsed = timestamp - self->start;
310211557Srpaulo	self->start = 0;
311211557Srpaulo	this->cpu = vtimestamp - self->vstart;
312211557Srpaulo	self->vstart = 0;
313211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
314211557Srpaulo 
315211557Srpaulo	/* print optional fields */
316211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
317211557Srpaulo	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
318211557Srpaulo	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
319211557Srpaulo	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
320211557Srpaulo 
321211557Srpaulo	/* print main data */
322211557Srpaulo	printf("%s(0x%X, \"%S\", 0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
323211557Srpaulo	    stringof(copyin(self->arg1, self->arg2)), self->arg2, (int)arg0,
324211557Srpaulo	    self->code, (int)errno);
325211557Srpaulo	OPT_stack ? ustack()    : 1;
326211557Srpaulo	OPT_stack ? trace("\n") : 1;
327211557Srpaulo	self->arg0 = 0;
328211557Srpaulo	self->arg1 = 0;
329211557Srpaulo	self->arg2 = 0;
330211557Srpaulo}
331211557Srpaulo
332211557Srpaulo/* print 0 arg output */
333211557Srpaulosyscall::*fork*:return
334211557Srpaulo/self->start/
335211557Srpaulo{
336211557Srpaulo	/* calculate elapsed time */
337211557Srpaulo	this->elapsed = timestamp - self->start;
338211557Srpaulo	self->start = 0;
339211557Srpaulo	this->cpu = vtimestamp - self->vstart;
340211557Srpaulo	self->vstart = 0;
341211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
342211557Srpaulo 
343211557Srpaulo	/* print optional fields */
344211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
345211557Srpaulo	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
346211557Srpaulo	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
347211557Srpaulo	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
348211557Srpaulo 
349211557Srpaulo	/* print main data */
350211557Srpaulo	printf("%s()\t\t = %d %s%d\n", probefunc,
351211557Srpaulo	    (int)arg0, self->code, (int)errno);
352211557Srpaulo	OPT_stack ? ustack()    : 1;
353211557Srpaulo	OPT_stack ? trace("\n") : 1;
354211557Srpaulo	self->arg0 = 0;
355211557Srpaulo	self->arg1 = 0;
356211557Srpaulo	self->arg2 = 0;
357211557Srpaulo}
358211557Srpaulo
359211557Srpaulo/* print 1 arg output */
360211557Srpaulosyscall::close:return
361211557Srpaulo/self->start/
362211557Srpaulo{
363211557Srpaulo	/* calculate elapsed time */
364211557Srpaulo	this->elapsed = timestamp - self->start;
365211557Srpaulo	self->start = 0;
366211557Srpaulo	this->cpu = vtimestamp - self->vstart;
367211557Srpaulo	self->vstart = 0;
368211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
369211557Srpaulo 
370211557Srpaulo	/* print optional fields */
371211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
372211557Srpaulo	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
373211557Srpaulo	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
374211557Srpaulo	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
375211557Srpaulo 
376211557Srpaulo	/* print main data */
377211557Srpaulo	printf("%s(0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
378211557Srpaulo	    (int)arg0, self->code, (int)errno);
379211557Srpaulo	OPT_stack ? ustack()    : 1;
380211557Srpaulo	OPT_stack ? trace("\n") : 1;
381211557Srpaulo	self->arg0 = 0;
382211557Srpaulo	self->arg1 = 0;
383211557Srpaulo	self->arg2 = 0;
384211557Srpaulo}
385211557Srpaulo
386211557Srpaulo/* print 2 arg output */
387238125Semastesyscall::utimes:return,
388211557Srpaulosyscall::munmap:return
389211557Srpaulo/self->start/
390211557Srpaulo{
391211557Srpaulo	/* calculate elapsed time */
392211557Srpaulo	this->elapsed = timestamp - self->start;
393211557Srpaulo	self->start = 0;
394211557Srpaulo	this->cpu = vtimestamp - self->vstart;
395211557Srpaulo	self->vstart = 0;
396211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
397211557Srpaulo 
398211557Srpaulo	/* print optional fields */
399211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
400211557Srpaulo	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
401211557Srpaulo	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
402211557Srpaulo	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
403211557Srpaulo 
404211557Srpaulo	/* print main data */
405211557Srpaulo	printf("%s(0x%X, 0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
406211557Srpaulo	    self->arg1, (int)arg0, self->code, (int)errno);
407211557Srpaulo	OPT_stack ? ustack()    : 1;
408211557Srpaulo	OPT_stack ? trace("\n") : 1;
409211557Srpaulo	self->arg0 = 0;
410211557Srpaulo	self->arg1 = 0;
411211557Srpaulo	self->arg2 = 0;
412211557Srpaulo}
413211557Srpaulo
414211557Srpaulo/* print 3 arg output - default */
415211557Srpaulosyscall:::return
416211557Srpaulo/self->start/
417211557Srpaulo{
418211557Srpaulo	/* calculate elapsed time */
419211557Srpaulo	this->elapsed = timestamp - self->start;
420211557Srpaulo	self->start = 0;
421211557Srpaulo	this->cpu = vtimestamp - self->vstart;
422211557Srpaulo	self->vstart = 0;
423211557Srpaulo	self->code = errno == 0 ? "" : "Err#";
424211557Srpaulo 
425211557Srpaulo	/* print optional fields */
426211557Srpaulo	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
427211557Srpaulo	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
428211557Srpaulo	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
429211557Srpaulo	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
430211557Srpaulo 
431211557Srpaulo	/* print main data */
432211557Srpaulo	printf("%s(0x%X, 0x%X, 0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
433211557Srpaulo	    self->arg1, self->arg2, (int)arg0, self->code, (int)errno);
434211557Srpaulo	OPT_stack ? ustack()    : 1;
435211557Srpaulo	OPT_stack ? trace("\n") : 1;
436211557Srpaulo	self->arg0 = 0;
437211557Srpaulo	self->arg1 = 0;
438211557Srpaulo	self->arg2 = 0;
439211557Srpaulo}
440211557Srpaulo
441211557Srpaulo/* program exited */
442211557Srpauloproc:::exit
443211557Srpaulo/(OPT_command || OPT_pid) && pid == $target/
444211557Srpaulo{
445211557Srpaulo	exit(0);
446211557Srpaulo}
447211557Srpaulo
448211557Srpaulo/* print counts */
449211557Srpaulodtrace:::END
450211557Srpaulo{
451211557Srpaulo	OPT_counts == 1 ? printf("\n%-32s %16s\n", "CALL", "COUNT") : 1;
452211557Srpaulo	OPT_counts == 1 ? printa("%-32s %@16d\n", @Counts) : 1;
453211557Srpaulo}
454211557Srpaulo'
455211557Srpaulo
456211557Srpaulo### Run DTrace
457211557Srpauloif [ $opt_command -eq 1 ]; then
458211557Srpaulo	/usr/sbin/dtrace -x dynvarsize=$buf -x evaltime=exec -n "$dtrace" \
459211557Srpaulo	    -c "$command" >&2
460211557Srpauloelif [ $opt_pid -eq 1 ]; then
461211557Srpaulo	/usr/sbin/dtrace -x dynvarsize=$buf -n "$dtrace" -p "$pid" >&2
462211557Srpauloelse
463211557Srpaulo	/usr/sbin/dtrace -x dynvarsize=$buf -n "$dtrace" >&2
464211557Srpaulofi
465