summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-08-06 12:06:06 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-08-06 12:06:06 -0400
commit3c4371661f144c331dd55ee6be8dab57ec2323c8 (patch)
tree217ccf5864840f14670138b592d90eceacc75fa3
parent44ab6f3be72e7b5eeaa2514cea0553b87007ee9c (diff)
parent0317fad416059781b7a152296c1d8b5a012bf925 (diff)
downloadsystemtap-steved-3c4371661f144c331dd55ee6be8dab57ec2323c8.tar.gz
systemtap-steved-3c4371661f144c331dd55ee6be8dab57ec2323c8.tar.xz
systemtap-steved-3c4371661f144c331dd55ee6be8dab57ec2323c8.zip
Merge commit 'origin/master' into pr4225
* commit 'origin/master': Use relative instead of absolute line. (bug 6611) move post-0.7 news tidbit to the top Add test for $$vars, $$params, $$locals. typographical tweaks for embedded script code Add $$vars, $$parms, $$locals Rename $path to $pathname of syscall tapset for 2.6.27 Correct several tests for 2.6.27 c code generation: assert C indentation/nesting cancels out at appropriate points Tweak test_installcheck for helloworld.meta and traceio2.meta. Run both tests for installcheck tests. No need for random suffix file cmdline and sysinfo files in the Ensure that a systemtap server is available if 'server' is specified session.h (struct systemtap_session): Added itrace_derived_probe * syscalls2.stp: Add sys_unlinkat. Fix on_each_cpu() call for kernels >2.6.26. Remove unused STAPCONF_MODULE_NSECTIONS
-rw-r--r--ChangeLog79
-rw-r--r--Makefile.am46
-rw-r--r--Makefile.in46
-rw-r--r--NEWS3
-rw-r--r--buildrun.cxx2
-rw-r--r--doc/langref.tex13
-rw-r--r--elaborate.cxx1
-rw-r--r--runtime/ChangeLog5
-rw-r--r--runtime/autoconf-module-nsections.c8
-rw-r--r--runtime/autoconf-oneachcpu-retry.c7
-rw-r--r--runtime/itrace.c438
-rw-r--r--runtime/time.c4
-rw-r--r--session.h2
-rwxr-xr-xstap-client218
-rwxr-xr-xstap-find-or-start-server36
-rwxr-xr-xstap-find-servers128
-rwxr-xr-xstap-server51
-rwxr-xr-xstap-serverd28
-rwxr-xr-xstap-start-server24
-rwxr-xr-xstap-stop-server30
-rw-r--r--stapprobes.5.in18
-rw-r--r--systemtap.base/itrace.exp102
-rw-r--r--systemtap.spec4
-rw-r--r--tapset/ChangeLog14
-rw-r--r--tapset/syscalls.stp64
-rw-r--r--tapset/syscalls2.stp64
-rw-r--r--tapset/vfs.stp9
-rw-r--r--tapsets.cxx362
-rw-r--r--testsuite/ChangeLog25
-rw-r--r--testsuite/Makefile.am2
-rw-r--r--testsuite/Makefile.in2
-rwxr-xr-xtestsuite/buildok/seven.stp2
-rwxr-xr-xtestsuite/buildok/seventeen.stp4
-rw-r--r--testsuite/lib/stap_compile.exp2
-rw-r--r--testsuite/lib/stap_run.exp2
-rw-r--r--testsuite/lib/stap_run2.exp2
-rw-r--r--testsuite/lib/stap_run_binary.exp2
-rw-r--r--testsuite/lib/stap_run_exact.exp2
-rw-r--r--testsuite/lib/systemtap.exp9
-rw-r--r--testsuite/systemtap.base/vars.exp32
-rw-r--r--testsuite/systemtap.base/warnings.stp2
-rw-r--r--testsuite/systemtap.examples/ChangeLog8
-rw-r--r--testsuite/systemtap.examples/check.exp44
-rw-r--r--testsuite/systemtap.examples/helloworld.meta2
-rw-r--r--testsuite/systemtap.examples/traceio2.meta2
45 files changed, 1737 insertions, 213 deletions
diff --git a/ChangeLog b/ChangeLog
index 6ab9dc3a..09e2ff37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,88 @@
+2008-08-05 Stan Cox <scox@redhat.com>
+
+ * NEWS: Updated $$vars, $$parms, $$locals.
+ * tapsets.cxx (visit_target_symbol): Missing break typo.
+
+2008-08-04 Stan Cox <scox@redhat.com>
+
+ * tapsets.cxx (dwarf_var_expanding_copy_visitor::visit_target_symbol):
+ Add support for $$vars, $$parms, and $$locals.
+ * stapprobes.5.in: Likewise.
+ * doc/langref.tex: Likewise.
+
2008-08-02 Frank Ch. Eigler <fche@elastic.org>
* translate.h (translator_output::assert_0_indent): New function.
* translate.cxx (emit_*): Add a couple of calls to confirm
newline(1)/(-1) nest matching.
+2008-07-30 Dave Brolley <brolley@redhat.com>
+
+ * stap-client (create_request): No need for random suffix for
+ cmdline and sysinfo files.
+ * stap-server (read_data_file): File name is exactly as specified.
+ Check that it exists.
+
+2008-07-29 Dave Brolley <brolley@redhat.com>
+
+ * Makefile.am (bin_SCRIPTS): add stap-find-servers, stap-start-server,
+ stap-find-or-start-server, stap-stop-server.
+ (EXTRA_DIST): Likewise.
+ (check): Ensure that a compatible systemtap server is running before
+ running the tests, if requested. If we start a sterver, stop it after
+ running the tests.
+ (installcheck): Likewise.
+ * stap-client (parse_options): Specify stdin as 'scripts/-' on the
+ generated command line.
+ (create_request): Use $script_file instead of '-'.
+ (unpack_response): Existence of the systemtap temp directory is
+ optional.
+ (find_and_connect_to_server): Use stap-find-servers and choose_server.
+ (choose_server): Rewritten from match_server. Examine multiple
+ servers.
+ (connect_to_server): New function.
+ (maybe_call_staprun): Check for existence of a module.
+ Use staprun_PATH.
+ (staprun_PATH): New function.
+ (fatal): Call disconnect_from_server.
+ (server_fatal): Likewise.
+ * stap-server: Catch SIGTERM and SIGINT.
+ (create_response): Check for the existence of $tmpdir_stap.
+ (terminate): New function.
+ * stap-serverd: Catch SIGTERM and SIGINT.
+ (listen): Run 'nc | stap-server' in the background and wait for them
+ to finish.
+ (terminate): Renamed from handle_sigint. Kill avahi-publish-service
+ and nc.
+ * systemtap.spec: Add stap-find-servers, stap-start-server,
+ stap-find-or-start-server, stap-stop-server.
+ * Makefile.in: Regenerated.
+
+2008-07-28 Dave Nomura <dcnltc@us.ibm.com>
+
+ * session.h (struct systemtap_session): Added itrace_derived_probe
+ group.
+ * elaborate.cxx (systemtap_session::systemtap_session): Added
+ initialization of itrace_derived_probes.
+ * tapsets.cxx (struct itrace_derived_probe): Add derived_probe
+ struct for holding info needed by itrace probes.
+ (struct itrace_derived_probe_group): New derived_probe_group
+ to handle itrace probes.
+ (itrace_derived_probe::itrace_derived_probe): Needed for use with
+ task_finder.
+ (itrace_derived_probe_group::join_group): Ditto.
+ (itrace_derived_probe_group::enroll): Ditto.
+ (itrace_derived_probe_group::emit_probe_decl): Ditto.
+ (itrace_derived_probe_group::emit_module_decls): Ditto.
+ (itrace_derived_probe_group::emit_module_init): Ditto.
+ (itrace_derived_probe_group::emit_module_exit): Ditto.
+ * stapprobes.5.in : Added documentation of itrace probe.
+
+2008-07-24 Josh Stone <joshua.i.stone@intel.com>
+
+ * buildrun.cxx (compile_pass): Remove STAPCONF_MODULE_NSECTIONS,
+ and add STAPCONF_ONEACHCPU_RETRY
+
2008-07-23 Frank Ch. Eigler <fche@elastic.org>
From James Bottomley <James.Bottomley@HansenPartnership.com>:
diff --git a/Makefile.am b/Makefile.am
index 3f619584..eaddfd59 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,7 +12,7 @@ AM_CXXFLAGS = -Wall -Werror
dist_man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5
bin_PROGRAMS = stap staprun
-bin_SCRIPTS = stap-client stap-server stap-serverd
+bin_SCRIPTS = stap-client stap-server stap-serverd stap-find-servers stap-start-server stap-find-or-start-server stap-stop-server
stap_SOURCES = main.cxx \
parse.cxx staptree.cxx elaborate.cxx translate.cxx \
tapsets.cxx buildrun.cxx loc2c.c hash.cxx mdfour.c \
@@ -155,7 +155,7 @@ EXTRA_DIST = auto_free.h buildrun.h elaborate.h loc2c.h session.h \
testsuite systemtap.spec runtime tapset \
dwarf_wrappers.h \
git_version.h git_version.sh \
- stap-client stap-server stap-serverd \
+ stap-client stap-server stap-serverd stap-find-servers stap-start-server stap-find-or-start-server stap-stop-server \
systemtap.spec
EXAMPLE_SOURCE_DIR = $(srcdir)/testsuite/systemtap.examples
@@ -250,18 +250,54 @@ SUBDIRS = testsuite doc
check:
SRCDIR=`cd $(srcdir); pwd`; \
- $(MAKE) -C testsuite check SYSTEMTAP_RUNTIME=$$SRCDIR/runtime SYSTEMTAP_TAPSET=$$SRCDIR/tapset LD_LIBRARY_PATH=$(PWD)/lib-elfutils:$(PWD)/lib-elfutils/systemtap SYSTEMTAP_PATH=$(PWD) RUNTESTFLAGS="$(RUNTESTFLAGS)"
+ BUILDDIR=`cd $(builddir); pwd`; \
+ need_server=0; \
+ (echo "X$(EXTRA_TOOL_OPTS)" | grep -q server) && need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Testing using a systemtap server"; \
+ need_server=0; \
+ server_pid=`stap-find-or-start-server` || need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Cannot find or start a systemtap server"; \
+ exit -1; \
+ fi; \
+ client_path="$$BUILDDIR/testsuite/net"; \
+ mkdir -p $$BUILDDIR/testsuite/net; \
+ cp -p $$SRCDIR/stap-client $$BUILDDIR/testsuite/net/stap; \
+ fi; \
+ $(MAKE) -C testsuite check SYSTEMTAP_RUNTIME=$$SRCDIR/runtime SYSTEMTAP_TAPSET=$$SRCDIR/tapset LD_LIBRARY_PATH=$(PWD)/lib-elfutils:$(PWD)/lib-elfutils/systemtap SYSTEMTAP_PATH="$$client_path:$(PWD)" RUNTESTFLAGS="$(RUNTESTFLAGS)"; \
+ if test "X$$server_pid" != "X"; then \
+ stap-stop-server $$server_pid; \
+ fi
installcheck:
+ BUILDDIR=`cd $(builddir); pwd`; \
if test \! -e $(DESTDIR)$(bindir)/stap; then \
echo $(DESTDIR)$(bindir)/stap doesn\'t exist, run make install; \
exit -1; \
- fi
+ fi; \
if test $(builddir)/stap -nt $(DESTDIR)$(bindir)/stap; then \
echo "$(DESTDIR)$(bindir)/stap is not recent, run make install"; \
exit -1; \
+ fi; \
+ need_server=0; \
+ (echo "X$(EXTRA_TOOL_OPTS)" | grep -q server) && need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Testing using a systemtap server"; \
+ need_server=0; \
+ server_pid=`stap-find-or-start-server` || need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Cannot find or start a systemtap server"; \
+ exit -1; \
+ fi; \
+ client_path=":$$BUILDDIR/testsuite/net"; \
+ mkdir -p $$BUILDDIR/testsuite/net; \
+ cp -p $(DESTDIR)$(bindir)/stap-client $$BUILDDIR/testsuite/net/stap; \
+ fi; \
+ $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)" EXTRA_SYSTEMTAP_PATH="$(EXTRA_SYSTEMTAP_PATH)$$client_path"; \
+ if test "X$$server_pid" != "X"; then \
+ stap-stop-server $$server_pid; \
fi
- $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)"
rpm: systemtap.spec dist
rpmbuild --define "_sourcedir $(PWD)/" -ba systemtap.spec
diff --git a/Makefile.in b/Makefile.in
index cc8d4fd3..e3b6f146 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -275,7 +275,7 @@ AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR=
AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W
AM_CXXFLAGS = -Wall -Werror
dist_man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5
-bin_SCRIPTS = stap-client stap-server stap-serverd
+bin_SCRIPTS = stap-client stap-server stap-serverd stap-find-servers stap-start-server stap-find-or-start-server stap-stop-server
stap_SOURCES = main.cxx \
parse.cxx staptree.cxx elaborate.cxx translate.cxx \
tapsets.cxx buildrun.cxx loc2c.c hash.cxx mdfour.c \
@@ -334,7 +334,7 @@ EXTRA_DIST = auto_free.h buildrun.h elaborate.h loc2c.h session.h \
testsuite systemtap.spec runtime tapset \
dwarf_wrappers.h \
git_version.h git_version.sh \
- stap-client stap-server stap-serverd \
+ stap-client stap-server stap-serverd stap-find-servers stap-start-server stap-find-or-start-server stap-stop-server \
systemtap.spec
EXAMPLE_SOURCE_DIR = $(srcdir)/testsuite/systemtap.examples
@@ -1636,18 +1636,54 @@ uninstall-local:
check:
SRCDIR=`cd $(srcdir); pwd`; \
- $(MAKE) -C testsuite check SYSTEMTAP_RUNTIME=$$SRCDIR/runtime SYSTEMTAP_TAPSET=$$SRCDIR/tapset LD_LIBRARY_PATH=$(PWD)/lib-elfutils:$(PWD)/lib-elfutils/systemtap SYSTEMTAP_PATH=$(PWD) RUNTESTFLAGS="$(RUNTESTFLAGS)"
+ BUILDDIR=`cd $(builddir); pwd`; \
+ need_server=0; \
+ (echo "X$(EXTRA_TOOL_OPTS)" | grep -q server) && need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Testing using a systemtap server"; \
+ need_server=0; \
+ server_pid=`stap-find-or-start-server` || need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Cannot find or start a systemtap server"; \
+ exit -1; \
+ fi; \
+ client_path="$$BUILDDIR/testsuite/net"; \
+ mkdir -p $$BUILDDIR/testsuite/net; \
+ cp -p $$SRCDIR/stap-client $$BUILDDIR/testsuite/net/stap; \
+ fi; \
+ $(MAKE) -C testsuite check SYSTEMTAP_RUNTIME=$$SRCDIR/runtime SYSTEMTAP_TAPSET=$$SRCDIR/tapset LD_LIBRARY_PATH=$(PWD)/lib-elfutils:$(PWD)/lib-elfutils/systemtap SYSTEMTAP_PATH="$$client_path:$(PWD)" RUNTESTFLAGS="$(RUNTESTFLAGS)"; \
+ if test "X$$server_pid" != "X"; then \
+ stap-stop-server $$server_pid; \
+ fi
installcheck:
+ BUILDDIR=`cd $(builddir); pwd`; \
if test \! -e $(DESTDIR)$(bindir)/stap; then \
echo $(DESTDIR)$(bindir)/stap doesn\'t exist, run make install; \
exit -1; \
- fi
+ fi; \
if test $(builddir)/stap -nt $(DESTDIR)$(bindir)/stap; then \
echo "$(DESTDIR)$(bindir)/stap is not recent, run make install"; \
exit -1; \
+ fi; \
+ need_server=0; \
+ (echo "X$(EXTRA_TOOL_OPTS)" | grep -q server) && need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Testing using a systemtap server"; \
+ need_server=0; \
+ server_pid=`stap-find-or-start-server` || need_server=1; \
+ if test $$need_server = 1; then \
+ echo "Cannot find or start a systemtap server"; \
+ exit -1; \
+ fi; \
+ client_path=":$$BUILDDIR/testsuite/net"; \
+ mkdir -p $$BUILDDIR/testsuite/net; \
+ cp -p $(DESTDIR)$(bindir)/stap-client $$BUILDDIR/testsuite/net/stap; \
+ fi; \
+ $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)" EXTRA_SYSTEMTAP_PATH="$(EXTRA_SYSTEMTAP_PATH)$$client_path"; \
+ if test "X$$server_pid" != "X"; then \
+ stap-stop-server $$server_pid; \
fi
- $(MAKE) -C testsuite installcheck RUNTESTFLAGS="$(RUNTESTFLAGS)"
rpm: systemtap.spec dist
rpmbuild --define "_sourcedir $(PWD)/" -ba systemtap.spec
diff --git a/NEWS b/NEWS
index 65af9271..0cdc2aa3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
* What's new
+- A formatted string representation of the variables, parameters, or local
+ variables at a probe point is now supported via the special $$vars,
+ $$parms, and $$locals context variables.
* What's new in version 0.7
diff --git a/buildrun.cxx b/buildrun.cxx
index 72c0d1c7..c2ebdce5 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -95,9 +95,9 @@ compile_pass (systemtap_session& s)
o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-x86-uniregs.c, -DSTAPCONF_X86_UNIREGS,)" << endl;
o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-nameidata.c, -DSTAPCONF_NAMEIDATA_CLEANUP,)" << endl;
o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-unregister-kprobes.c, -DSTAPCONF_UNREGISTER_KPROBES,)" << endl;
- o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-module-nsections.c, -DSTAPCONF_MODULE_NSECTIONS,)" << endl;
o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-real-parent.c, -DSTAPCONF_REAL_PARENT,)" << endl;
o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-uaccess.c, -DSTAPCONF_LINUX_UACCESS_H,)" << endl;
+ o << module_cflags << " += $(call stap_check_build, $(SYSTEMTAP_RUNTIME)/autoconf-oneachcpu-retry.c, -DSTAPCONF_ONEACHCPU_RETRY,)" << endl;
#if 0
/* NB: For now, the performance hit of probe_kernel_read/write (vs. our
* homegrown safe-access functions) is deemed undesireable, so we'll skip
diff --git a/doc/langref.tex b/doc/langref.tex
index e2c630d4..413ece4d 100644
--- a/doc/langref.tex
+++ b/doc/langref.tex
@@ -771,7 +771,7 @@ pointers, and arrays.
\texttt{\$var} refers to an in-scope variable var. If it is a type similar
to an integer, it will be cast to a 64-bit integer for script use. Pointers
similar to a string (char {*}) are copied to SystemTap string values by the
-kernel\_string() or user\_string functions().
+\texttt{kernel\_string()} or \texttt{user\_string()} functions.
\texttt{\$var->field} traverses a structure's field. The indirection operator
may be repeated to follow additional levels of pointers.
@@ -779,6 +779,17 @@ may be repeated to follow additional levels of pointers.
\texttt{\$var{[}N]} indexes into an array. The index is given with a literal
number.
+\texttt{\$\$vars} expands to a character string that is equivalent to
+\texttt{sprintf("parm1=\%x ... parmN=\%x var1=\%x ... varN=\%x", \$parm1, ..., \$parmN,
+\$var1, ..., \$varN)}
+
+\texttt{\$\$locals} expands to a character string that is equivalent to
+\texttt{sprintf("var1=\%x ... varN=\%x", \$var1, ..., \$varN)}
+
+\texttt{\$\$parms} expands to a character string that is equivalent to
+\texttt{sprintf("parm1=\%x ... parmN=\%x", \$parm1, ..., \$parmN)}
+
+
\subsubsection{kernel.function, module().function}
\index{kernel.function}
\index{module().function}
diff --git a/elaborate.cxx b/elaborate.cxx
index 73358a1d..0950b086 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -1187,6 +1187,7 @@ systemtap_session::systemtap_session ():
dwarf_derived_probes(0),
uprobe_derived_probes(0),
utrace_derived_probes(0),
+ itrace_derived_probes(0),
task_finder_derived_probes(0),
timer_derived_probes(0),
profile_derived_probes(0),
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index f12b5d9a..a8d73ffd 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,8 @@
+2008-07-24 Josh Stone <joshua.i.stone@intel.com>
+
+ * runtime/autoconf-module-nsections.c: removed
+ * runtime/autoconf-oneachcpu-retry.c: added
+
2008-07-21 David Smith <dsmith@redhat.com>
* task_finder_vma.c (__stp_tf_vma_initialize): New function to
diff --git a/runtime/autoconf-module-nsections.c b/runtime/autoconf-module-nsections.c
deleted file mode 100644
index c1ce58b7..00000000
--- a/runtime/autoconf-module-nsections.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <linux/module.h>
-
-struct module_sect_attrs x;
-
-void foo (void)
-{
- (void) x.nsections;
-}
diff --git a/runtime/autoconf-oneachcpu-retry.c b/runtime/autoconf-oneachcpu-retry.c
new file mode 100644
index 00000000..304d9842
--- /dev/null
+++ b/runtime/autoconf-oneachcpu-retry.c
@@ -0,0 +1,7 @@
+#include <linux/smp.h>
+
+void ____autoconf_func(void)
+{
+ /* Older on_each_cpu() calls had a "retry" parameter */
+ (void)on_each_cpu(NULL, NULL, 0, 0);
+}
diff --git a/runtime/itrace.c b/runtime/itrace.c
new file mode 100644
index 00000000..3ee48265
--- /dev/null
+++ b/runtime/itrace.c
@@ -0,0 +1,438 @@
+/*
+ * user space instruction tracing
+ * Copyright (C) 2005, 2006, 2007, 2008 IBM Corp.
+ *
+ * This file is part of systemtap, and is free software. You can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/rcupdate.h>
+#include <linux/utrace.h>
+#include <asm/string.h>
+#include <asm/tracehook.h>
+#include <asm/ptrace.h>
+#include "uprobes/uprobes.h"
+
+#ifndef put_task_struct
+#define put_task_struct(t) \
+ BUG_ON(atomic_dec_and_test(&tsk->usage))
+#endif
+
+#ifdef CONFIG_PPC
+struct bpt_info {
+ unsigned long addr;
+ unsigned int instr;
+};
+
+struct atomic_ss_info {
+ int step_over_atomic;
+ struct bpt_info end_bpt;
+ struct bpt_info br_bpt;
+};
+
+static int handle_ppc_atomic_seq(struct task_struct *tsk, struct pt_regs *regs,
+ struct atomic_ss_info *ss_info);
+static void remove_atomic_ss_breakpoint (struct task_struct *tsk,
+ struct bpt_info *bpt);
+#endif
+
+struct itrace_info {
+ pid_t tid;
+ u32 step_flag;
+ struct stap_itrace_probe *itrace_probe;
+#ifdef CONFIG_PPC
+ struct atomic_ss_info ppc_atomic_ss;
+#endif
+ struct task_struct *tsk;
+ struct utrace_attached_engine *engine;
+ struct list_head link;
+};
+
+static u32 debug = 1;
+
+static LIST_HEAD(usr_itrace_info);
+static spinlock_t itrace_lock;
+static struct itrace_info *create_itrace_info(
+ struct task_struct *tsk, u32 step_flag,
+ struct stap_itrace_probe *itrace_probe);
+
+static u32 usr_itrace_report_signal(struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs,
+ u32 action, siginfo_t *info,
+ const struct k_sigaction *orig_ka,
+ struct k_sigaction *return_ka)
+{
+ struct itrace_info *ui;
+ u32 return_flags;
+ unsigned long data = 0;
+#ifdef CONFIG_PPC
+ data = mfspr(SPRN_SDAR);
+#endif
+
+ ui = rcu_dereference(engine->data);
+ WARN_ON(!ui);
+
+ if (info->si_signo != SIGTRAP || !ui)
+ return UTRACE_ACTION_RESUME;
+
+ /* normal case: continue stepping, hide this trap from other engines */
+ return_flags = ui->step_flag | UTRACE_ACTION_HIDE | UTRACE_SIGNAL_IGN |
+ UTRACE_ACTION_NEWSTATE;
+
+#ifdef CONFIG_PPC
+ if (ui->ppc_atomic_ss.step_over_atomic) {
+ remove_atomic_ss_breakpoint(tsk, &ui->ppc_atomic_ss.end_bpt);
+ if (ui->ppc_atomic_ss.br_bpt.addr)
+ remove_atomic_ss_breakpoint(tsk,
+ &ui->ppc_atomic_ss.br_bpt);
+ ui->ppc_atomic_ss.step_over_atomic = 0;
+ }
+
+ if (handle_ppc_atomic_seq(tsk, regs, &ui->ppc_atomic_ss))
+ return_flags = UTRACE_ACTION_RESUME | UTRACE_ACTION_NEWSTATE |
+ UTRACE_SIGNAL_IGN;
+#endif
+
+ enter_itrace_probe(ui->itrace_probe, regs, (void *)&data);
+
+ return return_flags;
+}
+
+static u32 usr_itrace_report_clone(struct utrace_attached_engine *engine,
+ struct task_struct *parent, unsigned long clone_flags,
+ struct task_struct *child)
+{
+ return UTRACE_ACTION_RESUME;
+}
+
+static u32 usr_itrace_report_death(struct utrace_attached_engine *e,
+ struct task_struct *tsk)
+{
+ struct itrace_info *ui = rcu_dereference(e->data);
+ WARN_ON(!ui);
+
+ return (UTRACE_ACTION_NEWSTATE | UTRACE_ACTION_DETACH);
+}
+
+static const struct utrace_engine_ops utrace_ops =
+{
+ .report_signal = usr_itrace_report_signal,
+ .report_clone = usr_itrace_report_clone,
+ .report_death = usr_itrace_report_death
+};
+
+
+static struct itrace_info *create_itrace_info(
+ struct task_struct *tsk, u32 step_flag,
+ struct stap_itrace_probe *itrace_probe)
+{
+ struct itrace_info *ui;
+
+ if (debug)
+ printk(KERN_INFO "create_itrace_info: tid=%d\n", tsk->pid);
+ /* initialize ui */
+ ui = kzalloc(sizeof(struct itrace_info), GFP_USER);
+ ui->tsk = tsk;
+ ui->tid = tsk->pid;
+ ui->step_flag = step_flag;
+ ui->itrace_probe = itrace_probe;
+#ifdef CONFIG_PPC
+ ui->ppc_atomic_ss.step_over_atomic = 0;
+#endif
+ INIT_LIST_HEAD(&ui->link);
+
+ /* push ui onto usr_itrace_info */
+ spin_lock(&itrace_lock);
+ list_add(&ui->link, &usr_itrace_info);
+
+ /* attach a single stepping engine */
+ ui->engine = utrace_attach(ui->tsk, UTRACE_ATTACH_CREATE, &utrace_ops, ui);
+ if (IS_ERR(ui->engine)) {
+ printk(KERN_ERR "utrace_attach returns %ld\n",
+ PTR_ERR(ui->engine));
+ ui = NULL;
+ } else {
+ utrace_set_flags(tsk, ui->engine, ui->engine->flags |
+ ui->step_flag |
+ UTRACE_EVENT(CLONE) | UTRACE_EVENT_SIGNAL_ALL |
+ UTRACE_EVENT(DEATH));
+ }
+ spin_unlock(&itrace_lock);
+ return ui;
+}
+
+static struct itrace_info *find_itrace_info(pid_t tid)
+{
+ struct itrace_info *ui = NULL;
+
+ spin_lock(&itrace_lock);
+ list_for_each_entry(ui, &usr_itrace_info, link) {
+ if (ui->tid == tid)
+ goto done;
+ }
+ ui = NULL;
+done:
+ spin_unlock(&itrace_lock);
+ return ui;
+}
+
+
+int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe *p)
+{
+ struct itrace_info *ui;
+ struct task_struct *tsk;
+
+ rcu_read_lock();
+ tsk = find_task_by_pid(tid);
+ if (!tsk) {
+ printk(KERN_ERR "usr_itrace_init: Cannot find process %d\n", tid);
+ rcu_read_unlock();
+ return 1;
+ }
+
+ get_task_struct(tsk);
+ ui = create_itrace_info(tsk,
+ (single_step ?
+ UTRACE_ACTION_SINGLESTEP : UTRACE_ACTION_BLOCKSTEP), p);
+ if (!ui)
+ return 1;
+
+ put_task_struct(tsk);
+ rcu_read_unlock();
+
+ spin_lock_init(&itrace_lock);
+
+ /* set initial state */
+ spin_lock(&itrace_lock);
+ spin_unlock(&itrace_lock);
+ printk(KERN_INFO "usr_itrace_init: completed for tid = %d\n", tid);
+
+ return 0;
+}
+
+void static remove_usr_itrace_info(struct itrace_info *ui)
+{
+ struct itrace_info *tmp;
+
+ if (!ui)
+ return;
+
+ if (debug)
+ printk(KERN_INFO "remove_usr_itrace_info: tid=%d\n", ui->tid);
+
+ spin_lock(&itrace_lock);
+ if (ui->tsk && ui->engine) {
+ (void) utrace_detach(ui->tsk, ui->engine);
+ }
+ list_del(&ui->link);
+ spin_unlock(&itrace_lock);
+ kfree(ui);
+}
+
+void static cleanup_usr_itrace(void)
+{
+ struct itrace_info *tmp;
+ struct itrace_info *ui;
+
+ if (debug)
+ printk(KERN_INFO "cleanup_usr_itrace called\n");
+
+ list_for_each_entry_safe(ui, tmp, &usr_itrace_info, link) {
+ remove_usr_itrace_info(ui);
+ }
+}
+
+
+#ifdef CONFIG_PPC
+#define PPC_INSTR_SIZE 4
+#define TEXT_SEGMENT_BASE 1
+
+/* Instruction masks used during single-stepping of atomic sequences. */
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTR 0x7c000028
+#define LDARX_INSTR 0x7c0000A8
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTR 0x7c00012d
+#define STDCX_INSTR 0x7c0001ad
+#define BC_MASK 0xfc000000
+#define BC_INSTR 0x40000000
+#define ATOMIC_SEQ_LENGTH 16
+#define BPT_TRAP 0x7fe00008
+#define INSTR_SZ sizeof(int)
+
+static int get_instr(unsigned long addr, char *msg)
+{
+ unsigned int instr;
+
+ if (copy_from_user(&instr, (const void __user *) addr,
+ sizeof(instr))) {
+ printk(KERN_ERR "get_instr failed: %s\n", msg);
+ WARN_ON(1);
+ }
+ return instr;
+
+}
+
+static void insert_atomic_ss_breakpoint (struct task_struct *tsk,
+ struct bpt_info *bpt)
+{
+ unsigned int bp_instr = BPT_TRAP;
+ unsigned int cur_instr;
+
+ cur_instr = get_instr(bpt->addr, "insert_atomic_ss_breakpoint");
+ if (cur_instr != BPT_TRAP) {
+ bpt->instr = cur_instr;
+ WARN_ON(access_process_vm(tsk, bpt->addr, &bp_instr, INSTR_SZ, 1) !=
+ INSTR_SZ);
+ }
+}
+
+static void remove_atomic_ss_breakpoint (struct task_struct *tsk,
+ struct bpt_info *bpt)
+{
+ WARN_ON(access_process_vm(tsk, bpt->addr, &bpt->instr, INSTR_SZ, 1) !=
+ INSTR_SZ);
+}
+
+/* locate the branch destination. Return -1 if not a branch. */
+static unsigned long
+branch_dest (int opcode, int instr, struct pt_regs *regs, unsigned long pc)
+{
+ unsigned long dest;
+ int immediate;
+ int absolute;
+ int ext_op;
+
+ absolute = (int) ((instr >> 1) & 1);
+
+ switch (opcode) {
+ case 18:
+ immediate = ((instr & ~3) << 6) >> 6; /* br unconditional */
+ if (absolute)
+ dest = immediate;
+ else
+ dest = pc + immediate;
+ break;
+
+ case 16:
+ immediate = ((instr & ~3) << 16) >> 16; /* br conditional */
+ if (absolute)
+ dest = immediate;
+ else
+ dest = pc + immediate;
+ break;
+
+ case 19:
+ ext_op = (instr >> 1) & 0x3ff;
+
+ if (ext_op == 16) {
+ /* br conditional register */
+ dest = regs->link & ~3;
+ /* FIX: we might be in a signal handler */
+ WARN_ON(dest > 0);
+ } else if (ext_op == 528) {
+ /* br cond to ctr reg */
+ dest = regs->ctr & ~3;
+
+ /* for system call dest < TEXT_SEGMENT_BASE */
+ if (dest < TEXT_SEGMENT_BASE)
+ dest = regs->link & ~3;
+ } else
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+ return dest;
+}
+
+/* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX
+ instruction and ending with a STWCX/STDCX instruction. If such a sequence
+ is found, attempt to step through it. A breakpoint is placed at the end of
+ the sequence. */
+
+static int handle_ppc_atomic_seq(struct task_struct *tsk, struct pt_regs *regs,
+ struct atomic_ss_info *ss_info)
+{
+ unsigned long ip = regs->nip;
+ unsigned long start_addr;
+ unsigned int instr;
+ int got_stx = 0;
+ int i;
+ int ret;
+
+ unsigned long br_dest; /* bpt at branch instr's destination */
+ int bc_instr_count = 0; /* conditional branch instr count */
+
+ instr = get_instr(regs->nip, "handle_ppc_atomic_seq:1");
+ /* Beginning of atomic sequence starts with lwarx/ldarx instr */
+ if ((instr & LWARX_MASK) != LWARX_INSTR
+ && (instr & LWARX_MASK) != LDARX_INSTR)
+ return 0;
+
+ start_addr = regs->nip;
+ for (i = 0; i < ATOMIC_SEQ_LENGTH; ++i) {
+ ip += INSTR_SZ;
+ instr = get_instr(ip, "handle_ppc_atomic_seq:2");
+
+ /* look for at most one conditional branch in the sequence
+ * and put a bpt at it's destination address
+ */
+ if ((instr & BC_MASK) == BC_INSTR) {
+ if (bc_instr_count >= 1)
+ return 0; /* only handle a single branch */
+
+ br_dest = branch_dest (BC_INSTR >> 26, instr, regs, ip);
+
+ if (br_dest != -1 &&
+ br_dest >= TEXT_SEGMENT_BASE) {
+ ss_info->br_bpt.addr = br_dest;
+ bc_instr_count++;
+ }
+ }
+
+ if ((instr & STWCX_MASK) == STWCX_INSTR
+ || (instr & STWCX_MASK) == STDCX_INSTR) {
+ got_stx = 1;
+ break;
+ }
+ }
+
+ /* Atomic sequence ends with a stwcx/stdcx instr */
+ if (!got_stx)
+ return 0;
+
+ ip += INSTR_SZ;
+ instr = get_instr(ip, "handle_ppc_atomic_seq:3");
+ if ((instr & BC_MASK) == BC_INSTR) {
+ ip += INSTR_SZ;
+ instr = get_instr(ip, "handle_ppc_atomic_seq:4");
+ }
+
+ /* Insert a breakpoint right after the end of the atomic sequence. */
+ ss_info->end_bpt.addr = ip;
+
+ /* Check for duplicate bpts */
+ if (bc_instr_count && (ss_info->br_bpt.addr >= start_addr &&
+ ss_info->br_bpt.addr <= ss_info->end_bpt.addr))
+ ss_info->br_bpt.addr = 0;
+
+ insert_atomic_ss_breakpoint (tsk, &ss_info->end_bpt);
+ if (ss_info->br_bpt.addr)
+ insert_atomic_ss_breakpoint (tsk, &ss_info->br_bpt);
+
+ ss_info->step_over_atomic = 1;
+ return 1;
+}
+#endif
diff --git a/runtime/time.c b/runtime/time.c
index 8a0b6fad..6b01cebe 100644
--- a/runtime/time.c
+++ b/runtime/time.c
@@ -237,7 +237,11 @@ _stp_init_time(void)
return -1;
stp_timer_reregister = 1;
+#ifdef STAPCONF_ONEACHCPU_RETRY
ret = on_each_cpu(__stp_init_time, NULL, 0, 1);
+#else
+ ret = on_each_cpu(__stp_init_time, NULL, 1);
+#endif
#ifdef CONFIG_CPU_FREQ
if (!ret && !__stp_constant_freq()) {
diff --git a/session.h b/session.h
index 734c8d7d..9f38372f 100644
--- a/session.h
+++ b/session.h
@@ -32,6 +32,7 @@ struct be_derived_probe_group;
struct dwarf_derived_probe_group;
struct uprobe_derived_probe_group;
struct utrace_derived_probe_group;
+struct itrace_derived_probe_group;
struct task_finder_derived_probe_group;
struct timer_derived_probe_group;
struct profile_derived_probe_group;
@@ -146,6 +147,7 @@ struct systemtap_session
dwarf_derived_probe_group* dwarf_derived_probes;
uprobe_derived_probe_group* uprobe_derived_probes;
utrace_derived_probe_group* utrace_derived_probes;
+ itrace_derived_probe_group* itrace_derived_probes;
task_finder_derived_probe_group* task_finder_derived_probes;
timer_derived_probe_group* timer_derived_probes;
profile_derived_probe_group* profile_derived_probes;
diff --git a/stap-client b/stap-client
index 8c3607ae..d6bb8442 100755
--- a/stap-client
+++ b/stap-client
@@ -169,8 +169,13 @@ function parse_options {
# If the script file was given and it's not '-', then replace it with its
# client-temp-name in the command string.
- if test "X$script_file" != "X" -a "$script_file" != "-"; then
- local local_name=`generate_client_temp_name $script_file`
+ if test "X$script_file" != "X"; then
+ local local_name
+ if test "$script_file" != "-"; then
+ local_name=`generate_client_temp_name $script_file`
+ else
+ local_name=$script_file
+ fi
cmdline=`echo $cmdline | sed s,$script_file,script/$local_name,`
fi
}
@@ -257,7 +262,7 @@ function process_R {
# Include the given file or directory in the client's temporary
# tree to be sent to the server.
function include_file_or_directory {
- # Add a symbolic link of the named directory to our temporary directory
+ # Add a symbolic link of the named file or directory to our temporary directory
local local_name=`generate_client_temp_name $2`
mkdir -p $tmpdir_client/$1/`dirname $local_name` || \
fatal "ERROR: could not create $tmpdir_client/$1/`dirname $local_name`"
@@ -291,22 +296,16 @@ function create_request {
if test "X$script_file" != "X"; then
if test "$script_file" = "-"; then
mkdir -p $tmpdir_client/script || \
- fatal "ERROR: cannot create temporary diectory " $tmpdir_client/script
- cat > $tmpdir_client/script/-
+ fatal "ERROR: cannot create temporary directory " $tmpdir_client/script
+ cat > $tmpdir_client/script/$script_file
else
include_file_or_directory script $script_file > /dev/null
fi
fi
- # Add the necessary info to special files in our temporary directory. Do this
- # after linking in -I and -R directories in order to guarantee no name clashes.
- tmpfile=`mktemp cmdline.XXXXXX` || \
- fatal "ERROR: cannot create temporary file "
- echo "cmdline: $cmdline" > $tmpfile
-
- tmpfile=`mktemp sysinfo.XXXXXX` || \
- fatal "ERROR: cannot create temporary file " $tmpfile
- echo "sysinfo: `client_sysinfo`" > $tmpfile
+ # Add the necessary info to special files in our temporary directory.
+ echo "cmdline: $cmdline" > cmdline
+ echo "sysinfo: `client_sysinfo`" > sysinfo
}
# function client_sysinfo
@@ -343,9 +342,6 @@ function package_request {
# client -> "request:"
# server -> "ready:"
# client -> $tar_client
-#
-# $tmpdir_client is provided on the request so that the server knows what
-# the tar file will expand to.
function send_request {
echo "request:" >&3
# Get the server's response.
@@ -404,7 +400,7 @@ function unpack_response {
tar -xzf $tar_server || \
fatal "ERROR: Unpacking of server response, $tar_server, failed"
- # Identify the server's request tree. The tar file should have expanded
+ # Identify the server's response tree. The tar file should have expanded
# into a single directory named to match $tmpdir_prefix_server.??????
# which should now be the only item in the current directory.
test "`ls | wc -l`" = 1 || \
@@ -419,34 +415,39 @@ function unpack_response {
# Check the contents of the expanded directory. It should contain:
# 1) a file called stdout
# 2) a file called stderr
- # 3) a directory named to match stap??????
- test "`ls $tmpdir_server | wc -l`" = 3 || \
- fatal "ERROR: Wrong number of files after expansion of server's tar file"
+ # 3) optionally a directory named to match stap??????
+ local num_files=`ls $tmpdir_server | wc -l`
+ test $num_files = 3 -o $num_files = 2 || \
+ fatal "ERROR: Wrong number of files in server's temp directory"
test -f $tmpdir_server/stdout || \
fatal "ERROR: `pwd`/$tmpdir_server/stdout does not exist or is not a regular file"
test -f $tmpdir_server/stderr || \
fatal "ERROR: `pwd`/$tmpdir_server/stderr does not exist or is not a regular file"
+ # See if there is a systemtap temp directory
tmpdir_stap=`ls $tmpdir_server | grep stap`
tmpdir_stap=`expr "$tmpdir_stap" : "\\\(stap......\\\)"`
- test "X$tmpdir_stap" = "X" && \
- fatal "ERROR: `pwd`/$tmpdir_server/stap?????? does not exist"
- test -d $tmpdir_server/$tmpdir_stap || \
- fatal "ERROR: `pwd`/$tmpdir_server/$tmpdir_stap is not a directory"
-
- # Move the systemtap temp directory to a local temp location, if -k
- # was specified.
- if test $keep_temps = 1; then
- local local_tmpdir_stap=`mktemp -dt stapXXXXXX` || \
- fatal "ERROR: cannot create temporary directory " $local_tmpdir_stap
- mv $tmpdir_server/$tmpdir_stap/* $local_tmpdir_stap 2>/dev/null
- rm -fr $tmpdir_server/$tmpdir_stap
-
- # Correct the name of the temp directory in the server's stderr output
- sed -i "s,^Keeping temporary directory.*,Keeping temporary directory \"$local_tmpdir_stap\"," $tmpdir_server/stderr
- tmpdir_stap=$local_tmpdir_stap
- else
- tmpdir_stap=`pwd`/$tmpdir_stap
+ if test "X$tmpdir_stap" != "X"; then
+ test -d $tmpdir_server/$tmpdir_stap || \
+ fatal "ERROR: `pwd`/$tmpdir_server/$tmpdir_stap is not a directory"
+
+ # Move the systemtap temp directory to a local temp location, if -k
+ # was specified.
+ if test $keep_temps = 1; then
+ local local_tmpdir_stap=`mktemp -dt stapXXXXXX` || \
+ fatal "ERROR: cannot create temporary directory " $local_tmpdir_stap
+ mv $tmpdir_server/$tmpdir_stap/* $local_tmpdir_stap 2>/dev/null
+ rm -fr $tmpdir_server/$tmpdir_stap
+
+ # Correct the name of the temp directory in the server's stderr output
+ sed -i "s,^Keeping temporary directory.*,Keeping temporary directory \"$local_tmpdir_stap\"," $tmpdir_server/stderr
+ tmpdir_stap=$local_tmpdir_stap
+ else
+ tmpdir_stap=`pwd`/$tmpdir_stap
+ fi
+
+ # Make sure we own the systemtap temp directory if we are root.
+ test $EUID = 0 && chown $EUID:$EUID $tmpdir_stap
fi
# Move the contents of the server's tmpdir down one level to the
@@ -454,95 +455,57 @@ function unpack_response {
mv $tmpdir_server/* . 2>/dev/null
rm -fr $tmpdir_server
tmpdir_server=`pwd`
-
- # Make sure we own the systemtap temp directory if we are root.
- test $EUID = 0 && chown $EUID:$EUID $tmpdir_stap
}
# function: find_and_connect_to_server
#
-# Find and establish connection with a compatibale stap server.
+# Find and establish connection with a compatible stap server.
function find_and_connect_to_server {
- # Find a server
- server=`avahi-browse $avahi_service_tag --terminate -r 2>/dev/null | match_server`
- port=`expr "$server" : '[^/]*/\(.*\)'`
- server=`expr "$server" : '\([^/]*\)/.*'`
-
- test "X$server" != "X" || \
- fatal "ERROR: cannot find a server"
-
- test "X$port" != "X" || \
- fatal "ERROR: server port not provided"
-
- # Open a connection to the server
- if ! exec 3<> /dev/tcp/$server/$port; then
- fatal "ERROR: cannot connect to server at /dev/tcp/$server/$port"
- fi
+ # Use a temp file here instead of a pipeline so that the side effects
+ # of choose_server are seen by the rest of this script.
+ cd $tmpdir_client
+ stap-find-servers > servers
+ choose_server < servers
+ rm -fr servers
}
-# function: match_server
+# function: choose_server
#
-# Find a suitable server using the avahi-browse output provided on stdin.
-function match_server {
- local server_ip
-
- # Loop over the avahi service descriptors.
- while read
+# Examine each line from stdin and attempt to connect to each server
+# specified until successful.
+function choose_server {
+ local num_servers=0
+ local name
+ while read name server port remain
do
- # Examine the next service descriptor
- # Is it a stap server?
- (echo $REPLY | grep -q "^=.*_stap") || continue
-
- # Get the details of the service
- local service_tag equal data
- while read service_tag equal service_data
- do
- case $service_tag in
- '=' )
- break ;;
- hostname )
- server_name=`expr "$service_data" : '\[\([^]]*\)\]'`
- ;;
- address )
- # Sometimes (seems random), avahi-resolve-host-name resolves a local server to its
- # hardware address rather its ip address. Keep trying until we get
- # an ip address.
- server_ip=`expr "$service_data" : '\[\([^]]*\)\]'`
- local attempt
- for ((attempt=0; $attempt < 5; ++attempt))
- do
- server_ip=`expr "$server_ip" : '^\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\)$'`
- if test "X$server_ip" != "X"; then
- break
- fi
- # Resolve the server.domain to an ip address.
- server_ip=`avahi-resolve-host-name $hostname`
- server_ip=`expr "$server_ip" : '.* \(.*\)$'`
- done
- ;;
- port )
- port=`expr "$service_data" : '\[\([^]]*\)\]'`
- ;;
- txt )
- sysinfo_server=`expr "$service_data" : '\[\"\([^]]*\)\"\]'`
- ;;
- * )
- break ;;
- esac
- done
+ num_servers=$(($num_servers + 1))
+
+ if test "X$server" = "X"; then
+ fatal "ERROR: server ip address not provided"
+ fi
- # It is a stap server, but is it compatible?
- if test "$sysinfo_server" != "`client_sysinfo`"; then
- server_ip=
- continue
+ if test "X$port" = "X"; then
+ fatal "ERROR: server port not provided"
fi
- if test "X$server_ip" != "X"; then
- break
+ if connect_to_server $server $port; then
+ return 0
fi
done
- echo $server_ip/$port
+ if test num_servers = 0; then
+ fatal "ERROR: cannot find a server"
+ fi
+
+ fatal "ERROR: unable to connect to a server"
+}
+
+# function: connect_to_server IP PORT
+#
+# Establish connection with the given server
+function connect_to_server {
+ # Open a connection to the server
+ exec 3<> /dev/tcp/$1/$2
}
# function: disconnect_from_server
@@ -568,15 +531,40 @@ function stream_output {
# Call staprun using the module returned from the server, if requested.
function maybe_call_staprun {
if test $p_phase = 5; then
+ # Can't call staprun without a module.
+ test "X$tmpdir_stap" = "X" && return
+
+ local mod_name=`ls $tmpdir_stap | grep '.ko$'`
+ test "X$mod_name" != "X" || \
+ fatal "ERROR: no module to run in $tmpdir_stap"
+
+ # We have a module. Try to run it
for ((--v_level; $v_level > 0; --v_level))
do
staprun_opts="$staprun_opts -v"
done
- staprun $staprun_opts \
+ PATH=`staprun_PATH` staprun $staprun_opts \
$tmpdir_stap/`ls $tmpdir_stap | grep '.ko$'`
fi
}
+# function: staprun_PATH
+#
+# Compute a PATH suitable for running staprun.
+function staprun_PATH {
+ # staprun may invoke 'stap'. So we can use the current PATH if we were
+ # not invoked as 'stap' or we are not the first 'stap' on the PATH.
+ local first_stap=`which stap 2>/dev/null`
+ if test `which $0 2>/dev/null` != $first_stap; then
+ echo "$PATH"
+ return
+ fi
+
+ # Otherwise, remove the PATH component where we live from the PATH
+ local PATH_component=`dirname $first_stap`
+ echo $PATH | sed "s,$PATH_component,,g"
+}
+
# function: check_server_error SERVER_RESPONSE
#
# Check the given server response for an error message.
@@ -591,6 +579,7 @@ function check_server_error {
# Prints its arguments to stderr and exits
function fatal {
echo $0: "$@" >&2
+ disconnect_from_server
cleanup
exit 1
}
@@ -602,6 +591,7 @@ function fatal {
function server_fatal {
echo $0: "$@" >&2
cat <&3 >&2
+ disconnect_from_server
cleanup
exit 1
}
diff --git a/stap-find-or-start-server b/stap-find-or-start-server
new file mode 100755
index 00000000..0ea0ef43
--- /dev/null
+++ b/stap-find-or-start-server
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# Find or start a systemtap server
+#
+# Copyright (C) 2008 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+
+# This script attempts to find a systemtap server. If one is found, it
+# simply exits with 0.
+#
+# Otherwise, it attempts to start a server. If succesful, it echoes the
+# process id and exits with 0.
+#
+# Otherwise, it exits with 1
+
+# Is there a server available?
+stap-find-servers >/dev/null 2>&1 && exit 0
+
+# No server available, try to start one.
+pid=`stap-start-server`
+if test $? = 0; then
+ echo $pid
+ # Make sure the server is started
+ for ((attempt=0; $attempt < 5; ++attempt))
+ do
+ stap-find-servers >/dev/null 2>&1 && exit 0
+ sleep 1
+ done
+fi
+
+# Could not find or start a server
+exit 1
diff --git a/stap-find-servers b/stap-find-servers
new file mode 100755
index 00000000..9e7b633d
--- /dev/null
+++ b/stap-find-servers
@@ -0,0 +1,128 @@
+#!/bin/bash
+
+# Find compile servers for systemtap
+#
+# Copyright (C) 2008 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+
+# This script uses avahi to find systemtap compile servers on the local
+# network. Information about each server found is printed to stdout.
+
+#-----------------------------------------------------------------------------
+# Helper functions.
+#-----------------------------------------------------------------------------
+# function: configuration
+function configuration {
+ avahi_service_tag=_stap._tcp
+}
+
+# function: initialization
+function initialization {
+ rc=1 # not found yet
+ if test "X$1" = "X--all"; then
+ find_all=1
+ else
+ find_all=0
+ fi
+}
+
+# function: find_and_connect_to_server
+#
+# Find and establish connection with a compatibale stap server.
+function find_servers {
+ # Find a server
+ avahi-browse $avahi_service_tag --terminate -r 2>/dev/null | match_server
+ rc=$?
+}
+
+# function: match_server
+#
+# Find a suitable server using the avahi-browse output provided on stdin.
+function match_server {
+ local server_ip
+ local server_name
+ local server_sysinfo
+ local server_port
+ local rc=1 # not found yet
+
+ # Loop over the avahi service descriptors.
+ while read
+ do
+ # Examine the next service descriptor
+ # Is it a stap server?
+ (echo $REPLY | grep -q "^=.*_stap") || continue
+
+ # Get the details of the service
+ local service_tag equal data
+ while read service_tag equal service_data
+ do
+ case $service_tag in
+ '=' )
+ break ;;
+ hostname )
+ server_name=`expr "$service_data" : '\[\([^]]*\)\]'`
+ ;;
+ address )
+ # Sometimes (seems random), avahi-resolve-host-name resolves a local server to its
+ # hardware address rather its ip address. Keep trying until we get
+ # an ip address.
+ server_ip=`expr "$service_data" : '\[\([^]]*\)\]'`
+ local attempt
+ for ((attempt=0; $attempt < 5; ++attempt))
+ do
+ server_ip=`expr "$server_ip" : '^\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\)$'`
+ if test "X$server_ip" != "X"; then
+ break
+ fi
+ # Resolve the server.domain to an ip address.
+ server_ip=`avahi-resolve-host-name $hostname`
+ server_ip=`expr "$server_ip" : '.* \(.*\)$'`
+ done
+ ;;
+ port )
+ server_port=`expr "$service_data" : '\[\([^]]*\)\]'`
+ ;;
+ txt )
+ server_sysinfo=`expr "$service_data" : '\[\"\([^]]*\)\"\]'`
+ ;;
+ * )
+ break ;;
+ esac
+ done
+
+ # It is a stap server, but is it compatible?
+ if test $find_all = 0 -a "$server_sysinfo" != "`client_sysinfo`"; then
+ continue
+ fi
+
+ # It's compatible, or we're finding all servers. Print a summary line
+ echo $server_name $server_ip $server_port "'$server_sysinfo'"
+ rc=0
+ done
+
+ exit $rc
+}
+
+# function client_sysinfo
+#
+# Generate the client's sysinfo and echo it to stdout
+function client_sysinfo {
+ if test "X$sysinfo_client" = "X"; then
+ # Add some info from uname
+ sysinfo_client="`uname -rvm`"
+ fi
+ echo $sysinfo_client
+}
+
+#-----------------------------------------------------------------------------
+# Beginning of main line execution.
+#-----------------------------------------------------------------------------
+configuration
+initialization "$@"
+find_servers
+
+exit $rc
diff --git a/stap-server b/stap-server
index 16ffe8ee..e825c49a 100755
--- a/stap-server
+++ b/stap-server
@@ -13,6 +13,9 @@
# contained in the unpacked tree to build the requested systemtap kernel module.
# This module is then written to stdout.
+# Catch ctrl-c and other termination signals
+trap 'terminate' SIGTERM SIGINT
+
#-----------------------------------------------------------------------------
# Helper functions.
#-----------------------------------------------------------------------------
@@ -143,20 +146,20 @@ function check_compatibility {
# function: read_data_file PREFIX
#
-# Find a file whose name matches '$1.??????' whose first line
+# Find a file whose name is '$1' and whose first line
# contents are '$1: .*'. Read and echo the first line.
function read_data_file {
- for f in `ls $1.??????`
- do
- read < $f
- line=$REPLY
- data=`expr "$line" : "$1: \\\(.*\\\)"`
- if test "X$data" != "X"; then
- echo $data
- return
- fi
- done
- fatal "ERROR: Data file for $1 not found"
+ test -f $1 || \
+ fatal "ERROR: Data file $1 not found"
+
+ read < $1
+ line=$REPLY
+ data=`expr "$line" : "$1: \\\(.*\\\)"`
+ if test "X$data" != "X"; then
+ echo $data
+ return
+ fi
+ fatal "ERROR: Data in file $1 is incorrect"
}
# function: parse_options [ STAP-OPTIONS ]
@@ -312,6 +315,7 @@ function call_stap {
else
server_p_phase=$p_phase
fi
+
eval stap $cmdline -k -p $server_p_phase \
>> $tmpdir_server/stdout \
2>> $tmpdir_server/stderr
@@ -328,19 +332,21 @@ function create_response {
tmpdir_line=`cat stderr | grep "Keeping temp"`
tmpdir_stap=`expr "$tmpdir_line" : '.*"\(.*\)".*'`
- # Remove the message about keeping th<e stap temp directory from stderr, unless
+ # Remove the message about keeping the stap temp directory from stderr, unless
# the user did request to keep it.
- if test $keep_temps != 1; then
- sed -i "/^Keeping temp/d" stderr
+ if test "X$tmpdir_stap" != "X"; then
+ if test $keep_temps != 1; then
+ sed -i "/^Keeping temp/d" stderr
+ fi
+
+ # Add the contents of the stap temp directory to the server output directory
+ ln -s $tmpdir_stap `basename $tmpdir_stap`
fi
# If the user specified -p5, remove the name of the kernel module from stdout.
if test $p_phase = 5; then
sed -i '/\.ko$/d' stdout
fi
-
- # Add the contents of the stap temp directory to the server output directory
- ln -s $tmpdir_stap `basename $tmpdir_stap`
}
# function: package_response
@@ -404,6 +410,15 @@ function cleanup {
fi
}
+# function: terminate
+#
+# Terminate gracefully.
+function terminate {
+ # Clean up
+ cleanup
+ exit
+}
+
#-----------------------------------------------------------------------------
# Beginning of main line execution.
#-----------------------------------------------------------------------------
diff --git a/stap-serverd b/stap-serverd
index eaaeda00..af4b2717 100755
--- a/stap-serverd
+++ b/stap-serverd
@@ -13,8 +13,8 @@
# incoming connections. When a connection is detected, the stap-server script
# is run to handle the request.
-# Catch ctrl-c
-trap 'handle_sigint' SIGINT
+# Catch ctrl-c and other termination signals
+trap 'terminate' SIGTERM SIGINT
#-----------------------------------------------------------------------------
# Helper functions.
@@ -61,7 +61,10 @@ function listen {
# Loop forever accepting requests
while true
do
- nc -l $port < $fifo_name | stap-server $((port + 1)) > $fifo_name 2>&1
+ # Run this in the background and wait for it. This way any signals
+ # received (i.e. SIGTERM) will be processed.
+ nc -l $port < $fifo_name | stap-server $((port + 1)) > $fifo_name 2>&1 &
+ wait %nc
done
}
@@ -74,13 +77,24 @@ function fatal {
exit 1
}
-# function: handle_sigint
+# function: terminate
#
-# Terminate gracefully when SIGINT is received.
-function handle_sigint {
- echo "$0: received SIGINT. Exiting."
+# Terminate gracefully.
+function terminate {
+ echo "$0: Exiting"
+
+ # Kill the running 'avahi-publish-service' job
+ kill -s SIGTERM %avahi-publish-service 2> /dev/null
+ wait %avahi-publish-service 2> /dev/null
+
+ # Kill any running 'nc -l' job.
+ kill -s SIGTERM "%nc -l" 2> /dev/null
+ wait "%nc - l" 2> /dev/null
+
+ # Clean up
cd `dirname $tmpdir`
rm -fr $tmpdir
+
exit
}
diff --git a/stap-start-server b/stap-start-server
new file mode 100755
index 00000000..d143e269
--- /dev/null
+++ b/stap-start-server
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Start a systemtap server
+#
+# Copyright (C) 2008 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+
+# This script attempts to start a systemtap server and echoes the
+# process id, if successful.
+
+# start the server
+stap-serverd </dev/null >/dev/null 2>&1 &
+server_pid=$!
+
+# Exit if the server did not start ok
+(ps | grep -q $server_pid) || exit 1
+
+# The server started ok. Echo its process id.
+echo $server_pid
+exit 0
diff --git a/stap-stop-server b/stap-stop-server
new file mode 100755
index 00000000..5afcf705
--- /dev/null
+++ b/stap-stop-server
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Start a systemtap server
+#
+# Copyright (C) 2008 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+
+# This script attempts to stop a systemtap server with the
+# given pid.
+
+# Get the process id.
+pid=$1
+if test "X$pid" = "X"; then
+ echo "Usage: $0 PROCESS_ID" >&2
+ exit 1
+fi
+
+# Verify that it is a systemtap server
+(ps -a | grep stap-serverd | grep -q $pid)
+if test $? != 0; then
+ echo "$pid is not a systemtap server"
+ exit 1
+fi
+
+# Try to kill the server
+kill -s SIGTERM $pid
diff --git a/stapprobes.5.in b/stapprobes.5.in
index 700452a7..24075248 100644
--- a/stapprobes.5.in
+++ b/stapprobes.5.in
@@ -329,6 +329,19 @@ may be repeated to follow more levels of pointers.
$var[N]
indexes into an array. The index is given with a
literal number.
+.TP
+$$vars
+expands to a character string that is equivalent to
+sprintf("parm1=%x ... parmN=%x var1=%x ... varN=%x", parm1, ..., parmN,
+var1, ..., varN)
+.TP
+$$locals
+expands to a character string that is equivalent to
+sprintf("var1=%x ... varN=%x", var1, ..., varN)
+.TP
+$$parms
+expands to a character string that is equivalent to
+sprintf("parm1=%x ... parmN=%x", parm1, ..., parmN)
.PP
For ".return" probes, context variables other than the "$return"
value itself are only available for the function call parameters.
@@ -367,6 +380,8 @@ process(PID).syscall
process("PATH").syscall
process(PID).syscall.return
process("PATH").syscall.return
+process(PID).itrace
+process("PATH").itrace
.ESAMPLE
.PP
A
@@ -391,6 +406,9 @@ A
probe gets called when a thread described by PID or PATH returns from a
system call. The system call number is available in the "$syscall"
context variable.
+A
+.B .itrace
+probe gets called for every single step of the process described by PID or PATH.
.PP
Note that
.I PATH
diff --git a/systemtap.base/itrace.exp b/systemtap.base/itrace.exp
new file mode 100644
index 00000000..4b73ac1c
--- /dev/null
+++ b/systemtap.base/itrace.exp
@@ -0,0 +1,102 @@
+# itrace test
+
+# Initialize variables
+set utrace_support_found 0
+set exepath "[pwd]/ls_[pid]"
+
+set itrace1_script {
+ global instrs = 0
+ probe begin { printf("systemtap starting probe\n") }
+ probe process("%s").itrace
+ {
+ instrs += 1
+ if (instrs == 5)
+ exit()
+ }
+
+
+ probe end { printf("systemtap ending probe\n")
+ printf("itraced = %%d\n", instrs)
+ }
+}
+set itrace1_script_output "itraced = 5\r\n"
+
+set itrace2_script {
+ global instrs = 0, itrace_on = 0, start_timer = 0
+ probe begin { start_timer = 1; printf("systemtap starting probe\n") }
+ probe process("%s").itrace if (itrace_on)
+ {
+ instrs += 1
+ if (instrs == 5)
+ exit()
+ }
+
+
+ probe timer.ms(1) if (start_timer)
+ {
+ itrace_on = 1
+ }
+
+ probe timer.ms(10) if (start_timer)
+ {
+ itrace_on = 0
+ }
+ probe end { printf("systemtap ending probe\n")
+ printf("itraced = %%d\n", instrs)
+ }
+}
+set itrace2_script_output "itraced = 5\r\n"
+
+
+# Set up our own copy of /bin/ls, to make testing for a particular
+# executable easy. We can't use 'ln' here, since we might be creating
+# a cross-device link. We can't use 'ln -s' here, since the kernel
+# resolves the symbolic link and reports that /bin/ls is being
+# exec'ed (instead of our local copy).
+if {[catch {exec cp /bin/ls $exepath} res]} {
+ fail "unable to copy /bin/ls: $res"
+ return
+}
+
+# "load" generation function for stap_run. It spawns our own copy of
+# /bin/ls, waits 5 seconds, then kills it.
+proc run_ls_5_sec {} {
+ global exepath
+
+ spawn $exepath
+ set exe_id $spawn_id
+ after 5000;
+ exec kill -INT -[exp_pid -i $exe_id]
+ return 0;
+}
+
+
+# Try to find utrace_attach symbol in /proc/kallsyms
+set path "/proc/kallsyms"
+if {! [catch {exec grep -q utrace_attach $path} dummy]} {
+ set utrace_support_found 1
+}
+
+set TEST_NAME "itrace1"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} elseif {![installtest_p]} {
+ untested "$TEST_NAME : not installtest_p"
+} else {
+ set script [format $itrace1_script $exepath]
+ stap_run $TEST_NAME run_ls_5_sec $itrace1_script_output -e $script
+}
+
+
+set TEST_NAME "itrace2"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} elseif {![installtest_p]} {
+ untested "$TEST_NAME : not installtest_p"
+} else {
+ set script [format $itrace2_script $exepath]
+ stap_run $TEST_NAME run_ls_5_sec $itrace2_script_output -e $script
+}
+
+# Cleanup
+exec rm -f $exepath
diff --git a/systemtap.spec b/systemtap.spec
index deec1d28..503022d1 100644
--- a/systemtap.spec
+++ b/systemtap.spec
@@ -178,6 +178,10 @@ exit 0
%{_bindir}/stap
%{_bindir}/stap-server
%{_bindir}/stap-serverd
+%{_bindir}/stap-find-servers
+%{_bindir}/stap-start-server
+%{_bindir}/stap-find-or-start-server
+%{_bindir}/stap-stop-server
%{_mandir}/man1/*
%{_mandir}/man5/*
diff --git a/tapset/ChangeLog b/tapset/ChangeLog
index 29c10507..b2592e1e 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,3 +1,17 @@
+
+2008-08-04 Wenji Huang <wenji.huang@oracle.com>
+
+ * syscall.stp: Change $path to $pathname for 2.6.27.
+ * syscall2.stp: Ditto.
+
+2008-08-03 Wenji Huang <wenji.huang@oracle.com>
+
+ * vfs.stp(add_to_page_cache): Correct for 2.6.27.
+
+2008-07-25 Zhaolei <zhaolei@cn.fujitsu.com>
+
+ * syscalls2.stp: Add sys_unlinkat.
+
2008-07-18 Zhaolei <zhaolei@cn.fujitsu.com>
* syscalls2.stp: Add sys_symlinkat.
diff --git a/tapset/syscalls.stp b/tapset/syscalls.stp
index 11c2bdf7..7fd942af 100644
--- a/tapset/syscalls.stp
+++ b/tapset/syscalls.stp
@@ -1715,13 +1715,21 @@ probe syscall.getuid.return =
# void __user *value, size_t size)
probe syscall.getxattr = kernel.function("sys_getxattr") {
name = "getxattr"
+%( kernel_v > "2.6.26" %?
+ path = user_string($pathname)
+%:
path = user_string($path)
+%)
# FIXME
name2 = user_string($name)
value_uaddr = $value
size = $size
argstr = sprintf("%s, %s, %p, %d",
+%( kernel_v > "2.6.26" %?
+ user_string_quoted($pathname),
+%:
user_string_quoted($path),
+%)
user_string_quoted($name),
value_uaddr, size)
}
@@ -1754,11 +1762,18 @@ probe syscall.init_module.return = kernel.function("sys_init_module").return ? {
probe syscall.inotify_add_watch = kernel.function("sys_inotify_add_watch") ? {
name = "inotify_add_watch"
fd = $fd
+ mask = $mask
+%( kernel_v > "2.6.26" %?
+ path_uaddr = $pathname
+ path = user_string($pathname)
+ argstr = sprintf("%d, %s, %d", $fd, user_string_quoted($pathname), $mask)
+%:
path_uaddr = $path
path = user_string($path)
- mask = $mask
argstr = sprintf("%d, %s, %d", $fd, user_string_quoted($path), $mask)
+%)
}
+
probe syscall.inotify_add_watch.return = kernel.function("sys_inotify_add_watch").return ? {
name = "inotify_add_watch"
retstr = returnstr(1)
@@ -2081,13 +2096,21 @@ probe syscall.lchown16.return = kernel.function("sys_lchown16").return ? {
#
probe syscall.lgetxattr = kernel.function("sys_lgetxattr") {
name = "lgetxattr"
+%( kernel_v > "2.6.26" %?
+ path = user_string($pathname)
+%:
path = user_string($path)
+%)
# FIXME
name2 = user_string($name)
value_uaddr = $value
size = $size
argstr = sprintf("%s, %s, %p, %d",
+%( kernel_v > "2.6.26" %?
+ user_string_quoted($pathname),
+%:
user_string_quoted($path),
+%)
user_string_quoted($name),
value_uaddr, size)
}
@@ -2156,11 +2179,17 @@ probe syscall.listen.return = kernel.function("sys_listen").return ? {
#
probe syscall.listxattr = kernel.function("sys_listxattr") {
name = "listxattr"
- path_uaddr = $path
- path = user_string($path)
list_uaddr = $list
size = $size
+%( kernel_v > "2.6.26" %?
+ path_uaddr = $pathname
+ path = user_string($pathname)
+ argstr = sprintf("%s, %p, %d", user_string_quoted($pathname), $list, $size)
+%:
+ path_uaddr = $path
+ path = user_string($path)
argstr = sprintf("%s, %p, %d", user_string_quoted($path), $list, $size)
+%)
}
probe syscall.listxattr.return = kernel.function("sys_listxattr").return {
name = "listxattr"
@@ -2172,11 +2201,17 @@ probe syscall.listxattr.return = kernel.function("sys_listxattr").return {
#
probe syscall.llistxattr = kernel.function("sys_llistxattr") {
name = "llistxattr"
- path_uaddr = $path
- path = user_string($path)
list_uaddr = $list
size = $size
+%( kernel_v > "2.6.26" %?
+ path_uaddr = $pathname
+ path = user_string($pathname)
+ argstr = sprintf("%s, %p, %d", user_string_quoted($pathname), $list, $size)
+%:
+ path_uaddr = $path
+ path = user_string($path)
argstr = sprintf("%s, %p, %d", user_string_quoted($path), $list, $size)
+%)
}
probe syscall.llistxattr.return = kernel.function("sys_llistxattr").return {
name = "llistxattr"
@@ -2225,11 +2260,17 @@ probe syscall.lookup_dcookie.return = kernel.function("sys_lookup_dcookie").retu
#
probe syscall.lremovexattr = kernel.function("sys_lremovexattr") {
name = "lremovexattr"
- path_uaddr = $path
- path = user_string($path)
name_uaddr = $name
name2 = user_string($name)
+%( kernel_v > "2.6.26" %?
+ path_uaddr = $pathname
+ path = user_string($pathname)
+ argstr = sprintf("%s, %s", user_string_quoted($pathname), user_string_quoted($name))
+%:
+ path_uaddr = $path
+ path = user_string($path)
argstr = sprintf("%s, %s", user_string_quoted($path), user_string_quoted($name))
+%)
}
probe syscall.lremovexattr.return = kernel.function("sys_lremovexattr").return {
name = "lremovexattr"
@@ -2261,15 +2302,24 @@ probe syscall.lseek.return = kernel.function("sys_lseek").return {
#
probe syscall.lsetxattr = kernel.function("sys_lsetxattr") {
name = "lsetxattr"
+%( kernel_v > "2.6.26" %?
+ path_uaddr = $pathname
+ path = user_string($pathname)
+%:
path_uaddr = $path
path = user_string($path)
+%)
name_uaddr = $name
name_str = user_string($name)
value_uaddr = $value
size = $size
flags = $flags
argstr = sprintf("%s, %s, %p, %d, %d",
+%( kernel_v > "2.6.26" %?
+ user_string_quoted($pathname),
+%:
user_string_quoted($path),
+%)
user_string_quoted($name),
value_uaddr, $size, $flags)
}
diff --git a/tapset/syscalls2.stp b/tapset/syscalls2.stp
index 910193ef..57d190e3 100644
--- a/tapset/syscalls2.stp
+++ b/tapset/syscalls2.stp
@@ -623,12 +623,17 @@ probe syscall.readlink.return = kernel.function("sys_readlink").return {
probe syscall.readlinkat = kernel.function("sys_readlinkat") ? {
name = "readlinkat"
dfd = $dfd
- path = user_string($path)
buf_uaddr = $buf
bufsiz = $bufsiz
- argstr = sprintf("%s, %s, %p, %d", _dfd_str($dfd), user_string_quoted($path),
- $buf, $bufsiz)
+%( kernel_v > "2.6.26" %?
+ path = user_string($pathname)
+ argstr = sprintf("%s, %s, %p, %d", _dfd_str($dfd), user_string_quoted($pathname), $buf, $bufsiz)
+%:
+ path = user_string($path)
+ argstr = sprintf("%s, %s, %p, %d", _dfd_str($dfd), user_string_quoted($path), $buf, $bufsiz)
+%)
}
+
probe syscall.readlinkat.return = kernel.function("sys_readlinkat").return ? {
name = "readlinkat"
retstr = returnstr(1)
@@ -806,10 +811,17 @@ probe syscall.remap_file_pages.return =
#
probe syscall.removexattr = kernel.function("sys_removexattr") {
name = "removexattr"
- path = user_string($path)
name_str = user_string($name)
+%( kernel_v > "2.6.26" %?
+ path = user_string($pathname)
+ argstr = sprintf("%s, %s", user_string_quoted($pathname),
+ user_string_quoted($name))
+%:
+ path = user_string($path)
argstr = sprintf("%s, %s", user_string_quoted($path),
user_string_quoted($name))
+%)
+
}
probe syscall.removexattr.return = kernel.function("sys_removexattr").return {
name = "removexattr"
@@ -1978,15 +1990,24 @@ probe syscall.setuid.return =
#
probe syscall.setxattr = kernel.function("sys_setxattr") {
name = "setxattr"
+%( kernel_v > "2.6.26" %?
+ path_uaddr = $pathname
+ path = user_string($pathname)
+%:
path_uaddr = $path
path = user_string($path)
+%)
name_uaddr = $name
name_str = user_string($name)
value_uaddr = $value
size = $size
flags = $flags
argstr = sprintf("%s, %s, %p, %d, %d",
+%( kernel_v > "2.6.26" %?
+ user_string_quoted($pathname),
+%:
user_string_quoted($path),
+%)
user_string_quoted($name),
value_uaddr, $size, $flags)
}
@@ -2376,10 +2397,16 @@ probe syscall.statfs =
kernel.function("compat_sys_statfs") ?
{
name = "statfs"
- path = user_string($path)
buf_uaddr = $buf
+%( kernel_v > "2.6.26" %?
+ path = user_string($pathname)
+ argstr = sprintf("%s, %p", user_string_quoted($pathname), $buf)
+%:
+ path = user_string($path)
argstr = sprintf("%s, %p", user_string_quoted($path), $buf)
+%)
}
+
probe syscall.statfs.return =
kernel.function("sys_statfs").return,
kernel.function("compat_sys_statfs").return ?
@@ -2398,11 +2425,17 @@ probe syscall.statfs64 =
kernel.function("compat_sys_statfs64") ?
{
name = "statfs"
- path = user_string($path)
sz = $sz
buf_uaddr = $buf
+%( kernel_v > "2.6.26" %?
+ path = user_string($pathname)
+ argstr = sprintf("%s, %d, %p", user_string_quoted($pathname), $sz, $buf)
+%:
+ path = user_string($path)
argstr = sprintf("%s, %d, %p", user_string_quoted($path), $sz, $buf)
+%)
}
+
probe syscall.statfs64.return =
kernel.function("sys_statfs64").return ?,
kernel.function("compat_sys_statfs64").return ?
@@ -2899,6 +2932,25 @@ probe syscall.unlink.return = kernel.function("sys_unlink").return {
retstr = returnstr(1)
}
+# unlinkat ___________________________________________________
+# new function with 2.6.16
+# long sys_unlinkat(int dfd, const char __user *pathname,
+# int flag)
+probe syscall.unlinkat = kernel.function("sys_unlinkat") ? {
+ name = "unlinkat"
+ dfd = $dfd
+ dfd_str = _dfd_str($dfd)
+ pathname = $pathname
+ pathname_str = user_string($pathname)
+ flag = $flag
+ flag_str = _at_flag_str($flag)
+ argstr = sprintf("%s, %s, %s", dfd_str, user_string_quoted($pathname), flag_str)
+}
+probe syscall.unlinkat.return = kernel.function("sys_unlinkat").return ? {
+ name = "unlinkat"
+ retstr = returnstr(1)
+}
+
# unshare ____________________________________________________
# new function with 2.6.16
# long sys_unshare(unsigned long unshare_flags)
diff --git a/tapset/vfs.stp b/tapset/vfs.stp
index 46bc3d21..1ea8fc8e 100644
--- a/tapset/vfs.stp
+++ b/tapset/vfs.stp
@@ -744,7 +744,11 @@ probe vfs.do_mpage_readpage.return = kernel.function ("do_mpage_readpage").retur
units = "pages"
}
+%( kernel_v > "2.6.26" %?
+probe vfs.add_to_page_cache = kernel.function ("add_to_page_cache_locked")
+%:
probe vfs.add_to_page_cache = kernel.function ("add_to_page_cache")
+%)
{
dev = $mapping->host->i_sb->s_dev
devname = __find_bdevname(dev, $mapping->host->i_sb->s_bdev)
@@ -756,7 +760,12 @@ probe vfs.add_to_page_cache = kernel.function ("add_to_page_cache")
name = "vfs.add_to_page_cache"
argstr = sprintf("%d, %d", ino, index)
}
+
+%( kernel_v > "2.6.26" %?
+probe vfs.add_to_page_cache.return = kernel.function ("add_to_page_cache_locked").return
+%:
probe vfs.add_to_page_cache.return = kernel.function ("add_to_page_cache").return
+%)
{
name = "vfs.add_to_page_cache"
retstr = sprintf("%d", $return)
diff --git a/tapsets.cxx b/tapsets.cxx
index b9b4fcff..d06f7cea 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2485,7 +2485,7 @@ struct dwarf_query : public base_query
// It arises because we sometimes try to fix up slightly-off
// .statement() probes (something we find out in fairly low-level).
//
-// An alternative would be to put some more intellgence into query_cu(),
+// An alternative would be to put some more intelligence into query_cu(),
// and have it print additional suggestions after finding that
// q->dw.iterate_over_srcfile_lines resulted in no new finished_results.
@@ -4285,6 +4285,84 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
return;
}
+ if (e->base_name == "$$vars"
+ || e->base_name == "$$parms"
+ || e->base_name == "$$locals")
+ {
+ Dwarf_Die *scopes;
+ if (dwarf_getscopes_die (scope_die, &scopes) == 0)
+ return;
+
+ target_symbol *tsym = new target_symbol;
+ print_format* pf = new print_format;
+
+ // Convert $$parms to sprintf of a list of parms and active local vars
+ // which we recursively evaluate
+ token* tmp_tok = new token;
+ tmp_tok->type = tok_identifier;
+ tmp_tok->content = "sprintf";
+ pf->tok = tmp_tok;
+ pf->print_to_stream = false;
+ pf->print_with_format = true;
+ pf->print_with_delim = false;
+ pf->print_with_newline = false;
+ pf->print_char = false;
+
+ Dwarf_Die result;
+ if (dwarf_child (&scopes[0], &result) == 0)
+ do
+ {
+ switch (dwarf_tag (&result))
+ {
+ case DW_TAG_variable:
+ if (e->base_name == "$$parms")
+ continue;
+ break;
+ case DW_TAG_formal_parameter:
+ if (e->base_name == "$$locals")
+ continue;
+ break;
+
+ default:
+ continue;
+ }
+
+ const char *diename = dwarf_diename (&result);
+ token* sym_tok = new token;
+ sym_tok->location = e->get_tok()->location;
+ sym_tok->type = tok_identifier;
+ sym_tok->content = diename;
+ tsym->tok = sym_tok;
+ tsym->base_name = "$";
+ tsym->base_name += diename;
+ Dwarf_Attribute attr_mem;
+
+ // Ignore any variable that isn't accessible.
+ // dwarf_attr_integrate is checked by literal_stmt_for_local
+ // dwarf_getlocation_addr is checked by translate_location
+ // but if those fail we cannot catch semantic_error.
+ if (dwarf_attr_integrate (&result, DW_AT_location, &attr_mem) != NULL)
+ {
+ Dwarf_Op *expr;
+ size_t len;
+ if (dwarf_getlocation_addr (&attr_mem, addr - q.dw.module_bias,
+ &expr, &len, 1) == 0)
+ continue;
+ this->visit_target_symbol(tsym);
+ pf->raw_components += diename;
+ pf->raw_components += "=%#x ";
+ pf->args.push_back(*(expression**)this->targets.top());
+ }
+ }
+ while (dwarf_siblingof (&result, &result) == 0);
+
+ pf->raw_components += "\\n";
+ pf->components = print_format::string_to_components(pf->raw_components);
+ provide <print_format*> (this, pf);
+
+ return;
+ }
+
// Synthesize a function.
functiondecl *fdecl = new functiondecl;
fdecl->tok = e->tok;
@@ -5376,6 +5454,280 @@ task_finder_derived_probe_group::emit_module_exit (systemtap_session& s)
s.op->newline() << "stap_stop_task_finder();";
}
+// ------------------------------------------------------------------------
+// itrace user-space probes
+// ------------------------------------------------------------------------
+
+
+struct itrace_derived_probe: public derived_probe
+{
+ bool has_path;
+ string path;
+ int64_t pid;
+ int single_step;
+
+ itrace_derived_probe (systemtap_session &s, probe* p, probe_point* l,
+ bool hp, string &pn, int64_t pd, int ss
+ );
+ void join_group (systemtap_session& s);
+};
+
+
+struct itrace_derived_probe_group: public generic_dpg<itrace_derived_probe>
+{
+private:
+ map<string, vector<itrace_derived_probe*> > probes_by_path;
+ typedef map<string, vector<itrace_derived_probe*> >::iterator p_b_path_iterator;
+ map<int64_t, vector<itrace_derived_probe*> > probes_by_pid;
+ typedef map<int64_t, vector<itrace_derived_probe*> >::iterator p_b_pid_iterator;
+ unsigned num_probes;
+
+ void emit_probe_decl (systemtap_session& s, itrace_derived_probe *p);
+
+public:
+ itrace_derived_probe_group(): num_probes(0) { }
+
+ void enroll (itrace_derived_probe* probe);
+ void emit_module_decls (systemtap_session& s);
+ void emit_module_init (systemtap_session& s);
+ void emit_module_exit (systemtap_session& s);
+};
+
+
+itrace_derived_probe::itrace_derived_probe (systemtap_session &s,
+ probe* p, probe_point* l,
+ bool hp, string &pn, int64_t pd,
+ int ss
+ ):
+ derived_probe(p, l), has_path(hp), path(pn), pid(pd), single_step(ss)
+{
+}
+
+
+void
+itrace_derived_probe::join_group (systemtap_session& s)
+{
+ if (! s.itrace_derived_probes)
+ s.itrace_derived_probes = new itrace_derived_probe_group ();
+
+ s.itrace_derived_probes->enroll (this);
+
+ task_finder_derived_probe_group::create_session_group (s);
+}
+
+struct itrace_builder: public derived_probe_builder
+{
+ itrace_builder() {}
+ virtual void build(systemtap_session & sess,
+ probe * base,
+ probe_point * location,
+ std::map<std::string, literal *> const & parameters,
+ vector<derived_probe *> & finished_results)
+ {
+ string path;
+ int64_t pid;
+ int single_step;
+
+ bool has_path = get_param (parameters, TOK_PROCESS, path);
+ bool has_pid = get_param (parameters, TOK_PROCESS, pid);
+ assert (has_path || has_pid);
+
+ single_step = 1;
+
+ // If we have a path, we need to validate it.
+ if (has_path)
+ {
+ string::size_type start_pos, end_pos;
+ string component;
+
+ // Make sure it starts with '/'.
+ if (path[0] != '/')
+ throw semantic_error ("process path must start with a '/'",
+ location->tok);
+
+ start_pos = 1; // get past the initial '/'
+ while ((end_pos = path.find('/', start_pos)) != string::npos)
+ {
+ component = path.substr(start_pos, end_pos - start_pos);
+ // Make sure it isn't empty.
+ if (component.size() == 0)
+ throw semantic_error ("process path component cannot be empty",
+ location->tok);
+ // Make sure it isn't relative.
+ else if (component == "." || component == "..")
+ throw semantic_error ("process path cannot be relative (and contain '.' or '..')", location->tok);
+
+ start_pos = end_pos + 1;
+ }
+ component = path.substr(start_pos);
+ // Make sure it doesn't end with '/'.
+ if (component.size() == 0)
+ throw semantic_error ("process path cannot end with a '/'", location->tok);
+ // Make sure it isn't relative.
+ else if (component == "." || component == "..")
+ throw semantic_error ("process path cannot be relative (and contain '.' or '..')", location->tok);
+ }
+
+ finished_results.push_back(new itrace_derived_probe(sess, base, location,
+ has_path, path, pid,
+ single_step
+ ));
+ }
+};
+
+
+void
+itrace_derived_probe_group::enroll (itrace_derived_probe* p)
+{
+ if (p->has_path)
+ probes_by_path[p->path].push_back(p);
+ else
+ probes_by_pid[p->pid].push_back(p);
+ num_probes++;
+
+ // XXX: multiple exec probes (for instance) for the same path (or
+ // pid) should all share a itrace report function, and have their
+ // handlers executed sequentially.
+}
+
+
+void
+itrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
+ itrace_derived_probe *p)
+{
+ s.op->newline() << "{";
+ s.op->line() << " .tgt={";
+
+ if (p->has_path)
+ {
+ s.op->line() << " .pathname=\"" << p->path << "\",";
+ s.op->line() << " .pid=0,";
+ }
+ else
+ {
+ s.op->line() << " .pathname=NULL,";
+ s.op->line() << " .pid=" << p->pid << ",";
+ }
+
+ s.op->line() << " .callback=&_stp_itrace_probe_cb,";
+ s.op->line() << " },";
+ s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
+ s.op->line() << " .single_step=" << p->single_step << ",";
+ s.op->line() << " .ph=&" << p->name << ",";
+
+ s.op->line() << " },";
+}
+
+
+void
+itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
+{
+ if (probes_by_path.empty() && probes_by_pid.empty())
+ return;
+
+ s.op->newline();
+ s.op->newline() << "/* ---- itrace probes ---- */";
+ s.op->newline() << "struct stap_itrace_probe {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_task_finder_target tgt;";
+ s.op->newline() << "const char *pp;";
+ s.op->newline() << "void (*ph) (struct context*);";
+ s.op->newline() << "int single_step;";
+ s.op->newline(-1) << "};";
+ s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data);";
+ s.op->newline() << "#include \"itrace.c\"";
+
+ // output routine to call itrace probe
+ s.op->newline() << "static void enter_itrace_probe(struct stap_itrace_probe *p, struct pt_regs *regs, void *data) {";
+ s.op->indent(1);
+
+ common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING");
+ s.op->newline() << "c->probe_point = p->pp;";
+ s.op->newline() << "c->regs = regs;";
+ s.op->newline() << "c->data = data;";
+
+ // call probe function
+ s.op->newline() << "(*p->ph) (c);";
+ common_probe_entryfn_epilogue (s.op);
+
+ s.op->newline() << "return;";
+ s.op->newline(-1) << "}";
+
+ // Output task finder callback routine that gets called for all
+ // itrace probe types.
+ s.op->newline() << "static int _stp_itrace_probe_cb(struct task_struct *tsk, int register_p, int process_p, struct stap_task_finder_target *tgt) {";
+ s.op->indent(1);
+ s.op->newline() << "int rc = 0;";
+ s.op->newline() << "struct stap_itrace_probe *p = container_of(tgt, struct stap_itrace_probe, tgt);";
+
+ s.op->newline() << "if (register_p) ";
+ s.op->indent(1);
+
+ s.op->newline() << "rc = usr_itrace_init(p->single_step, tsk->pid, p);";
+ s.op->newline(-1) << "else";
+ s.op->newline(1) << "remove_usr_itrace_info(find_itrace_info(p->tgt.pid));";
+ s.op->newline(-1) << "return rc;";
+ s.op->newline(-1) << "}";
+
+ s.op->newline() << "struct stap_itrace_probe stap_itrace_probes[] = {";
+ s.op->indent(1);
+
+ // Set up 'process(PATH)' probes
+ if (! probes_by_path.empty())
+ {
+ for (p_b_path_iterator it = probes_by_path.begin();
+ it != probes_by_path.end(); it++)
+ {
+ for (unsigned i = 0; i < it->second.size(); i++)
+ {
+ itrace_derived_probe *p = it->second[i];
+ emit_probe_decl(s, p);
+ }
+ }
+ }
+
+ // Set up 'process(PID)' probes
+ if (! probes_by_pid.empty())
+ {
+ for (p_b_pid_iterator it = probes_by_pid.begin();
+ it != probes_by_pid.end(); it++)
+ {
+ for (unsigned i = 0; i < it->second.size(); i++)
+ {
+ itrace_derived_probe *p = it->second[i];
+ emit_probe_decl(s, p);
+ }
+ }
+ }
+ s.op->newline(-1) << "};";
+}
+
+
+void
+itrace_derived_probe_group::emit_module_init (systemtap_session& s)
+{
+ if (probes_by_path.empty() && probes_by_pid.empty())
+ return;
+
+ s.op->newline();
+ s.op->newline() << "/* ---- itrace probes ---- */";
+
+ s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];";
+ s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
+ s.op->newline(-1) << "}";
+}
+
+
+void
+itrace_derived_probe_group::emit_module_exit (systemtap_session& s)
+{
+ if (probes_by_path.empty() && probes_by_pid.empty()) return;
+ s.op->newline();
+ s.op->newline() << "/* ---- itrace probes ---- */";
+ s.op->newline() << "cleanup_usr_itrace();";
+}
// ------------------------------------------------------------------------
// utrace user-space probes
@@ -8723,6 +9075,13 @@ register_standard_tapsets(systemtap_session & s)
->bind(new utrace_builder ());
s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_THREAD)->bind(TOK_END)
->bind(new utrace_builder ());
+
+ // itrace user-space probes
+ s.pattern_root->bind_str(TOK_PROCESS)->bind("itrace")
+ ->bind(new itrace_builder ());
+ s.pattern_root->bind_num(TOK_PROCESS)->bind("itrace")
+ ->bind(new itrace_builder ());
+
s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_SYSCALL)
->bind(new utrace_builder ());
s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_SYSCALL)
@@ -8774,6 +9133,7 @@ all_session_groups(systemtap_session& s)
// "register" the dummy task_finder probe group after all probe
// groups that use the task_finder.
DOONE(utrace);
+ DOONE(itrace);
DOONE(task_finder);
#undef DOONE
return g;
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index 14243b80..9dd388ad 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,28 @@
+2008-08-05 Stan Cox <scox@redhat.com>
+
+ * systemtap.base/warnings.stp: Use relative instead of absolute line.
+ * systemtap.base/vars.exp: New test.
+
+2008-08-03 Wenji Huang <wenji.huang@oracle.com>
+
+ * buildok/seven.stp: Correct for 2.6.27.
+ * buildok/seventeen.stp: Ditto.
+
+2008-07-29 Dave Brolley <brolley@redhat.com>
+
+ * Makefile.am (SYSTEMTAP_PATH): Add $(EXTRA_SYSTEMTAP_PATH).
+ * lib/stap_compile.exp: Revert previous change.
+ * lib/stap_run.exp: Likewise.
+ * lib/stap_run2.exp: Likewise.
+ * lib/stap_run_binary.exp: Likewise.
+ * lib/stap_run_exact.exp: Likewise.
+ * lib/systemtap.exp (stap_exec): Removed.
+ * Makefile.in: Regenerated.
+
+2008-07-24 Dave Nomura <dcnltc@us.ibm.com>
+
+ * systemtap.base/itrace.stp: Added simple tests of itrace probe.
+
2008-07-14 Dave Brolley <brolley@redhat.com>
* Makefile.am (TOOL_OPTS): New variable.
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 5f3044cd..03c70cb6 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -40,7 +40,7 @@ SYSTEMTAP_RUNTIME=$(DESTDIR)$(pkgdatadir)/runtime
SYSTEMTAP_TAPSET=$(DESTDIR)$(pkgdatadir)/tapset
LD_LIBRARY_PATH=$(DESTDIR)$(libdir)/systemtap
CRASH_LIBDIR=$(DESTDIR)$(libdir)/systemtap
-SYSTEMTAP_PATH=$(DESTDIR)$(bindir)
+SYSTEMTAP_PATH=$(EXTRA_SYSTEMTAP_PATH):$(DESTDIR)$(bindir)
RUNTESTDEFAULTFLAGS = --tool $$tool --tool_opts \'$(TOOL_OPTS)\' --srcdir $$srcdir
EXPECT = expect
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 8fe7a21f..cc23aed4 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -149,7 +149,7 @@ SYSTEMTAP_RUNTIME = $(DESTDIR)$(pkgdatadir)/runtime
SYSTEMTAP_TAPSET = $(DESTDIR)$(pkgdatadir)/tapset
LD_LIBRARY_PATH = $(DESTDIR)$(libdir)/systemtap
CRASH_LIBDIR = $(DESTDIR)$(libdir)/systemtap
-SYSTEMTAP_PATH = $(DESTDIR)$(bindir)
+SYSTEMTAP_PATH = $(EXTRA_SYSTEMTAP_PATH):$(DESTDIR)$(bindir)
RUNTESTDEFAULTFLAGS = --tool $$tool --tool_opts \'$(TOOL_OPTS)\' --srcdir $$srcdir
EXPECT = expect
RUNTEST = "env SYSTEMTAP_RUNTIME=$(SYSTEMTAP_RUNTIME) SYSTEMTAP_TAPSET=$(SYSTEMTAP_TAPSET) LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) CRASH_LIBDIR=$(CRASH_LIBDIR) PATH=$(SYSTEMTAP_PATH):$$PATH $(srcdir)/execrc runtest"
diff --git a/testsuite/buildok/seven.stp b/testsuite/buildok/seven.stp
index d6f6e5a9..dc3bc786 100755
--- a/testsuite/buildok/seven.stp
+++ b/testsuite/buildok/seven.stp
@@ -6,6 +6,7 @@
# first: enums and ints
+%( kernel_v <= "2.6.26" %?
probe kernel.function("find_pid")
{
%( kernel_v >= "2.6.17" %?
@@ -15,6 +16,7 @@ probe kernel.function("find_pid")
. sprint($nr) . ")")
%)
}
+%)
# second: opaque pointers and enums
diff --git a/testsuite/buildok/seventeen.stp b/testsuite/buildok/seventeen.stp
index 9adffa48..e4a7a8e8 100755
--- a/testsuite/buildok/seventeen.stp
+++ b/testsuite/buildok/seventeen.stp
@@ -5,5 +5,9 @@
probe kernel.function("pipe_write")
{
+%( kernel_v > "2.6.26" %?
+ printf("0x%x\n", $write_pipefifo_fops->llseek)
+%:
printf("0x%x\n", $write_fifo_fops->llseek)
+%)
}
diff --git a/testsuite/lib/stap_compile.exp b/testsuite/lib/stap_compile.exp
index 8f82018f..35124a44 100644
--- a/testsuite/lib/stap_compile.exp
+++ b/testsuite/lib/stap_compile.exp
@@ -4,7 +4,7 @@
# - script is the script to compile
# Additional arguments are passed to stap as-is.
proc stap_compile { TEST_NAME compile script args } {
- set cmd [concat [stap_exec] {-v -p4 -e} $script $args]
+ set cmd [concat stap {-v -p4 -e} $script $args]
verbose -log "running $cmd"
eval spawn $cmd
diff --git a/testsuite/lib/stap_run.exp b/testsuite/lib/stap_run.exp
index 5f67d773..c0027e95 100644
--- a/testsuite/lib/stap_run.exp
+++ b/testsuite/lib/stap_run.exp
@@ -26,7 +26,7 @@ proc stap_run { TEST_NAME {LOAD_GEN_FUNCTION ""} {OUTPUT_CHECK_STRING ""} args }
if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return }
- set cmd [concat [stap_exec] -v $args]
+ set cmd [concat stap -v $args]
if [file readable $test_file_name] {
lappend cmd $test_file_name
}
diff --git a/testsuite/lib/stap_run2.exp b/testsuite/lib/stap_run2.exp
index 1d9dc0b3..9849aefb 100644
--- a/testsuite/lib/stap_run2.exp
+++ b/testsuite/lib/stap_run2.exp
@@ -15,7 +15,7 @@ proc stap_run2 { TEST_NAME args } {
if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return }
- set cmd [concat [stap_exec] $args $test_file_name]
+ set cmd [concat stap $args $test_file_name]
catch {eval exec $cmd} res
set n 0
diff --git a/testsuite/lib/stap_run_binary.exp b/testsuite/lib/stap_run_binary.exp
index a5e1195a..1d31d817 100644
--- a/testsuite/lib/stap_run_binary.exp
+++ b/testsuite/lib/stap_run_binary.exp
@@ -13,7 +13,7 @@ proc stap_run_binary { TEST_NAME} {
if {[info procs installtest_p] != "" && ![installtest_p]} {untested $TEST_NAME; return}
set hex_args {-ve 8/1 "%02x " "\n"}
- set res [exec [stap_exec] $test_file_name | hexdump $hex_args]
+ set res [exec stap $test_file_name | hexdump $hex_args]
if {[string compare $res $::result_string] == 0} {
pass "$TEST_NAME"
diff --git a/testsuite/lib/stap_run_exact.exp b/testsuite/lib/stap_run_exact.exp
index 23c22ec0..6a473798 100644
--- a/testsuite/lib/stap_run_exact.exp
+++ b/testsuite/lib/stap_run_exact.exp
@@ -12,7 +12,7 @@
proc stap_run_exact { TEST_NAME test_file_name args } {
if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return }
- set cmd [concat [stap_exec] $args $test_file_name]
+ set cmd [concat stap $args $test_file_name]
catch {eval exec $cmd} res
set n 0
diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp
index e74bd13c..db5c1587 100644
--- a/testsuite/lib/systemtap.exp
+++ b/testsuite/lib/systemtap.exp
@@ -16,15 +16,6 @@ proc use_server_p {} {
}
-proc stap_exec {} {
- if {[info procs use_server_p] != "" && [use_server_p]} then {
- return "stap-client"
- } else {
- return "stap"
- }
-}
-
-
proc print_systemtap_version {} {
set version [exec /bin/uname -r]
set location "/boot/vmlinux-$version"
diff --git a/testsuite/systemtap.base/vars.exp b/testsuite/systemtap.base/vars.exp
new file mode 100644
index 00000000..7541c01b
--- /dev/null
+++ b/testsuite/systemtap.base/vars.exp
@@ -0,0 +1,32 @@
+# Script for testing $$vars, $$parms, $$locals
+
+set test "vars"
+
+# grab C statement that $$vars yields
+set cmd [concat stap -p3 -e {"probe kernel.statement(\"bio_copy_user@fs/bio.c+1\") \{print (\$\$vars)\}"} 2>&1 | grep {"printf.*="} | sed -e {"s/^.*MAXSTRINGLEN, \"//"} -e {s/..\".*$//}]
+catch {eval exec $cmd} vars
+
+# grab C statement that $$parms yields
+set cmd [regsub "vars" $cmd "parms"]
+catch {eval exec $cmd} parms
+
+# grab C statement that $$locals yields
+set cmd [regsub "parms" $cmd "locals"]
+catch {eval exec $cmd} locals
+
+# syntax check of $$vars C statement
+set vars_ok [regexp "(\[a-z_\]+=%#llx *)+" $vars]
+if {!$vars_ok} {
+ fail "$test"
+} else {
+ pass "$test"
+}
+
+# $$vars should be equivalent to $$parms + $$locals
+if {![string equal [string trim $vars] \
+ [string trim [concat $parms " " $locals]]]} {
+ fail "$test parms/locals"
+} else {
+ pass "$test parms/locals"
+}
+
diff --git a/testsuite/systemtap.base/warnings.stp b/testsuite/systemtap.base/warnings.stp
index 94ed57b3..d71b3034 100644
--- a/testsuite/systemtap.base/warnings.stp
+++ b/testsuite/systemtap.base/warnings.stp
@@ -9,7 +9,7 @@ probe never { print(elide+me1) bar () }
# PR 6611
-probe probea = kernel.statement("bio_init@fs/bio.c:135")
+probe probea = kernel.statement("bio_init@fs/bio.c+3")
{ printf("%d", funca(2)); elide_me6="foo" }
probe probea { printf("%d", funcb(2,3)); printf("%s",var) }
diff --git a/testsuite/systemtap.examples/ChangeLog b/testsuite/systemtap.examples/ChangeLog
index d75ad014..7cb39fb9 100644
--- a/testsuite/systemtap.examples/ChangeLog
+++ b/testsuite/systemtap.examples/ChangeLog
@@ -1,3 +1,11 @@
+2008-08-01 William Cohen <wcohen@redhat.com>
+
+ * helloworld.meta, traceio2.meta: Tweak test_installcheck.
+
+2008-08-01 William Cohen <wcohen@redhat.com>
+
+ * check.exp: Run both tests for installcheck tests.
+
2008-07-11 Mark Wielaard <mwielaard@redhat.com>
* traceio.meta: s/decending/descending/ in description.
diff --git a/testsuite/systemtap.examples/check.exp b/testsuite/systemtap.examples/check.exp
index 2ac43050..14d9a57e 100644
--- a/testsuite/systemtap.examples/check.exp
+++ b/testsuite/systemtap.examples/check.exp
@@ -32,6 +32,23 @@ proc extract_tag { META_DATA TAG } {
return $value
}
+proc run_command { test command } {
+ #FIXME tcl says that single quotes not dealt with
+ if { $command != "" } then {
+ verbose -log "attempting command $command"
+ set res [catch {eval exec $command} value]
+ verbose -log "OUT $value"
+ verbose -log "RC $res"
+ if {$res != 0 } {
+ fail $test
+ } else {
+ pass $test
+ }
+ } else {
+ untested $test
+ }
+}
+
set curdir [pwd]
set src_examples $srcdir/systemtap.examples
@@ -39,36 +56,21 @@ set meta_files [lsort [exec find $src_examples -path "*.meta"]]
foreach file $meta_files {
set dir [file dirname $file]
set test [regsub {.*/testsuite/} $file ""]
+ set test [regsub {.meta} $test ""]
cd $dir
set meta_data [get_meta_data $file]
set test_check [extract_tag "$meta_data" "test_check"]
+ set command $test_check
+ run_command "$test build" $command
set test_installcheck [extract_tag "$meta_data" "test_installcheck"]
- # Would like to run the tests (-p5), but pass fail logic too
- # simple and fails for many examples
- # FIXME following line prevents installcheck with "--tools_opts install"
- set test_installcheck ""
+ # The pass/fail logic too simple and fails for some examples
+ # FIXME would like to be able to run more complicated test code
if {[info procs installtest_p] != "" && [installtest_p]
&& $test_installcheck != "" } then {
set command $test_installcheck
- } else {
- set command $test_check
- }
-
- #FIXME tcl says that single quotes not dealt with
- if { $command != "" } then {
- verbose -log "attempting command $command"
- set res [catch {eval exec $command} value]
- verbose -log "OUT $value"
- verbose -log "RC $res"
- if {$res != 0 } {
- fail $test
- } else {
- pass $test
- }
- } else {
- untested $test
+ run_command "$test run" $command
}
}
diff --git a/testsuite/systemtap.examples/helloworld.meta b/testsuite/systemtap.examples/helloworld.meta
index f56b7ca3..60bc53f2 100644
--- a/testsuite/systemtap.examples/helloworld.meta
+++ b/testsuite/systemtap.examples/helloworld.meta
@@ -10,4 +10,4 @@ output: text
scope: system-wide
description: A basic "Hello World" program implemented in SystemTap script. It prints out "hello world" message and then immediately exits.
test_check: stap -p4 helloworld.stp
-test_installcheck: stap helloworld.stp -c "sleep 1"
+test_installcheck: stap helloworld.stp
diff --git a/testsuite/systemtap.examples/traceio2.meta b/testsuite/systemtap.examples/traceio2.meta
index e6bca1a9..4b63108c 100644
--- a/testsuite/systemtap.examples/traceio2.meta
+++ b/testsuite/systemtap.examples/traceio2.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: Print out the executable name and process number as reads and writes to the specified device occur.
test_check: stap -p4 traceio2.stp 0x0801
-test_installcheck: /bin/sh eval stap traceio2.stp 0x0801 -c "sleep 1"
+test_installcheck: stap traceio2.stp 0x0801 -c "sleep 1"