#! /usr/bin/stap
#
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
global opt_f
global opt_q
global trace
# FIXME: count()?
global trace_count
global last_tid
probe begin
{
trace[target ()] = 1
trace_count = 1
last_tid = target ()
}
function heading:string ()
{
if (trace_count > 1)
{
/* strace really calls TID a "pid". */
return sprintf ("[pid %5d] ", tid ())
}
else
return ""
}
global namea
function destroy (tid:long)
{
delete namea[tid]
}
function lhs:string (tid:long)
{
return namea[tid]
}
probe end
{
foreach (tid in namea)
printf ("%s = ? \n", lhs (tid))
}
/* BUG: sleeping function called from invalid context at kernel/mutex.c:94
%{static DEFINE_MUTEX (tracer_mutex);%}
function lock ()
%{
mutex_lock (&tracer_mutex);
%}
function unlock ()
%{
mutex_unlock (&tracer_mutex);
%}
*/
global dummy
function lock () { dummy = 1; }
function unlock () { dummy = 1; }
#probe kprocess.start
#{
# trace[pid ()] = 1
# trace_count++
#}
#probe kprocess.exit
#{
# trace[pid ()] = 0
# trace_count--
#}
probe kprocess.create
{
if (opt_f && trace[tid ()] != 0)
{
/* systemtap bug? Why `new_pid' is provided but `new_tid' is not? */
new_tid = task_tid (task)
trace[new_tid] = 1
trace_count++
if (!opt_q)
printf ("Process %d attached\n", new_tid);
}
}
probe kprocess.release
{
/* systemtap bug? Why `pid' is provided but `tid' is not? */
/* systemtap bug? Why `[pt]id' is not called `released_[pt]id' to keep the
naming in sync with kprocess.create? */
tid = task_tid (task)
if (trace[tid] != 0)
{
if (namea[tid] != "")
{
printf ("%s = ?\n", lhs (tid))
destroy (tid)
}
# FIXME
else if (0)
{
/* systemtap bug? exit_group(2) systemtap calls "exit" and _exit(2)
is not caught at all. */
lock ()
if (last_tid != tid () && namea[last_tid] != "")
printf (" \n")
last_tid = tid
printf ("%s_exit(?) = ?\n", heading ())
unlock ()
}
delete trace[tid]
trace_count--
if (!opt_q)
printf ("Process %d detached\n", tid);
}
}
probe syscall.*
{
if (trace[tid ()] != 0)
{
lock ()
/* Why is mmap() called recursively twice? */
if (namea[last_tid] != "")
printf (" \n")
last_tid = tid ();
namea[tid ()] = name
printf ("%s%s(%s", heading (), name, argstr)
unlock ()
}
}
probe syscall.*.return
{
if (trace[tid ()] != 0)
{
lock ()
if (last_tid != tid () && namea[last_tid] != "")
printf (" \n")
if ((last_tid != tid () && namea[last_tid] != "")
|| (last_tid == tid () && namea[last_tid] == ""))
printf ("%s<... %s resumed> ", heading (), name);
last_tid = tid ();
printf (") = %s\n", retstr)
destroy (tid ())
unlock ()
}
}