--- /dev/null
+COPYING
+INSTALL
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.h
+config.h.in
+config.h.in~
+config.log
+config.status
+config/Makefile
+config/Makefile.in
+config/depcomp
+config/install-sh
+config/missing
+configure
+src/.deps
+src/Makefile
+src/Makefile.am
+src/Makefile.in
+src/staptrace
+src/staptrace.o
+stamp-h1
+staptrace.spec
+src/staptrace-staptrace.o
+tags
--- /dev/null
+# Process this file with automake to create Makefile.in
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+SUBDIRS = config src
+# po
+
+EXTRA_DIST = staptrace.spec
--- /dev/null
+# Process this file with automake to create Makefile.in
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+EXTRA_DIST = staptrace.spec.in
--- /dev/null
+# -*- rpm-spec-*-
+Summary: strace equivalent based on systemtap
+Name: staptrace
+Version: @PACKAGE_VERSION@
+Release: 1
+License: GPLv3+
+Group: Development/Tools
+Source: staptrace-%{version}.tar.xz
+
+%description
+FIXME
+
+%prep
+%setup -q
+
+%build
+%configure
+make
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+mkdir -p ${RPM_BUILD_ROOT}%{_prefix}
+
+%makeinstall
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+%{_bindir}/staptrace
+%{_datadir}/staptrace
+
+%changelog
--- /dev/null
+dnl Process this file with autoconf to produce a configure script.
+dnl Configure input file for staptrace. -*-autoconf-*-
+dnl
+dnl Process this file with automake to create Makefile.in
+dnl
+dnl Copyright (C) 2010 Free Software Foundation, Inc.
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+AC_INIT([stap trace],[0.1],[http://bugzilla.redhat.com/bugzilla/],[staptrace])
+
+AC_CONFIG_AUX_DIR([config])
+AC_CONFIG_FILES([config/Makefile])
+
+AC_PREREQ(2.63) dnl Minimum Autoconf version required.
+
+dnl We use GNU make extensions; automake 1.10 defaults to -Wportability.
+AM_INIT_AUTOMAKE([foreign -Wno-portability dist-xz no-dist-gzip])
+AM_MAINTAINER_MODE
+
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_HEADERS([config.h])
+
+dnl The RPM spec file. We substitute a few values in the file.
+AC_CONFIG_FILES([staptrace.spec:config/staptrace.spec.in])
+
+AC_PROG_CC
+
+AC_CONFIG_FILES([src/Makefile])
+
+AC_OUTPUT
--- /dev/null
+#include <error.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libintl.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef STAP_SCRIPT_FILENAME
+#error "STAP_SCRIPT_FILENAME is required"
+#endif
+
+#define STRINGIFY(lit) #lit
+#define _(x) gettext (x)
+
+static int opt_d, opt_f, opt_q, opt_p;
+
+/* Script filename. */
+static char *opt_Z = STRINGIFY (STAP_SCRIPT_FILENAME);
+
+static void *
+xmalloc (size_t size)
+{
+ void *retval = malloc (size);
+
+ if (retval == NULL)
+ error (EXIT_FAILURE, errno, _("memory allocation of %zu bytes"), size);
+
+ return retval;
+}
+
+static void
+usage (int status)
+{
+ printf ("\
+usage: staptrace [-dfq] [-o file] [-p pid] [command [arg ...]]\n\
+ [-Z <stap script>]\n\
+\n\
+Default -Z is: %s\n\
+",
+ opt_Z);
+ exit (status);
+}
+
+static void
+dump_args (char **args)
+{
+ char **argp;
+
+ for (argp = args; *argp; argp++)
+ {
+ if (argp > args)
+ fputs (", ", stderr);
+ fprintf (stderr, "'%s'", *argp);
+ }
+ fputc ('\n', stderr);
+}
+
+int
+main (int argc, char **argv)
+{
+ char **args, **argp;
+
+ args = xmalloc (sizeof (*args) * argc * 2);
+ argp = args;
+ *argp++ = argv[0];
+
+ for (;;)
+ {
+ int i;
+
+ i = getopt (argc, argv, "+dfqo:p:hZ:");
+ if (i == EOF)
+ break;
+ switch (i)
+ {
+ case 'd':
+ opt_d = 1;
+ break;
+ case 'f':
+ if (opt_f)
+ error (EXIT_FAILURE, 0, _("-ff is unsupported"));
+ *argp++ = "-G";
+ *argp++ = "opt_f=1";
+ opt_f = 1;
+ break;
+ case 'q':
+ *argp++ = "-G";
+ *argp++ = "opt_q=1";
+ opt_q = 1;
+ break;
+ case 'o':
+ *argp++ = "-o";
+ *argp++ = optarg;
+ break;
+ case 'p':
+ *argp++ = "-x";
+ *argp++ = optarg;
+ opt_p = 1;
+ break;
+ case 'Z':
+ opt_Z = optarg;
+ break;
+ case 'h':
+ usage (EXIT_SUCCESS);
+ default:
+ error (0, 0, _("Invalid option '%c'"), i);
+ usage (EXIT_FAILURE);
+ }
+ }
+
+ if ((optind == argc) == !opt_p)
+ usage (EXIT_FAILURE);
+
+ if (optind < argc)
+ {
+ size_t len;
+ int i;
+ char *d;
+ const char *s;
+
+ *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++)
+ {
+ *d++ = ' ';
+ *d++ = '\'';
+ for (s = argv[optind]; *s; s++)
+ switch (*s)
+ {
+ case '\'':
+ d = stpcpy (d, "'\\''");
+ break;
+ case '\\':
+ *d++ = '\\';
+ /* FALLTHRU */
+ default:
+ *d++ = *s;
+ }
+ *d++ = '\'';
+ }
+ *d++ = 0;
+ }
+ *argp++ = opt_Z;
+ *argp = NULL;
+
+ if (opt_d)
+ dump_args (args);
+ execvp ("stap", args);
+
+ if (!opt_d)
+ dump_args (args);
+ error (EXIT_FAILURE, errno, "Error executing stap");
+}
--- /dev/null
+#! /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 <http://www.gnu.org/licenses/>.
+
+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 = ? <tracer terminated>\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 (" <unfinished ...>\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 (" <unfinished ...>\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 (" <unfinished ...>\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 ()
+ }
+}