1235368Sgnn#!/usr/sbin/dtrace -Zs
2/*
3 * sh_pidcolors.d - Demonstration of deeper DTrace Bourne shell analysis.
4 *                  Written for the sh DTrace provider.
5 *
6 * $Id: sh_pidcolors.d 27 2007-09-13 09:26:01Z brendan $
7 *
8 * USAGE: sh_pidcolors.d { -p PID | -c cmd }	# hit Ctrl-C to end
9 *
10 * This extends sh_syscolors.d by including some "pid" provider tracing
11 * as a starting point for deeper analysis. Currently it adds the probes,
12 *
13 *	pid$target:a.out:e*:entry,
14 *	pid$target:a.out:e*:return
15 *
16 * which means, all functions from the /usr/bin/sh binary that begin with
17 * the letter "e". This adds about 34 probes. Customise it to whichever
18 * parts of /usr/bin/sh or the system libraries you are interested in.
19 *
20 * FIELDS:
21 *		C		CPU-id
22 *		PID		Process ID
23 *		DELTA(us)	Elapsed time from previous line to this line
24 *		FILE		Filename of the shell script
25 *		LINE		Line number of filename
26 *		TYPE		Type of call (func/builtin/cmd/line/shell)
27 *		NAME		Shell function, builtin or command name
28 *
29 * The filename for syscalls may be printed as the shell name, if the
30 * script was invoked using the form "shell filename" rather than running
31 * the script with an interpreter line.
32 *
33 * WARNING: Watch the first column carefully, it prints the CPU-id. If it
34 * changes, then it is very likely that the output has been shuffled.
35 *
36 * COPYRIGHT: Copyright (c) 2007 Brendan Gregg.
37 *
38 * CDDL HEADER START
39 *
40 *  The contents of this file are subject to the terms of the
41 *  Common Development and Distribution License, Version 1.0 only
42 *  (the "License").  You may not use this file except in compliance
43 *  with the License.
44 *
45 *  You can obtain a copy of the license at Docs/cddl1.txt
46 *  or http://www.opensolaris.org/os/licensing.
47 *  See the License for the specific language governing permissions
48 *  and limitations under the License.
49 *
50 * CDDL HEADER END
51 *
52 * 09-Sep-2007	Brendan Gregg	Created this.
53 */
54
55#pragma D option quiet
56#pragma D option switchrate=10
57
58self int depth;
59
60dtrace:::BEGIN
61{
62        color_shell = "\033[2;35m";		/* violet, faint */
63        color_line = "\033[1;35m";		/* violet, bold */
64        color_lib = "\033[2;34m";		/* blue, faint */
65        color_syscall = "\033[2;32m";		/* green, faint */
66        color_off = "\033[0m";			/* default */
67
68	printf("%s %6s %10s  %16s:%-4s %-8s -- %s\n", "C", "PID", "DELTA(us)",
69	    "FILE", "LINE", "TYPE", "NAME");
70}
71
72sh$target:::function-entry,
73sh$target:::function-return,
74sh$target:::builtin-entry,
75sh$target:::command-entry,
76syscall:::entry,
77syscall:::return,
78/* Customize Here, */
79pid$target:a.out:e*:entry,
80pid$target:a.out:e*:return
81/self->last == 0 && pid == $target/
82{
83	self->last = timestamp;
84}
85
86sh$target:::function-entry
87{
88	this->delta = (timestamp - self->last) / 1000;
89	printf("%s%d %6d %10d  %16s:%-4d %-8s %*s-> %s%s\n", color_shell,
90	    cpu, pid, this->delta, basename(copyinstr(arg0)), arg2, "func",
91	    self->depth * 2, "", copyinstr(arg1), color_off);
92	self->depth++;
93	self->last = timestamp;
94}
95
96sh$target:::function-return
97{
98	this->delta = (timestamp - self->last) / 1000;
99	self->depth -= self->depth > 0 ? 1 : 0;
100	printf("%s%d %6d %10d  %16s:-    %-8s %*s<- %s%s\n", color_shell,
101	    cpu, pid, this->delta, basename(copyinstr(arg0)), "func",
102	    self->depth * 2, "", copyinstr(arg1), color_off);
103	self->last = timestamp;
104}
105
106sh$target:::builtin-entry
107{
108	this->delta = (timestamp - self->last) / 1000;
109	printf("%s%d %6d %10d  %16s:%-4d %-8s %*s-> %s%s\n", color_shell,
110	    cpu, pid, this->delta, basename(copyinstr(arg0)), arg2, "builtin",
111	    self->depth * 2, "", copyinstr(arg1), color_off);
112	self->depth++;
113	self->last = timestamp;
114}
115
116sh$target:::builtin-return
117{
118	this->delta = (timestamp - self->last) / 1000;
119	self->depth -= self->depth > 0 ? 1 : 0;
120	printf("%s%d %6d %10d  %16s:%-4d %-8s %*s<- %s%s\n", color_shell,
121	    cpu, pid, this->delta, basename(copyinstr(arg0)), arg2, "builtin",
122	    self->depth * 2, "", copyinstr(arg1), color_off);
123	self->last = timestamp;
124}
125
126sh$target:::command-entry
127{
128	this->delta = (timestamp - self->last) / 1000;
129	printf("%s%d %6d %10d  %16s:%-4d %-8s %*s-> %s%s\n", color_shell,
130	    cpu, pid, this->delta, basename(copyinstr(arg0)), arg2, "cmd",
131	    self->depth * 2, "", copyinstr(arg1), color_off);
132	self->depth++;
133	self->last = timestamp;
134}
135
136sh$target:::command-return
137{
138	this->delta = (timestamp - self->last) / 1000;
139	self->depth -= self->depth > 0 ? 1 : 0;
140	printf("%s%d %6d %10d  %16s:%-4d %-8s %*s<- %s%s\n", color_shell,
141	    cpu, pid, this->delta, basename(copyinstr(arg0)), arg2, "cmd",
142	    self->depth * 2, "", copyinstr(arg1), color_off);
143	self->last = timestamp;
144}
145
146sh$target:::line
147{
148	this->delta = (timestamp - self->last) / 1000;
149	printf("%s%d %6d %10d  %16s:%-4d %-8s %*s-- %s\n", color_line,
150	    cpu, pid, this->delta, basename(copyinstr(arg0)), arg1, "line",
151	    self->depth * 2, "", color_off);
152	self->last = timestamp;
153}
154
155/* Customise Here, */
156pid$target:a.out:e*:entry
157{
158	this->delta = (timestamp - self->last) / 1000;
159	printf("%s%d %6d %10d  %16s:-    %-8s %*s-> %s%s\n", color_lib,
160	    cpu, pid, this->delta, basename(execname), "sh",
161	    self->depth * 2, "", probefunc, color_off);
162	self->depth++;
163	self->last = timestamp;
164}
165
166/* Customise Here, */
167pid$target:a.out:e*:return
168{
169	this->delta = (timestamp - self->last) / 1000;
170	self->depth -= self->depth > 0 ? 1 : 0;
171	printf("%s%d %6d %10d  %16s:-    %-8s %*s<- %s%s\n", color_lib,
172	    cpu, pid, this->delta, basename(execname), "sh",
173	    self->depth * 2, "", probefunc, color_off);
174	self->last = timestamp;
175}
176
177syscall:::entry
178/pid == $target/
179{
180	this->delta = (timestamp - self->last) / 1000;
181	printf("%s%d %6d %10d  %16s:-    %-8s %*s-> %s%s\n", color_syscall,
182	    cpu, pid, this->delta, basename(execname), "syscall",
183	    self->depth * 2, "", probefunc, color_off);
184	self->depth++;
185	self->last = timestamp;
186}
187
188syscall:::return
189/pid == $target/
190{
191	this->delta = (timestamp - self->last) / 1000;
192	self->depth -= self->depth > 0 ? 1 : 0;
193	printf("%s%d %6d %10d  %16s:-    %-8s %*s<- %s%s\n", color_syscall,
194	    cpu, pid, this->delta, basename(execname), "syscall",
195	    self->depth * 2, "", probefunc, color_off);
196	self->last = timestamp;
197}
198
199proc:::exit
200/pid == $target/
201{
202	exit(0);
203}
204