#include <libintl.h>
#include <stdio.h>
#include <string.h>
+#include <signal.h>
#ifndef STAP_SCRIPT_FILENAME
#error "STAP_SCRIPT_FILENAME is required"
for (argp = args; *argp; argp++)
{
if (argp > args)
- fputs (", ", stderr);
- fprintf (stderr, "'%s'", *argp);
+ fputc (' ', stderr);
+ fputs (*argp, stderr);
}
fputc ('\n', stderr);
}
{
char **args, **argp;
- args = xmalloc (sizeof (*args) * argc * 2);
+ args = xmalloc (sizeof (*args) * argc * 2 + 32);
argp = args;
- *argp++ = argv[0];
+ *argp++ = "stap";
for (;;)
{
if (optind < argc)
{
- size_t len;
+ pid_t child;
int i;
- char *d;
- const char *s;
+ static char kill_s[64];
+ static char opt_s[64];
- *argp++ = "-c";
-
- len = 32;
- for (i = optind; i < argc; i++)
- len += 3 + strlen (argv[i]) * 4;
-
- d = *argp++ = xmalloc (len);
- d = stpcpy (d, "(exec");
- for (i = optind; i < argc; i++)
+ child = fork ();
+ switch (child)
{
- *d++ = ' ';
- *d++ = '\'';
- for (s = argv[optind]; *s; s++)
- switch (*s)
- {
- case '\'':
- d = stpcpy (d, "'\\''");
- break;
- case '\\':
- *d++ = '\\';
- /* FALLTHRU */
- default:
- *d++ = *s;
- }
- *d++ = '\'';
+ case -1:
+ error (EXIT_FAILURE, errno, _("Error calling fork"));
+ case 0:
+ i = raise (SIGSTOP);
+ if (i != 0)
+ error (EXIT_FAILURE, errno, _("Error calling raise (SIGSTOP)"));
+
+ execvp (argv[optind], &argv[optind]);
+ error (EXIT_FAILURE, errno, "Error executing child command");
+ default:
+ break;
}
- *d++ = ')';
- *d++ = 0;
+
+ /* FIXME: Call `kill -CONT' from the systamtap script. How? */
+ i = sprintf (kill_s, "kill -CONT %lu; "
+ "while [ -e /proc/%lu/root ]; do sleep 0.1; done",
+ (unsigned long) child, (unsigned long) child);
+ if (i <= 0)
+ error (EXIT_FAILURE, errno, _("Error calling sprintf"));
+ *argp++ = "-c";
+ *argp++ = kill_s;
+ i = sprintf (opt_s, "opt_child=%lu", (unsigned long) child);
+ if (i <= 0)
+ error (EXIT_FAILURE, errno, _("Error calling sprintf"));
+ *argp++ = "-G";
+ *argp++ = opt_s;
}
*argp++ = opt_Z;
*argp = NULL;
# ` = 0' is there to prevent: WARNING: never-assigned global variable
global opt_f = 0
global opt_q = 0
+# Override target().
+global opt_child = 0
/* systemtap bug? /usr/share/doc/systemtap-1.3/SystemTap_Beginners_Guide.pdf
Example 3.19 reads or writes? */
global last_tid
probe begin
{
- trace[target ()] = 1
- last_tid = target ()
+ tid = opt_child > 0 ? opt_child : target ()
+ trace[tid] = 1
+ last_tid = tid
}
-function heading:string ()
+function heading:string (tid:long)
{
foreach (tidi in trace limit 2)
tid_count++
if (tid_count > 1)
{
/* strace really calls TID a "pid". */
- return sprintf ("[pid %5d] ", tid ())
+ return sprintf ("[pid %5d] ", tid)
}
else
return ""
}
-global namea
+global funcname
+global nest
-function destroy (tid:long)
-{
- delete namea[tid]
-}
-
-function lhs:string (tid:long)
-{
- return namea[tid]
-}
probe end
{
- foreach (tid in namea)
- printf ("%s = ? <tracer terminated>\n", lhs (tid))
+ if (nest[last_tid])
+ printf (") = ? <tracer terminated>\n")
+ foreach (tid in nest)
+ if (tid != last_tid)
+ printf ("%s<... %s resumed> ) = ? <tracer terminated>\n", heading (tid),
+ funcname[tid] != "" ? funcname[tid] : "?");
}
/* BUG: sleeping function called from invalid context at kernel/mutex.c:94
mutex_unlock (&tracer_mutex);
%}
*/
-global dummy
-function lock () { dummy = 1; }
-function unlock () { dummy = 1; }
+global lockvar
+function lock ()
+{
+ lockvar++
+}
+function unlock ()
+{
+ lockvar++
+}
#probe kprocess.start
#{
tid = task_tid (task)
if (trace[tid] != 0)
{
- if (namea[tid] != "")
- {
- printf ("%s = ?\n", lhs (tid))
- destroy (tid)
- }
-# FIXME
- else if (0)
+ if (nest[tid])
{
- /* 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 (" <unfinished ...>\n")
- last_tid = tid
- printf ("%s_exit(?) = ?\n", heading ())
- unlock ()
+ /* FIXME: Do not assume "exit" for the nested calls. */
+ printf ("%s<... %s resumed> = ?\n", heading (tid),
+ funcname[tid] != "" ? funcname[tid] : "exit")
+ delete nest[tid]
+ delete funcname[tid]
}
delete trace[tid]
if (!opt_q)
{
lock ()
/* Why is mmap() called recursively twice? */
- if (namea[last_tid] != "")
+ if (nest[last_tid])
printf (" <unfinished ...>\n")
last_tid = tid ();
- namea[tid ()] = name
- printf ("%s%s(%s", heading (), name, argstr)
+ funcname[tid ()] = name
+ nest[tid ()]++
+ printf ("%s%s(%s", heading (tid ()), name, argstr)
unlock ()
}
}
if (trace[tid ()] != 0)
{
lock ()
- if (last_tid != tid () && namea[last_tid] != "")
+ if (last_tid != tid () && nest[last_tid])
printf (" <unfinished ...>\n")
- if ((last_tid != tid () && namea[last_tid] != "")
- || (last_tid == tid () && namea[last_tid] == ""))
- printf ("%s<... %s resumed> ", heading (), name);
+ if (last_tid != tid () || (last_tid == tid () && !nest[last_tid]))
+ printf ("%s<... %s resumed> ", heading (tid ()), name);
last_tid = tid ();
printf (") = %s\n", retstr)
- destroy (tid ())
+ if (!--nest[tid ()])
+ delete nest[tid ()]
+ delete funcname[tid ()]
unlock ()
}
}