Fix .stp permissions.
[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 global opt_f
19 global opt_q
20
21 global trace
22 # FIXME: count()?
23 global trace_count
24 global last_tid
25 probe begin
26 {
27   trace[target ()] = 1
28   trace_count = 1
29   last_tid = target ()
30 }
31
32 function heading:string ()
33 {
34   if (trace_count > 1)
35     {
36       /* strace really calls TID a "pid".  */
37       return sprintf ("[pid %5d] ", tid ())
38     }
39   else
40     return ""
41 }
42
43 global namea
44
45 function destroy (tid:long)
46 {
47   delete namea[tid]
48 }
49
50 function lhs:string (tid:long)
51 {
52   return namea[tid]
53 }
54 probe end
55 {
56   foreach (tid in namea)
57     printf ("%s = ? <tracer terminated>\n", lhs (tid))
58 }
59
60 /* BUG: sleeping function called from invalid context at kernel/mutex.c:94
61 %{static DEFINE_MUTEX (tracer_mutex);%}
62 function lock ()
63 %{
64   mutex_lock (&tracer_mutex);
65 %}
66 function unlock ()
67 %{
68   mutex_unlock (&tracer_mutex);
69 %}
70 */
71 global dummy
72 function lock () { dummy = 1; }
73 function unlock () { dummy = 1; }
74
75 #probe kprocess.start
76 #{
77 #  trace[pid ()] = 1
78 #  trace_count++
79 #}
80 #probe kprocess.exit
81 #{
82 #  trace[pid ()] = 0
83 #  trace_count--
84 #}
85 probe kprocess.create
86 {
87   if (opt_f && trace[tid ()] != 0)
88     {
89       /* systemtap bug?  Why `new_pid' is provided but `new_tid' is not?  */
90       new_tid = task_tid (task)
91       trace[new_tid] = 1
92       trace_count++
93       if (!opt_q)
94         printf ("Process %d attached\n", new_tid);
95     }
96 }
97
98 probe kprocess.release
99 {
100   /* systemtap bug?  Why `pid' is provided but `tid' is not?  */
101   /* systemtap bug?  Why `[pt]id' is not called `released_[pt]id' to keep the
102      naming in sync with kprocess.create?  */
103   tid = task_tid (task)
104   if (trace[tid] != 0)
105     {
106       if (namea[tid] != "")
107         {
108           printf ("%s = ?\n", lhs (tid))
109           destroy (tid)
110         }
111 # FIXME
112       else if (0)
113         {
114           /* systemtap bug?  exit_group(2) systemtap calls "exit" and _exit(2)
115              is not caught at all.  */
116           lock ()
117           if (last_tid != tid () && namea[last_tid] != "")
118             printf (" <unfinished ...>\n")
119           last_tid = tid
120           printf ("%s_exit(?) = ?\n", heading ())
121           unlock ()
122         }
123       delete trace[tid]
124       trace_count--
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 }