#! /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 () } }