Home | History | Annotate | Line # | Download | only in Bin
dtruss revision 1.1
      1  1.1  christos #!/bin/sh
      2  1.1  christos #
      3  1.1  christos # dtruss - print process system call time details.
      4  1.1  christos #          Written using DTrace (Solaris 10 3/05).
      5  1.1  christos #
      6  1.1  christos # $Id: dtruss,v 1.1 2015/09/30 22:01:07 christos Exp $
      7  1.1  christos #
      8  1.1  christos # USAGE: dtruss [-acdeflhoLs] [-t syscall] { -p PID | -n name | command }
      9  1.1  christos #
     10  1.1  christos #		-p PID		# examine this PID
     11  1.1  christos #		-n name		# examine this process name
     12  1.1  christos #		-t syscall	# examine this syscall only
     13  1.1  christos #		-a		# print all details
     14  1.1  christos #		-c		# print system call counts
     15  1.1  christos #		-d		# print relative timestamps (us)
     16  1.1  christos #		-e		# print elapsed times (us)
     17  1.1  christos #		-f		# follow children as they are forked
     18  1.1  christos #		-l		# force printing of pid/lwpid per line
     19  1.1  christos #		-o		# print on cpu times (us)
     20  1.1  christos #		-s		# print stack backtraces
     21  1.1  christos #		-L		# don't print pid/lwpid per line
     22  1.1  christos #		-b bufsize	# dynamic variable buf size (default is "4m")
     23  1.1  christos #  eg,
     24  1.1  christos #		dtruss df -h	# run and examine the "df -h" command
     25  1.1  christos #		dtruss -p 1871	# examine PID 1871
     26  1.1  christos #		dtruss -n tar	# examine all processes called "tar"
     27  1.1  christos #		dtruss -f test.sh	# run test.sh and follow children
     28  1.1  christos #
     29  1.1  christos # See the man page dtruss(1M) for further details.
     30  1.1  christos #
     31  1.1  christos # SEE ALSO: procsystime    # DTraceToolkit
     32  1.1  christos #           dapptrace      # DTraceToolkit
     33  1.1  christos #           truss
     34  1.1  christos #
     35  1.1  christos # COPYRIGHT: Copyright (c) 2005, 2006, 2007 Brendan Gregg.
     36  1.1  christos #
     37  1.1  christos # CDDL HEADER START
     38  1.1  christos #
     39  1.1  christos #  The contents of this file are subject to the terms of the
     40  1.1  christos #  Common Development and Distribution License, Version 1.0 only
     41  1.1  christos #  (the "License").  You may not use this file except in compliance
     42  1.1  christos #  with the License.
     43  1.1  christos #
     44  1.1  christos #  You can obtain a copy of the license at Docs/cddl1.txt
     45  1.1  christos #  or http://www.opensolaris.org/os/licensing.
     46  1.1  christos #  See the License for the specific language governing permissions
     47  1.1  christos #  and limitations under the License.
     48  1.1  christos #
     49  1.1  christos # CDDL HEADER END
     50  1.1  christos #
     51  1.1  christos # TODO: Track signals, more output formatting.
     52  1.1  christos #
     53  1.1  christos # 29-Apr-2005   Brendan Gregg   Created this.
     54  1.1  christos # 09-May-2005      "      " 	Fixed evaltime (thanks Adam L.)
     55  1.1  christos # 16-May-2005	   "      "	Added -t syscall tracing.
     56  1.1  christos # 17-Jun-2005	   "      "	Added -s stack backtraces.
     57  1.1  christos # 17-Jun-2005	   "      "	Last update.
     58  1.1  christos # 29-Jun-2007	   "      "	Used progenyof() (thanks Aaron Gutman).
     59  1.1  christos # 06-Aug-2007	   "      "	Various updates.
     60  1.1  christos #
     61  1.1  christos 
     62  1.1  christos 
     63  1.1  christos ##############################
     64  1.1  christos # --- Process Arguments ---
     65  1.1  christos #
     66  1.1  christos 
     67  1.1  christos ### Default variables
     68  1.1  christos opt_pid=0; opt_name=0; pid=0; pname="."; opt_elapsed=0; opt_cpu=0
     69  1.1  christos opt_counts=0; opt_relative=0; opt_printid=0; opt_follow=0; opt_command=0
     70  1.1  christos command=""; opt_buf=0; buf="4m"; opt_trace=0; trace="."; opt_stack=0
     71  1.1  christos 
     72  1.1  christos ### Process options
     73  1.1  christos while getopts ab:cdefhln:op:st:L name
     74  1.1  christos do
     75  1.1  christos         case $name in
     76  1.1  christos 	b)	opt_buf=1; buf=$OPTARG ;;
     77  1.1  christos         p)      opt_pid=1; pid=$OPTARG ;;
     78  1.1  christos         n)      opt_name=1; pname=$OPTARG ;;
     79  1.1  christos         t)      opt_trace=1; trace=$OPTARG ;;
     80  1.1  christos 	a)	opt_counts=1; opt_relative=1; opt_elapsed=1; opt_follow=1
     81  1.1  christos 		opt_printid=1; opt_cpu=1 ;;
     82  1.1  christos 	c)	opt_counts=1 ;;
     83  1.1  christos 	d)	opt_relative=1 ;;
     84  1.1  christos 	e)	opt_elapsed=1 ;;
     85  1.1  christos 	f)	opt_follow=1 ;;
     86  1.1  christos 	l)	opt_printid=1 ;;
     87  1.1  christos 	o)	opt_cpu=1 ;;
     88  1.1  christos 	L)	opt_printid=-1 ;;
     89  1.1  christos 	s)	opt_stack=-1 ;;
     90  1.1  christos         h|?)    cat <<-END >&2
     91  1.1  christos 		USAGE: dtruss [-acdefholLs] [-t syscall] { -p PID | -n name | command }
     92  1.1  christos 
     93  1.1  christos 		          -p PID          # examine this PID
     94  1.1  christos 		          -n name         # examine this process name
     95  1.1  christos 		          -t syscall      # examine this syscall only
     96  1.1  christos 		          -a              # print all details
     97  1.1  christos 		          -c              # print syscall counts
     98  1.1  christos 		          -d              # print relative times (us)
     99  1.1  christos 		          -e              # print elapsed times (us)
    100  1.1  christos 		          -f              # follow children (-p or cmd only)
    101  1.1  christos 		          -l              # force printing pid/lwpid
    102  1.1  christos 		          -o              # print on cpu times
    103  1.1  christos 		          -s              # print stack backtraces
    104  1.1  christos 		          -L              # don't print pid/lwpid
    105  1.1  christos 		          -b bufsize      # dynamic variable buf size
    106  1.1  christos 		   eg,
    107  1.1  christos 		       dtruss df -h       # run and examine "df -h"
    108  1.1  christos 		       dtruss -p 1871     # examine PID 1871
    109  1.1  christos 		       dtruss -n tar      # examine all processes called "tar"
    110  1.1  christos 		       dtruss -f test.sh  # run test.sh and follow children
    111  1.1  christos 		END
    112  1.1  christos 		exit 1
    113  1.1  christos         esac
    114  1.1  christos done
    115  1.1  christos shift `expr $OPTIND - 1`
    116  1.1  christos 
    117  1.1  christos ### Option logic
    118  1.1  christos if [ $opt_pid -eq 0 -a $opt_name -eq 0 ]; then
    119  1.1  christos 	opt_command=1
    120  1.1  christos 	if [ "$*" = "" ]; then
    121  1.1  christos 		$0 -h
    122  1.1  christos 		exit
    123  1.1  christos 	fi
    124  1.1  christos 	command="$*"	# yes, I meant $*!
    125  1.1  christos fi
    126  1.1  christos if [ $opt_follow -eq 1 -o $opt_name -eq 1 ]; then
    127  1.1  christos 	if [ $opt_printid -ne -1 ]; then
    128  1.1  christos 		opt_printid=1
    129  1.1  christos 	else
    130  1.1  christos 		opt_printid=0
    131  1.1  christos 	fi
    132  1.1  christos fi
    133  1.1  christos if [ $opt_follow -eq 1 -a $opt_name -eq 1 ]; then
    134  1.1  christos 	echo "ERROR: -f option cannot be used with -n (use -p or cmd instead)."
    135  1.1  christos 	exit 1
    136  1.1  christos fi
    137  1.1  christos 
    138  1.1  christos ### Option translation
    139  1.1  christos if [ "$trace" = "exec" ]; then trace="exece"; fi
    140  1.1  christos if [ "$trace" = "time" ]; then trace="gtime"; fi
    141  1.1  christos if [ "$trace" = "exit" ]; then trace="rexit"; fi
    142  1.1  christos 
    143  1.1  christos 
    144  1.1  christos #################################
    145  1.1  christos # --- Main Program, DTrace ---
    146  1.1  christos #
    147  1.1  christos 
    148  1.1  christos ### Define D Script
    149  1.1  christos dtrace='
    150  1.1  christos #pragma D option quiet
    151  1.1  christos #pragma D option switchrate=10
    152  1.1  christos  
    153  1.1  christos /*
    154  1.1  christos  * Command line arguments
    155  1.1  christos  */
    156  1.1  christos inline int OPT_command   = '$opt_command';
    157  1.1  christos inline int OPT_follow    = '$opt_follow';
    158  1.1  christos inline int OPT_printid   = '$opt_printid';
    159  1.1  christos inline int OPT_relative  = '$opt_relative';
    160  1.1  christos inline int OPT_elapsed   = '$opt_elapsed';
    161  1.1  christos inline int OPT_cpu       = '$opt_cpu';
    162  1.1  christos inline int OPT_counts    = '$opt_counts';
    163  1.1  christos inline int OPT_pid       = '$opt_pid';
    164  1.1  christos inline int OPT_name      = '$opt_name';
    165  1.1  christos inline int OPT_trace     = '$opt_trace';
    166  1.1  christos inline int OPT_stack     = '$opt_stack';
    167  1.1  christos inline string NAME       = "'$pname'";
    168  1.1  christos inline string TRACE      = "'$trace'";
    169  1.1  christos 
    170  1.1  christos dtrace:::BEGIN 
    171  1.1  christos {
    172  1.1  christos 	/* print header */
    173  1.1  christos 	OPT_printid  ? printf("%-9s  ", "PID/LWP") : 1;
    174  1.1  christos 	OPT_relative ? printf("%8s ", "RELATIVE") : 1;
    175  1.1  christos 	OPT_elapsed  ? printf("%7s ", "ELAPSD") : 1;
    176  1.1  christos 	OPT_cpu      ? printf("%6s ", "CPU") : 1;
    177  1.1  christos 	printf("SYSCALL(args) \t\t = return\n");
    178  1.1  christos }
    179  1.1  christos 
    180  1.1  christos /*
    181  1.1  christos  * Save syscall entry info
    182  1.1  christos  */
    183  1.1  christos syscall:::entry
    184  1.1  christos /((OPT_command || OPT_pid) && pid == $target) || 
    185  1.1  christos  (OPT_name && execname == NAME) ||
    186  1.1  christos  (OPT_follow && progenyof($target))/
    187  1.1  christos {
    188  1.1  christos 	/* set start details */
    189  1.1  christos 	self->start = timestamp;
    190  1.1  christos 	self->vstart = vtimestamp;
    191  1.1  christos 	self->arg0 = arg0;
    192  1.1  christos 	self->arg1 = arg1;
    193  1.1  christos 	self->arg2 = arg2;
    194  1.1  christos 
    195  1.1  christos 	/* count occurances */
    196  1.1  christos 	OPT_counts == 1 ? @Counts[probefunc] = count() : 1;
    197  1.1  christos }
    198  1.1  christos 
    199  1.1  christos /*
    200  1.1  christos  * Follow children
    201  1.1  christos  */
    202  1.1  christos syscall::fork*:return
    203  1.1  christos /(OPT_follow && progenyof($target)) && (!OPT_trace || (TRACE == probefunc))/
    204  1.1  christos {
    205  1.1  christos 	/* print output */
    206  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    207  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    208  1.1  christos 	OPT_relative ? printf("%8d:  ", vtimestamp/1000) : 1;
    209  1.1  christos 	OPT_elapsed  ? printf("%7d:  ", 0) : 1;
    210  1.1  christos 	OPT_cpu      ? printf("%6d ", 0) : 1;
    211  1.1  christos 	printf("%s(0x%X, 0x%X, 0x%X)\t\t = %d %s%d\n", probefunc,
    212  1.1  christos 	    self->arg0, self->arg1, self->arg2, (int)arg0, self->code,
    213  1.1  christos 	    (int)errno);
    214  1.1  christos }
    215  1.1  christos 
    216  1.1  christos /*
    217  1.1  christos  * Check for syscall tracing
    218  1.1  christos  */
    219  1.1  christos syscall:::entry
    220  1.1  christos /OPT_trace && probefunc != TRACE/
    221  1.1  christos {
    222  1.1  christos 	/* drop info */
    223  1.1  christos 	self->start = 0;
    224  1.1  christos 	self->vstart = 0;
    225  1.1  christos 	self->arg0 = 0;
    226  1.1  christos 	self->arg1 = 0;
    227  1.1  christos 	self->arg2 = 0;
    228  1.1  christos }
    229  1.1  christos 
    230  1.1  christos /*
    231  1.1  christos  * Print return data
    232  1.1  christos  */
    233  1.1  christos 
    234  1.1  christos /*
    235  1.1  christos  * The following code is written in an intentionally repetative way.
    236  1.1  christos  * The first versions had no code redundancies, but performed badly during
    237  1.1  christos  * benchmarking. The priority here is speed, not cleverness. I know there
    238  1.1  christos  * are many obvious shortcuts to this code, I have tried them. This style has
    239  1.1  christos  * shown in benchmarks to be the fastest (fewest probes fired, fewest actions).
    240  1.1  christos  */
    241  1.1  christos 
    242  1.1  christos /* print 3 args, return as hex */
    243  1.1  christos syscall::sigprocmask:return
    244  1.1  christos /self->start/
    245  1.1  christos {
    246  1.1  christos 	/* calculate elapsed time */
    247  1.1  christos 	this->elapsed = timestamp - self->start;
    248  1.1  christos 	self->start = 0;
    249  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    250  1.1  christos 	self->vstart = 0;
    251  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    252  1.1  christos  
    253  1.1  christos 	/* print optional fields */
    254  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    255  1.1  christos 	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
    256  1.1  christos 	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
    257  1.1  christos 	OPT_cpu ? printf("%6d ", this->cpu/1000) : 1;
    258  1.1  christos  
    259  1.1  christos 	/* print main data */
    260  1.1  christos 	printf("%s(0x%X, 0x%X, 0x%X)\t\t = 0x%X %s%d\n", probefunc,
    261  1.1  christos 	    (int)self->arg0, self->arg1, self->arg2, (int)arg0,
    262  1.1  christos 	    self->code, (int)errno);
    263  1.1  christos 	OPT_stack ? ustack()    : 1;
    264  1.1  christos 	OPT_stack ? trace("\n") : 1;
    265  1.1  christos 	self->arg0 = 0;
    266  1.1  christos 	self->arg1 = 0;
    267  1.1  christos 	self->arg2 = 0;
    268  1.1  christos }
    269  1.1  christos 
    270  1.1  christos /* print 3 args, arg0 as a string */
    271  1.1  christos syscall::access*:return,
    272  1.1  christos syscall::stat*:return, 
    273  1.1  christos syscall::lstat*:return, 
    274  1.1  christos syscall::readlink*:return,
    275  1.1  christos syscall::open*:return
    276  1.1  christos /self->start/
    277  1.1  christos {
    278  1.1  christos 	/* calculate elapsed time */
    279  1.1  christos 	this->elapsed = timestamp - self->start;
    280  1.1  christos 	self->start = 0;
    281  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    282  1.1  christos 	self->vstart = 0;
    283  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    284  1.1  christos  
    285  1.1  christos 	/* print optional fields */
    286  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    287  1.1  christos 	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
    288  1.1  christos 	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
    289  1.1  christos 	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
    290  1.1  christos  
    291  1.1  christos 	/* print main data */
    292  1.1  christos 	printf("%s(\"%S\", 0x%X, 0x%X)\t\t = %d %s%d\n", probefunc,
    293  1.1  christos 	    copyinstr(self->arg0), self->arg1, self->arg2, (int)arg0,
    294  1.1  christos 	    self->code, (int)errno);
    295  1.1  christos 	OPT_stack ? ustack()    : 1;
    296  1.1  christos 	OPT_stack ? trace("\n") : 1;
    297  1.1  christos 	self->arg0 = 0;
    298  1.1  christos 	self->arg1 = 0;
    299  1.1  christos 	self->arg2 = 0;
    300  1.1  christos }
    301  1.1  christos 
    302  1.1  christos /* print 3 args, arg1 as a string */
    303  1.1  christos syscall::write:return,
    304  1.1  christos syscall::pwrite:return,
    305  1.1  christos syscall::*read*:return
    306  1.1  christos /self->start/
    307  1.1  christos {
    308  1.1  christos 	/* calculate elapsed time */
    309  1.1  christos 	this->elapsed = timestamp - self->start;
    310  1.1  christos 	self->start = 0;
    311  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    312  1.1  christos 	self->vstart = 0;
    313  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    314  1.1  christos  
    315  1.1  christos 	/* print optional fields */
    316  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    317  1.1  christos 	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
    318  1.1  christos 	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
    319  1.1  christos 	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
    320  1.1  christos  
    321  1.1  christos 	/* print main data */
    322  1.1  christos 	printf("%s(0x%X, \"%S\", 0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
    323  1.1  christos 	    stringof(copyin(self->arg1, self->arg2)), self->arg2, (int)arg0,
    324  1.1  christos 	    self->code, (int)errno);
    325  1.1  christos 	OPT_stack ? ustack()    : 1;
    326  1.1  christos 	OPT_stack ? trace("\n") : 1;
    327  1.1  christos 	self->arg0 = 0;
    328  1.1  christos 	self->arg1 = 0;
    329  1.1  christos 	self->arg2 = 0;
    330  1.1  christos }
    331  1.1  christos 
    332  1.1  christos /* print 0 arg output */
    333  1.1  christos syscall::*fork*:return
    334  1.1  christos /self->start/
    335  1.1  christos {
    336  1.1  christos 	/* calculate elapsed time */
    337  1.1  christos 	this->elapsed = timestamp - self->start;
    338  1.1  christos 	self->start = 0;
    339  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    340  1.1  christos 	self->vstart = 0;
    341  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    342  1.1  christos  
    343  1.1  christos 	/* print optional fields */
    344  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    345  1.1  christos 	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
    346  1.1  christos 	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
    347  1.1  christos 	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
    348  1.1  christos  
    349  1.1  christos 	/* print main data */
    350  1.1  christos 	printf("%s()\t\t = %d %s%d\n", probefunc,
    351  1.1  christos 	    (int)arg0, self->code, (int)errno);
    352  1.1  christos 	OPT_stack ? ustack()    : 1;
    353  1.1  christos 	OPT_stack ? trace("\n") : 1;
    354  1.1  christos 	self->arg0 = 0;
    355  1.1  christos 	self->arg1 = 0;
    356  1.1  christos 	self->arg2 = 0;
    357  1.1  christos }
    358  1.1  christos 
    359  1.1  christos /* print 1 arg output */
    360  1.1  christos syscall::close:return
    361  1.1  christos /self->start/
    362  1.1  christos {
    363  1.1  christos 	/* calculate elapsed time */
    364  1.1  christos 	this->elapsed = timestamp - self->start;
    365  1.1  christos 	self->start = 0;
    366  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    367  1.1  christos 	self->vstart = 0;
    368  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    369  1.1  christos  
    370  1.1  christos 	/* print optional fields */
    371  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    372  1.1  christos 	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
    373  1.1  christos 	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
    374  1.1  christos 	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
    375  1.1  christos  
    376  1.1  christos 	/* print main data */
    377  1.1  christos 	printf("%s(0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
    378  1.1  christos 	    (int)arg0, self->code, (int)errno);
    379  1.1  christos 	OPT_stack ? ustack()    : 1;
    380  1.1  christos 	OPT_stack ? trace("\n") : 1;
    381  1.1  christos 	self->arg0 = 0;
    382  1.1  christos 	self->arg1 = 0;
    383  1.1  christos 	self->arg2 = 0;
    384  1.1  christos }
    385  1.1  christos 
    386  1.1  christos /* print 2 arg output */
    387  1.1  christos syscall::utimes:return,
    388  1.1  christos syscall::munmap:return
    389  1.1  christos /self->start/
    390  1.1  christos {
    391  1.1  christos 	/* calculate elapsed time */
    392  1.1  christos 	this->elapsed = timestamp - self->start;
    393  1.1  christos 	self->start = 0;
    394  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    395  1.1  christos 	self->vstart = 0;
    396  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    397  1.1  christos  
    398  1.1  christos 	/* print optional fields */
    399  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    400  1.1  christos 	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
    401  1.1  christos 	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
    402  1.1  christos 	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
    403  1.1  christos  
    404  1.1  christos 	/* print main data */
    405  1.1  christos 	printf("%s(0x%X, 0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
    406  1.1  christos 	    self->arg1, (int)arg0, self->code, (int)errno);
    407  1.1  christos 	OPT_stack ? ustack()    : 1;
    408  1.1  christos 	OPT_stack ? trace("\n") : 1;
    409  1.1  christos 	self->arg0 = 0;
    410  1.1  christos 	self->arg1 = 0;
    411  1.1  christos 	self->arg2 = 0;
    412  1.1  christos }
    413  1.1  christos 
    414  1.1  christos /* print 3 arg output - default */
    415  1.1  christos syscall:::return
    416  1.1  christos /self->start/
    417  1.1  christos {
    418  1.1  christos 	/* calculate elapsed time */
    419  1.1  christos 	this->elapsed = timestamp - self->start;
    420  1.1  christos 	self->start = 0;
    421  1.1  christos 	this->cpu = vtimestamp - self->vstart;
    422  1.1  christos 	self->vstart = 0;
    423  1.1  christos 	self->code = errno == 0 ? "" : "Err#";
    424  1.1  christos  
    425  1.1  christos 	/* print optional fields */
    426  1.1  christos 	OPT_printid  ? printf("%6d/%d:  ", pid, tid) : 1;
    427  1.1  christos 	OPT_relative ? printf("%8d ", vtimestamp/1000) : 1;
    428  1.1  christos 	OPT_elapsed  ? printf("%7d ", this->elapsed/1000) : 1;
    429  1.1  christos 	OPT_cpu      ? printf("%6d ", this->cpu/1000) : 1;
    430  1.1  christos  
    431  1.1  christos 	/* print main data */
    432  1.1  christos 	printf("%s(0x%X, 0x%X, 0x%X)\t\t = %d %s%d\n", probefunc, self->arg0,
    433  1.1  christos 	    self->arg1, self->arg2, (int)arg0, self->code, (int)errno);
    434  1.1  christos 	OPT_stack ? ustack()    : 1;
    435  1.1  christos 	OPT_stack ? trace("\n") : 1;
    436  1.1  christos 	self->arg0 = 0;
    437  1.1  christos 	self->arg1 = 0;
    438  1.1  christos 	self->arg2 = 0;
    439  1.1  christos }
    440  1.1  christos 
    441  1.1  christos /* program exited */
    442  1.1  christos proc:::exit
    443  1.1  christos /(OPT_command || OPT_pid) && pid == $target/
    444  1.1  christos {
    445  1.1  christos 	exit(0);
    446  1.1  christos }
    447  1.1  christos 
    448  1.1  christos /* print counts */
    449  1.1  christos dtrace:::END
    450  1.1  christos {
    451  1.1  christos 	OPT_counts == 1 ? printf("\n%-32s %16s\n", "CALL", "COUNT") : 1;
    452  1.1  christos 	OPT_counts == 1 ? printa("%-32s %@16d\n", @Counts) : 1;
    453  1.1  christos }
    454  1.1  christos '
    455  1.1  christos 
    456  1.1  christos ### Run DTrace
    457  1.1  christos if [ $opt_command -eq 1 ]; then
    458  1.1  christos 	/usr/sbin/dtrace -x dynvarsize=$buf -x evaltime=exec -n "$dtrace" \
    459  1.1  christos 	    -c "$command" >&2
    460  1.1  christos elif [ $opt_pid -eq 1 ]; then
    461  1.1  christos 	/usr/sbin/dtrace -x dynvarsize=$buf -n "$dtrace" -p "$pid" >&2
    462  1.1  christos else
    463  1.1  christos 	/usr/sbin/dtrace -x dynvarsize=$buf -n "$dtrace" >&2
    464  1.1  christos fi
    465