fixes
[staptrace.git] / src / staptrace.stp
1 #! /usr/bin/stap
2
3 # Copyright (C) 2010 Free Software Foundation, Inc.
4
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 # ` = 0' is there to prevent: WARNING: never-assigned global variable
19 global opt_f = 0
20 global opt_q = 0
21
22 /* systemtap bug?  /usr/share/doc/systemtap-1.3/SystemTap_Beginners_Guide.pdf
23    Example 3.19 reads or writes?  */
24
25 global trace
26 global last_tid
27 probe begin
28 {
29   trace[target ()] = 1
30   last_tid = target ()
31 }
32
33 function heading:string ()
34 {
35   foreach (tidi in trace limit 2)
36     tid_count++
37
38   if (tid_count > 1)
39     {
40       /* strace really calls TID a "pid".  */
41       return sprintf ("[pid %5d] ", tid ())
42     }
43   else
44     return ""
45 }
46
47 global namea
48
49 function destroy (tid:long)
50 {
51   delete namea[tid]
52 }
53
54 function lhs:string (tid:long)
55 {
56   return namea[tid]
57 }
58 probe end
59 {
60   foreach (tid in namea)
61     printf ("%s = ? <tracer terminated>\n", lhs (tid))
62 }
63
64 /* BUG: sleeping function called from invalid context at kernel/mutex.c:94
65 %{static DEFINE_MUTEX (tracer_mutex);%}
66 function lock ()
67 %{
68   mutex_lock (&tracer_mutex);
69 %}
70 function unlock ()
71 %{
72   mutex_unlock (&tracer_mutex);
73 %}
74 */
75 global dummy
76 function lock () { dummy = 1; }
77 function unlock () { dummy = 1; }
78
79 #probe kprocess.start
80 #{
81 #  trace[pid ()] = 1
82 #}
83 #probe kprocess.exit
84 #{
85 #  trace[pid ()] = 0
86 #}
87 probe kprocess.create
88 {
89   if (opt_f && trace[tid ()] != 0)
90     {
91       /* systemtap bug?  Why `new_pid' is provided but `new_tid' is not?  */
92       new_tid = task_tid (task)
93       trace[new_tid] = 1
94       if (!opt_q)
95         printf ("Process %d attached\n", new_tid);
96     }
97 }
98
99 probe kprocess.release
100 {
101   /* systemtap bug?  Why `pid' is provided but `tid' is not?  */
102   /* systemtap bug?  Why `[pt]id' is not called `released_[pt]id' to keep the
103      naming in sync with kprocess.create?  */
104   tid = task_tid (task)
105   if (trace[tid] != 0)
106     {
107       if (namea[tid] != "")
108         {
109           printf ("%s = ?\n", lhs (tid))
110           destroy (tid)
111         }
112 # FIXME
113       else if (0)
114         {
115           /* systemtap bug?  exit_group(2) systemtap calls "exit" and _exit(2)
116              is not caught at all.  */
117           lock ()
118           if (last_tid != tid () && namea[last_tid] != "")
119             printf (" <unfinished ...>\n")
120           last_tid = tid
121           printf ("%s_exit(?) = ?\n", heading ())
122           unlock ()
123         }
124       delete trace[tid]
125       if (!opt_q)
126         printf ("Process %d detached\n", tid);
127     }
128 }
129 probe syscall.*
130 {
131   if (trace[tid ()] != 0)
132     {
133       lock ()
134       /* Why is mmap() called recursively twice?  */
135       if (namea[last_tid] != "")
136         printf (" <unfinished ...>\n")
137       last_tid = tid ();
138       namea[tid ()] = name
139       printf ("%s%s(%s", heading (), name, argstr)
140       unlock ()
141     }
142 }
143 probe syscall.*.return
144 {
145   if (trace[tid ()] != 0)
146     {
147       lock ()
148       if (last_tid != tid () && namea[last_tid] != "")
149         printf (" <unfinished ...>\n")
150       if ((last_tid != tid () && namea[last_tid] != "")
151           || (last_tid == tid () && namea[last_tid] == ""))
152         printf ("%s<... %s resumed> ", heading (), name);
153       last_tid = tid ();
154       printf (") = %s\n", retstr)
155       destroy (tid ())
156       unlock ()
157     }
158 }