summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Keniston <jkenisto@us.ibm.com>2009-04-15 16:02:58 -0700
committerJim Keniston <jkenisto@us.ibm.com>2009-04-15 16:02:58 -0700
commit900686f5e209099d493a15f4e36a5030dc0aa8be (patch)
tree405757c92915c516cd0ff28e217a000843573f3f
parent2020af07c2a7f58538874ce652b52a6883f7ada0 (diff)
parent7c2136cfc88d68cfc5eb490444dc25c7dc1c0632 (diff)
downloadsystemtap-steved-900686f5e209099d493a15f4e36a5030dc0aa8be.tar.gz
systemtap-steved-900686f5e209099d493a15f4e36a5030dc0aa8be.tar.xz
systemtap-steved-900686f5e209099d493a15f4e36a5030dc0aa8be.zip
Merge branch 'master' of ssh://kenistoj@sources.redhat.com/git/systemtap
-rw-r--r--AUTHORS1
-rw-r--r--Makefile.am5
-rw-r--r--Makefile.in17
-rw-r--r--NEWS40
-rw-r--r--buildrun.cxx16
-rwxr-xr-xconfigure8
-rw-r--r--configure.ac3
-rw-r--r--doc/SystemTap_Beginners_Guide/en-US/References.xml2
-rw-r--r--doc/SystemTap_Tapset_Reference/tapsets.tmpl6
-rw-r--r--doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml4
-rwxr-xr-xdoc/Tapset_Reference_Guide/publicanize.sh107
-rwxr-xr-xdtrace2
-rw-r--r--elaborate.cxx6
-rw-r--r--elaborate.h5
-rw-r--r--hash.cxx1
-rw-r--r--includes/sys/sdt.h48
-rw-r--r--main.cxx77
-rw-r--r--man/stapprobes.iosched.3stap.in2
-rw-r--r--man/stapprobes.kprocess.3stap.in (renamed from man/stapprobes.process.3stap.in)24
-rw-r--r--man/stapprobes.netdev.3stap.in2
-rw-r--r--man/stapprobes.nfs.3stap.in2
-rw-r--r--man/stapprobes.nfsd.3stap.in2
-rw-r--r--man/stapprobes.pagefault.3stap.in2
-rw-r--r--man/stapprobes.rpc.3stap.in2
-rw-r--r--man/stapprobes.scsi.3stap.in2
-rw-r--r--man/stapprobes.signal.3stap.in2
-rw-r--r--man/stapprobes.tcp.3stap.in2
-rw-r--r--man/stapprobes.udp.3stap.in2
-rw-r--r--run-stap.in7
-rw-r--r--run-staprun.in24
-rw-r--r--runtime/autoconf-asm-syscall.c2
-rw-r--r--runtime/loc2c-runtime.h17
-rw-r--r--runtime/map-gen.c291
-rw-r--r--runtime/pmap-gen.c343
-rw-r--r--runtime/runtime.h19
-rw-r--r--runtime/stack.c8
-rw-r--r--runtime/staprun/common.c9
-rw-r--r--runtime/staprun/relay.c19
-rw-r--r--runtime/staprun/relay_old.c22
-rw-r--r--runtime/staprun/staprun_funcs.c15
-rw-r--r--runtime/sym.c140
-rw-r--r--runtime/sym.h1
-rw-r--r--runtime/syscall.h298
-rw-r--r--runtime/task_finder.c508
-rw-r--r--runtime/task_finder_vma.c110
-rw-r--r--runtime/unwind.c2
-rw-r--r--runtime/uprobes/.gitignore7
-rw-r--r--staptree.h1
-rw-r--r--tapset/DEVGUIDE6
-rw-r--r--tapset/ansi.stp70
-rw-r--r--tapset/context-symbols.stp61
-rw-r--r--tapset/context-unwind.stp3
-rw-r--r--tapset/context.stp25
-rw-r--r--tapset/errno.stp14
-rw-r--r--tapset/i686/syscalls.stp2
-rw-r--r--tapset/ip.stp46
-rw-r--r--tapset/kprocess.stp (renamed from tapset/process.stp)30
-rw-r--r--tapset/tcp.stp94
-rw-r--r--tapset/ucontext-symbols.stp52
-rw-r--r--tapset/utrace.stp8
-rw-r--r--tapsets.cxx552
-rw-r--r--testsuite/buildko/two.stp14
-rwxr-xr-xtestsuite/buildok/modname.stp8
-rwxr-xr-xtestsuite/buildok/process-all-probes.stp12
-rwxr-xr-xtestsuite/buildok/process_test.stp12
-rwxr-xr-xtestsuite/buildok/symdata.stp8
-rwxr-xr-xtestsuite/buildok/symname.stp8
-rw-r--r--testsuite/buildok/thirty.stp49
-rwxr-xr-xtestsuite/buildok/twentysix.stp7
-rwxr-xr-xtestsuite/buildok/uaddr.stp8
-rwxr-xr-xtestsuite/buildok/usymdata.stp8
-rwxr-xr-xtestsuite/buildok/usymname.stp8
-rw-r--r--testsuite/lib/stap_run.exp1
-rw-r--r--testsuite/lib/systemtap.exp14
-rwxr-xr-xtestsuite/semok/badvar.stp4
-rw-r--r--testsuite/systemtap.base/bitfield.exp3
-rw-r--r--testsuite/systemtap.base/bitfield.stp46
-rwxr-xr-xtestsuite/systemtap.base/bz5274.exp9
-rw-r--r--testsuite/systemtap.base/bz6850.exp9
-rw-r--r--testsuite/systemtap.base/itrace.exp42
-rw-r--r--testsuite/systemtap.base/labels.exp51
-rw-r--r--testsuite/systemtap.base/sdt.exp4
-rw-r--r--testsuite/systemtap.base/static_uprobes.exp12
-rw-r--r--testsuite/systemtap.base/stmt_rel.exp46
-rw-r--r--testsuite/systemtap.base/stmt_rel.stp71
-rw-r--r--testsuite/systemtap.base/uprobes.exp9
-rw-r--r--testsuite/systemtap.base/uprobes_exe.c8
-rw-r--r--testsuite/systemtap.base/uprobes_lib.c3
-rw-r--r--testsuite/systemtap.base/uprobes_lib.exp28
-rw-r--r--testsuite/systemtap.base/uprobes_lib.stp10
-rw-r--r--testsuite/systemtap.base/uprobes_uname.exp46
-rw-r--r--testsuite/systemtap.base/uprobes_uname.stp7
-rw-r--r--testsuite/systemtap.base/utrace_p4.exp34
-rw-r--r--testsuite/systemtap.base/utrace_p5.exp21
-rw-r--r--testsuite/systemtap.context/args.tcl2
-rw-r--r--testsuite/systemtap.context/backtrace.tcl2
-rw-r--r--testsuite/systemtap.context/context.exp1
-rw-r--r--testsuite/systemtap.context/num_args.tcl2
-rw-r--r--testsuite/systemtap.context/pid.tcl2
-rw-r--r--testsuite/systemtap.context/usymbols.c39
-rw-r--r--testsuite/systemtap.context/usymbols.exp82
-rw-r--r--testsuite/systemtap.context/usymbols_lib.c29
-rw-r--r--testsuite/systemtap.examples/general/ansi_colors.meta13
-rwxr-xr-xtestsuite/systemtap.examples/general/ansi_colors.stp43
-rw-r--r--testsuite/systemtap.examples/general/ansi_colors2.meta13
-rwxr-xr-xtestsuite/systemtap.examples/general/ansi_colors2.stp31
-rw-r--r--testsuite/systemtap.examples/index.html14
-rw-r--r--testsuite/systemtap.examples/index.txt42
-rwxr-xr-xtestsuite/systemtap.examples/io/ioblktime.stp2
-rw-r--r--testsuite/systemtap.examples/keyword-index.html28
-rw-r--r--testsuite/systemtap.examples/keyword-index.txt64
-rwxr-xr-xtestsuite/systemtap.examples/network/nettop.stp10
-rwxr-xr-x[-rw-r--r--]testsuite/systemtap.examples/network/tcp.stp0
-rw-r--r--testsuite/systemtap.examples/network/tcpdumplike.meta12
-rwxr-xr-xtestsuite/systemtap.examples/network/tcpdumplike.stp14
-rw-r--r--testsuite/systemtap.examples/process/errsnoop.meta7
-rwxr-xr-xtestsuite/systemtap.examples/process/errsnoop.stp44
-rwxr-xr-xtestsuite/systemtap.examples/process/proc_snoop.stp12
-rwxr-xr-xtestsuite/systemtap.examples/profiling/timeout.stp4
-rw-r--r--testsuite/systemtap.pass1-4/buildok.exp2
-rw-r--r--testsuite/systemtap.server/server.exp1
-rw-r--r--testsuite/systemtap.stress/whitelist.exp1
-rw-r--r--translate.cxx105
-rw-r--r--util.cxx41
-rw-r--r--util.h2
125 files changed, 3234 insertions, 1248 deletions
diff --git a/AUTHORS b/AUTHORS
index 0ed3ed04..a6e54c7b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,5 @@
Ananth N Mavinakayanahalli
+Andre Detsch
Anil Keshavamurthy
Anithra Janakiraman
Breno Leitao
diff --git a/Makefile.am b/Makefile.am
index 580c4178..f5fedae1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,7 +17,7 @@ stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap \
staprun.8 \
man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap \
man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap \
-man/stapprobes.pagefault.3stap man/stapprobes.process.3stap \
+man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap \
man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap \
man/stapprobes.signal.3stap man/stapprobes.socket.3stap \
man/stapprobes.tcp.3stap man/stapprobes.udp.3stap
@@ -122,7 +122,8 @@ if BUILD_SERVER
install-exec-local: install-scripts
PHONIES += install-scripts
-install-scripts:
+# scripts should be installed before this rule is run
+install-scripts: install-binSCRIPTS
for f in $(bin_SCRIPTS); do \
sed -i -e "/INSTALL-HOOK/d;s,exec_prefix=,exec_prefix=$(exec_prefix)/bin/,;s,sysconfdir=.*,sysconfdir=$(sysconfdir)," $(DESTDIR)$(bindir)/$$f; \
done
diff --git a/Makefile.in b/Makefile.in
index 7f880e7f..a953be51 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -64,7 +64,7 @@ DIST_COMMON = INSTALL NEWS README AUTHORS $(srcdir)/Makefile.in \
$(top_srcdir)/man/stapprobes.nfs.3stap.in \
$(top_srcdir)/man/stapprobes.nfsd.3stap.in \
$(top_srcdir)/man/stapprobes.pagefault.3stap.in \
- $(top_srcdir)/man/stapprobes.process.3stap.in \
+ $(top_srcdir)/man/stapprobes.kprocess.3stap.in \
$(top_srcdir)/man/stapprobes.rpc.3stap.in \
$(top_srcdir)/man/stapprobes.scsi.3stap.in \
$(top_srcdir)/man/stapprobes.signal.3stap.in \
@@ -72,7 +72,7 @@ DIST_COMMON = INSTALL NEWS README AUTHORS $(srcdir)/Makefile.in \
$(top_srcdir)/man/stapprobes.tcp.3stap.in \
$(top_srcdir)/man/stapprobes.udp.3stap.in \
$(top_srcdir)/initscript/systemtap.in $(srcdir)/run-stap.in \
- depcomp $(oldinclude_HEADERS)
+ $(srcdir)/run-staprun.in depcomp $(oldinclude_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -85,11 +85,11 @@ CONFIG_CLEAN_FILES = stap.1 stapprobes.3stap stapfuncs.3stap \
stapvars.3stap stapex.3stap staprun.8 stap-server.8 \
man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap \
man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap \
- man/stapprobes.pagefault.3stap man/stapprobes.process.3stap \
+ man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap \
man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap \
man/stapprobes.signal.3stap man/stapprobes.socket.3stap \
man/stapprobes.tcp.3stap man/stapprobes.udp.3stap \
- initscript/systemtap run-stap
+ initscript/systemtap run-stap run-staprun
@BUILD_SERVER_TRUE@am__EXEEXT_1 = stap-client-connect$(EXEEXT) \
@BUILD_SERVER_TRUE@ stap-server-connect$(EXEEXT)
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" \
@@ -303,7 +303,7 @@ man_MANS = stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap \
stapex.3stap staprun.8 man/stapprobes.iosched.3stap \
man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap \
man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap \
- man/stapprobes.process.3stap man/stapprobes.rpc.3stap \
+ man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap \
man/stapprobes.scsi.3stap man/stapprobes.signal.3stap \
man/stapprobes.socket.3stap man/stapprobes.tcp.3stap \
man/stapprobes.udp.3stap $(am__append_1)
@@ -457,7 +457,7 @@ man/stapprobes.nfsd.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapp
cd $(top_builddir) && $(SHELL) ./config.status $@
man/stapprobes.pagefault.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.pagefault.3stap.in
cd $(top_builddir) && $(SHELL) ./config.status $@
-man/stapprobes.process.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.process.3stap.in
+man/stapprobes.kprocess.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.kprocess.3stap.in
cd $(top_builddir) && $(SHELL) ./config.status $@
man/stapprobes.rpc.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.rpc.3stap.in
cd $(top_builddir) && $(SHELL) ./config.status $@
@@ -475,6 +475,8 @@ initscript/systemtap: $(top_builddir)/config.status $(top_srcdir)/initscript/sys
cd $(top_builddir) && $(SHELL) ./config.status $@
run-stap: $(top_builddir)/config.status $(srcdir)/run-stap.in
cd $(top_builddir) && $(SHELL) ./config.status $@
+run-staprun: $(top_builddir)/config.status $(srcdir)/run-staprun.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@@ -1468,7 +1470,8 @@ cscope:
@BUILD_ELFUTILS_TRUE@install-exec-local: install-elfutils
@BUILD_SERVER_TRUE@install-exec-local: install-scripts
-@BUILD_SERVER_TRUE@install-scripts:
+# scripts should be installed before this rule is run
+@BUILD_SERVER_TRUE@install-scripts: install-binSCRIPTS
@BUILD_SERVER_TRUE@ for f in $(bin_SCRIPTS); do \
@BUILD_SERVER_TRUE@ sed -i -e "/INSTALL-HOOK/d;s,exec_prefix=,exec_prefix=$(exec_prefix)/bin/,;s,sysconfdir=.*,sysconfdir=$(sysconfdir)," $(DESTDIR)$(bindir)/$$f; \
@BUILD_SERVER_TRUE@ done
diff --git a/NEWS b/NEWS
index ec204442..37a424d8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,19 +1,31 @@
+* What's new
+
+- The overlapping process.* tapsets are now separated. Those probe points
+ documented in stapprobes(3stap) remain the same. Those that were formerly
+ in stapprobes.process(3stap) have been renamed to kprocess, to reflect
+ their kernel perspective on processes.
+
+- The --skip-badvars option now also suppresses run-time error
+ messages that would otherwise result from erroneous memory accesses.
+ Such accesses can originate from $context expressions fueled by
+ erroneous debug data, or by kernel_{long,string,...}() tapset calls.
+
* What's new in version 0.9.5
- - New probes process().insn and process().insn.block that allows
- inspection of the process after each instruction or block of
- instructions executed. So to count the total number of instructions
- a process executes during a run do something like:
- $ stap -e 'global steps; probe process("/bin/ls").insn {steps++}
- probe end {printf("Total instructions: %d\n", steps);}' \
- -c /bin/ls
- This feature can slow down execution of a process somewhat.
-
- - Systemtap probes and function man pages extracted from the tapsets
- are now available under 3stap. To show the page for probe vm.pagefault
- or the stap function pexecname do:
- $ man 3stap vm.pagefault
- $ man 3stap pexecname
+- New probes process().insn and process().insn.block that allows
+ inspection of the process after each instruction or block of
+ instructions executed. So to count the total number of instructions
+ a process executes during a run do something like:
+ $ stap -e 'global steps; probe process("/bin/ls").insn {steps++}
+ probe end {printf("Total instructions: %d\n", steps);}' \
+ -c /bin/ls
+ This feature can slow down execution of a process somewhat.
+
+- Systemtap probes and function man pages extracted from the tapsets
+ are now available under 3stap. To show the page for probe vm.pagefault
+ or the stap function pexecname do:
+ $ man 3stap vm.pagefault
+ $ man 3stap pexecname
- Kernel tracepoints are now supported for probing predefined kernel
events without any debuginfo. Tracepoints incur less overhead than
diff --git a/buildrun.cxx b/buildrun.cxx
index 97357692..82ac9d4e 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -48,6 +48,12 @@ run_make_cmd(systemtap_session& s, string& make_cmd)
cerr << "unsetenv failed: " << e << endl;
}
+ // Disable ccache to avoid saving files that will never be reused.
+ // (ccache is useless to us, because our compiler commands always
+ // include the randomized tmpdir path.)
+ // It's not critical if this fails, so the return is ignored.
+ (void) setenv("CCACHE_DISABLE", "1", 0);
+
if (s.verbose > 2)
make_cmd += " V=1";
else if (s.verbose > 1)
@@ -56,7 +62,7 @@ run_make_cmd(systemtap_session& s, string& make_cmd)
make_cmd += " -s >/dev/null 2>&1";
if (s.verbose > 1) clog << "Running " << make_cmd << endl;
- rc = system (make_cmd.c_str());
+ rc = stap_system (make_cmd.c_str());
return rc;
}
@@ -159,6 +165,8 @@ compile_pass (systemtap_session& s)
#endif
output_autoconf(s, o, "autoconf-save-stack-trace.c",
"STAPCONF_KERNEL_STACKTRACE", NULL);
+ output_autoconf(s, o, "autoconf-asm-syscall.c",
+ "STAPCONF_ASM_SYSCALL_H", NULL);
o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl;
@@ -223,7 +231,7 @@ kernel_built_uprobes (systemtap_session& s)
{
string grep_cmd = string ("/bin/grep -q unregister_uprobe ") +
s.kernel_build_tree + string ("/Module.symvers");
- int rc = system (grep_cmd.c_str());
+ int rc = stap_system (grep_cmd.c_str());
return (rc == 0);
}
@@ -274,7 +282,7 @@ copy_uprobes_symbols (systemtap_session& s)
string uprobes_home = s.runtime_path + "/uprobes";
string cp_cmd = string("/bin/cp ") + uprobes_home +
string("/Module.symvers ") + s.tmpdir;
- int rc = system (cp_cmd.c_str());
+ int rc = stap_system (cp_cmd.c_str());
return rc;
}
@@ -339,7 +347,7 @@ run_pass (systemtap_session& s)
if (s.verbose>1) clog << "Running " << staprun_cmd << endl;
- rc = system (staprun_cmd.c_str ());
+ rc = stap_system (staprun_cmd.c_str ());
return rc;
}
diff --git a/configure b/configure
index a63b6557..852dc786 100755
--- a/configure
+++ b/configure
@@ -8074,7 +8074,7 @@ _ACEOF
ac_config_headers="$ac_config_headers config.h:config.in"
-ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.process.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap"
+ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap"
@@ -8082,6 +8082,8 @@ subdirs="$subdirs testsuite"
ac_config_files="$ac_config_files run-stap"
+ac_config_files="$ac_config_files run-staprun"
+
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@@ -8774,7 +8776,7 @@ do
"man/stapprobes.nfs.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.nfs.3stap" ;;
"man/stapprobes.nfsd.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.nfsd.3stap" ;;
"man/stapprobes.pagefault.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.pagefault.3stap" ;;
- "man/stapprobes.process.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.process.3stap" ;;
+ "man/stapprobes.kprocess.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.kprocess.3stap" ;;
"man/stapprobes.rpc.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.rpc.3stap" ;;
"man/stapprobes.scsi.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.scsi.3stap" ;;
"man/stapprobes.signal.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.signal.3stap" ;;
@@ -8783,6 +8785,7 @@ do
"man/stapprobes.udp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.udp.3stap" ;;
"initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;;
"run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;;
+ "run-staprun") CONFIG_FILES="$CONFIG_FILES run-staprun" ;;
*) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
@@ -9562,6 +9565,7 @@ $as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
done
;;
"run-stap":F) chmod +x run-stap ;;
+ "run-staprun":F) chmod +x run-staprun ;;
esac
done # for ac_tag
diff --git a/configure.ac b/configure.ac
index eab206a2..a953e156 100644
--- a/configure.ac
+++ b/configure.ac
@@ -356,9 +356,10 @@ dnl Don't use this directly (when not given it is set to NONE).
AC_DEFINE_UNQUOTED(STAP_PREFIX, "$prefix", [configure prefix location])
AC_CONFIG_HEADERS([config.h:config.in])
-AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.process.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap)
+AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap)
AC_CONFIG_SUBDIRS(testsuite)
AC_CONFIG_FILES([run-stap], [chmod +x run-stap])
+AC_CONFIG_FILES([run-staprun], [chmod +x run-staprun])
AC_OUTPUT
if test "${prefix}" = "/usr/local"; then
diff --git a/doc/SystemTap_Beginners_Guide/en-US/References.xml b/doc/SystemTap_Beginners_Guide/en-US/References.xml
index ff993df2..6ab74f17 100644
--- a/doc/SystemTap_Beginners_Guide/en-US/References.xml
+++ b/doc/SystemTap_Beginners_Guide/en-US/References.xml
@@ -43,7 +43,7 @@
The <filename>stapprobes</filename> man page enumerates a variety of probe points supported by SystemTap, along with additional aliases
defined by the SystemTap tapset library. The bottom of the man page includes a list of other man pages
enumerating similar probe points for specific system components, such as
- <filename>stapprobes.scsi</filename>, <filename>stapprobes.process</filename>,
+ <filename>stapprobes.scsi</filename>, <filename>stapprobes.kprocess</filename>,
<filename>stapprobes.signal</filename>, etc.
</para>
</listitem>
diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl
index b7c0713b..19a8e02f 100644
--- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl
+++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl
@@ -181,13 +181,13 @@
</para>
!Itapset/socket.stp
</chapter>
- <chapter id="process.stp">
- <title>Process Tapset</title>
+ <chapter id="kprocess.stp">
+ <title>Kernel Process Tapset</title>
<para>
This family of probe points is used to probe process-related activities.
It contains the following probe points:
</para>
-!Itapset/process.stp
+!Itapset/kprocess.stp
</chapter>
<chapter id="signal.stp">
<title>Signal Tapset</title>
diff --git a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml
index d497eae6..293a0dc3 100644
--- a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml
+++ b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml
@@ -64,7 +64,7 @@
<para>
<programlisting>
-probe process.exec = kernel.function("do_execve"),
+probe kprocess.exec = kernel.function("do_execve"),
kernel.function("compat_do_execve")
{<replaceable>probe body</replaceable>}
</programlisting>
@@ -106,7 +106,7 @@ kernel.function("compat_do_execve")
<para>
<programlisting>
-probe process.create = kernel.function("copy_process").return
+probe kprocess.create = kernel.function("copy_process").return
{
task = $return
new_pid = task_pid(task)
diff --git a/doc/Tapset_Reference_Guide/publicanize.sh b/doc/Tapset_Reference_Guide/publicanize.sh
index d4da6e02..0d1b134e 100755
--- a/doc/Tapset_Reference_Guide/publicanize.sh
+++ b/doc/Tapset_Reference_Guide/publicanize.sh
@@ -1,26 +1,74 @@
#!/bin/bash
+INFILE="../SystemTap_Tapset_Reference/tapsets.xml"
+OUTFILE="en-US/Tapset_Reference_Guide.xml"
+TMPFILE='mktemp' || exit 1
+TMPFILE2='mktemp' || exit 1
-#copy the automated tapsets.xml
-cp ../SystemTap_Tapset_Reference/tapsets.xml temp.xml ;
+do_help()
+{
+ echo "publicanize.sh: usage:
+ -?/--help this message
+ -i/--input=file input file name
+ -o/--output=file output file name
+" >&2
+}
+
+
+#process optional arguments -i -o
+while [ "$#" -ne 0 ]
+do
+ arg=`printf %s $1 | awk -F= '{print $1}'`
+ val=`printf %s $1 | awk -F= '{print $2}'`
+ shift
+ if test -z "$val"; then
+ local possibleval=$1
+ printf %s $1 "$possibleval" | grep ^- >/dev/null 2>&1
+ if test "$?" != "0"; then
+ val=$possibleval
+ if [ "$#" -ge 1 ]; then
+ shift
+ fi
+ fi
+ fi
+
+ case "$arg" in
+ -i|--input)
+ INFILE=$val
+ ;;
+ -o|--output)
+ OUTFILE=$val
+ ;;
+ -\?|--help)
+ do_help
+ exit 0
+ ;;
+ *)
+ echo "Unknown option \"$arg\". See opcontrol --help" >&2
+ exit 1
+ ;;
+ esac
+done
+
+
+#copy the generated tapsets.xml
+cp $INFILE $TMPFILE || exit 1
#remove all excess whitespace
-sed -i -e 's/^\s*//g' temp.xml ;
+sed -i -e 's/^\s*//g' $TMPFILE
-#remove marked Intro (starthere to endhere), then copy it to en-US
-sed '/starthere/,/endhere/d' temp.xml > Tapset_Reference_Guide.xml
-cp Tapset_Reference_Guide.xml en-US/Tapset_Reference_Guide.xml;
-rm Tapset_Reference_Guide.xml
+#remove marked Intro (starthere to endhere)
+sed -i -e '/starthere/,/endhere/d' $TMPFILE
#re-convert programlisting tags
-sed -i -e 's/&lt;programlisting&gt;/<programlisting>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/programlisting&gt;/<\/programlisting>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;programlisting&gt;/<programlisting>/g' $TMPFILE
+sed -i -e 's/&lt;\/programlisting&gt;/<\/programlisting>/g' $TMPFILE
#replace header
-cat en-US/Tapset_Reference_Guide.xml |
+cat $TMPFILE |
perl -p -e 'undef $/;s|<bookinfo>\n<title>SystemTap Tapset Reference Manual</title>|<xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="Preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|msg' |
-perl -p -e 'undef $/;s|<authorgroup>\n<author>\n<firstname>William</firstname>\n<surname>Cohen</surname>\n<contrib></contrib>\n<affiliation>\n<address>\n<email>wcohen\@redhat.com</email>\n</address>\n</affiliation>\n</author>\n</authorgroup>||msg' |
-perl -p -e 'undef $/;s|<copyright>\n<year>2008, 2009</year>\n<holder>Red Hat, Inc.</holder>\n</copyright>||msg' |
+perl -p -e 'undef $/;s|<authorgroup>\n<author>\n<othername>SystemTap</othername>\n<contrib>Hackers</contrib>\n</author>\n</authorgroup>||msg' |
+perl -p -e 'undef $/;s|<copyright>\n<year>2008-2009</year>\n<holder>Red Hat, Inc. and others</holder>\n</copyright>||msg' |
perl -p -e 'undef $/;s|<legalnotice>\n<para>\nThis documentation is free software\; you can redistribute\nit and/or modify it under the terms of the GNU General Public\nLicense version 2 as published by the Free Software Foundation.\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\nThis program is distributed in the hope that it will be\nuseful, but WITHOUT ANY WARRANTY; without even the implied\nwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nSee the GNU General Public License for more details.\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\nYou should have received a copy of the GNU General Public\nLicense along with this program; if not, write to the Free\nSoftware Foundation, Inc., 59 Temple Place, Suite 330, Boston,\nMA 02111-1307 USA\n</para>||msg' |
@@ -32,34 +80,33 @@ perl -p -e 'undef $/;s|<programlisting>\n|<programlisting>\n<emphasis>function <
perl -p -e 'undef $/;s|<para>\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\n\n</para>||msg' |
perl -p -e 'undef $/;s|<para>\n<programlisting>|<programlisting>|msg' |
-perl -p -e 'undef $/;s|</programlisting>\n</para>|</programlisting>|msg' > clean.xml
+perl -p -e 'undef $/;s|</programlisting>\n</para>|</programlisting>|msg' > $TMPFILE2
#replace Intro with my own
-perl -p -i -e 's|<!--markerforxi-->|<xi:include href="Introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="Tapset_Dev_Guide.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' clean.xml
+perl -p -i -e 's|<!--markerforxi-->|<xi:include href="Introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="Tapset_Dev_Guide.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' $TMPFILE2
#for tapset name format section
-#perl -p -i -e 'undef $/;s|<screen>\nname:return \(parameters\)\ndefinition\n</screen>|<screen>\n<replaceable>function/probe</replaceable> tapset_name:return \(parameters\)\n</screen>|msg' clean.xml
-#perl -p -i -e 's|<para>In this guide, tapset definitions appear in the following format:</para>|<para>In this guide, the synopsis of each tapset appears in the following format:</para>|g' clean.xml
-#perl -p -i -e 's|<!-- markerforxi pls dont remove -->|<xi:include href="tapsetnameformat-lastpara.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="refentry-example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' clean.xml
+#perl -p -i -e 'undef $/;s|<screen>\nname:return \(parameters\)\ndefinition\n</screen>|<screen>\n<replaceable>function/probe</replaceable> tapset_name:return \(parameters\)\n</screen>|msg' $TMPFILE2
+#perl -p -i -e 's|<para>In this guide, tapset definitions appear in the following format:</para>|<para>In this guide, the synopsis of each tapset appears in the following format:</para>|g' $TMPFILE2
+#perl -p -i -e 's|<!-- markerforxi pls dont remove -->|<xi:include href="tapsetnameformat-lastpara.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />\n<xi:include href="refentry-example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />|g' $TMPFILE2
-cp clean.xml en-US/Tapset_Reference_Guide.xml
-rm clean.xml
-
# statements change synopsis tags, as they are still currently unfixed in publican-redhat
-sed -i -e 's/refsynopsisdiv>/refsect1>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/refsect1>/refsection>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/synopsis>/programlisting>\n/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/refsynopsisdiv>/refsect1>/g' $TMPFILE2
+sed -i -e 's/refsect1>/refsection>/g' $TMPFILE2
+sed -i -e 's/synopsis>/programlisting>\n/g' $TMPFILE2
# re-convert tags
-sed -i -e 's/&lt;emphasis&gt;/<emphasis>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/emphasis&gt;/<\/emphasis>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;emphasis&gt;/<emphasis>/g' $TMPFILE2
+sed -i -e 's/&lt;\/emphasis&gt;/<\/emphasis>/g' $TMPFILE2
-sed -i -e 's/&lt;remark&gt;/<remark>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/remark&gt;/<\/remark>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;remark&gt;/<remark>/g' $TMPFILE2
+sed -i -e 's/&lt;\/remark&gt;/<\/remark>/g' $TMPFILE2
-sed -i -e 's/&lt;command&gt;/<command>/g' en-US/Tapset_Reference_Guide.xml;
-sed -i -e 's/&lt;\/command&gt;/<\/command>/g' en-US/Tapset_Reference_Guide.xml;
+sed -i -e 's/&lt;command&gt;/<command>/g' $TMPFILE2
+sed -i -e 's/&lt;\/command&gt;/<\/command>/g' $TMPFILE2
#useful marker script; moves content between starthere and endhere to file target
-#sed -n '/starthere/,/endhere/ s/.*/&/w target' Tapset_Reference_Guide.xml \ No newline at end of file
+#sed -n '/starthere/,/endhere/ s/.*/&/w target' $TMPFILE2
+
+mv $TMPFILE2 $OUTFILE
diff --git a/dtrace b/dtrace
index fd7b4b99..ca95b678 100755
--- a/dtrace
+++ b/dtrace
@@ -94,7 +94,7 @@ class provider:
########################################################################
def usage ():
- print "Usage " + sys.argv[0] + "[-h | -G] -s File.d -o File {Files}"
+ print "Usage " + sys.argv[0] + " [-h | -G] -s File.d -o File {Files}"
sys.exit(1)
def open_file (arg):
diff --git a/elaborate.cxx b/elaborate.cxx
index 34e6ab16..b760173f 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -2433,7 +2433,8 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
p->body = duv.require(p->body, true);
if (p->body == 0)
{
- if (! s.suppress_warnings)
+ if (! s.suppress_warnings
+ && ! s.timing) // PR10070
s.print_warning ("side-effect-free probe '" + p->name + "'", p->tok);
p->body = new null_statement();
@@ -3392,6 +3393,9 @@ typeresolution_info::visit_symbol (symbol* e)
void
typeresolution_info::visit_target_symbol (target_symbol* e)
{
+ if (!e->probe_context_var.empty())
+ return;
+
// This occurs only if a target symbol was not resolved over in
// tapset.cxx land, that error was properly suppressed, and the
// later unused-expression-elimination pass didn't get rid of it
diff --git a/elaborate.h b/elaborate.h
index 0ad5b4b2..d927177b 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -129,6 +129,11 @@ struct derived_probe: public probe
void printsig_nested (std::ostream &o) const;
virtual void collect_derivation_chain (std::vector<probe*> &probes_list);
+ virtual void print_dupe_stamp(std::ostream&) {}
+ // To aid duplication elimination, print a stamp which uniquely identifies
+ // the code that will be added to the probe body. (Doesn't need to be the
+ // actual code...)
+
virtual void emit_probe_context_vars (translator_output*) {}
// From within unparser::emit_common_header, add any extra variables
// to this probe's context locals.
diff --git a/hash.cxx b/hash.cxx
index 3ff6848d..01013c43 100644
--- a/hash.cxx
+++ b/hash.cxx
@@ -174,6 +174,7 @@ find_script_hash (systemtap_session& s, const string& script, const hash &base)
h.add(s.ignore_vmlinux); // --ignore-vmlinux
h.add(s.ignore_dwarf); // --ignore-dwarf
h.add(s.consult_symtab); // --kelf, --kmap
+ h.add(s.skip_badvars); // --skip-badvars
if (!s.kernel_symtab_path.empty()) // --kmap
{
h.add(s.kernel_symtab_path);
diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h
index ba75076b..c3fa16d9 100644
--- a/includes/sys/sdt.h
+++ b/includes/sys/sdt.h
@@ -39,6 +39,19 @@
#endif
#define STAP_LABEL(a,b) STAP_CONCAT(a,b)
+/* Taking the address of a local label and/or referencing alloca prevents the
+ containing function from being inlined, which keeps the parameters visible. */
+
+#if __GNUC__ == 4 && __GNUC_MINOR__ <= 1
+#include <alloca.h>
+#define STAP_UNINLINE alloca((size_t)0)
+#else
+#define STAP_UNINLINE
+#endif
+
+#define STAP_UNINLINE_LABEL(label) \
+ __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label
+
#define STAP_PROBE_(probe) \
do { \
STAP_PROBE_DATA(probe); \
@@ -46,13 +59,11 @@ do { \
"\tnop"); \
} while (0)
-/* Taking the address of a local label prevents the containing function
- from being inlined, which keeps the parameters visible. */
-
#define STAP_PROBE1_(probe,label,parm1) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -61,9 +72,10 @@ do { \
#define STAP_PROBE2_(probe,label,parm1,parm2) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -72,10 +84,11 @@ do { \
#define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
- volatile __typeof__((parm1)) arg1 = parm1; \
+ STAP_UNINLINE_LABEL(label); \
+ volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -84,11 +97,12 @@ do { \
#define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
volatile __typeof__((parm4)) arg4 = parm4; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -97,12 +111,13 @@ do { \
#define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
volatile __typeof__((parm4)) arg4 = parm4; \
volatile __typeof__((parm5)) arg5 = parm5; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -111,13 +126,14 @@ do { \
#define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
volatile __typeof__((parm4)) arg4 = parm4; \
volatile __typeof__((parm5)) arg5 = parm5; \
volatile __typeof__((parm6)) arg6 = parm6; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -126,7 +142,7 @@ do { \
#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
@@ -134,6 +150,7 @@ do { \
volatile __typeof__((parm5)) arg5 = parm5; \
volatile __typeof__((parm6)) arg6 = parm6; \
volatile __typeof__((parm7)) arg7 = parm7; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -142,7 +159,7 @@ do { \
#define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
@@ -151,6 +168,7 @@ do { \
volatile __typeof__((parm6)) arg6 = parm6; \
volatile __typeof__((parm7)) arg7 = parm7; \
volatile __typeof__((parm8)) arg8 = parm8; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -159,7 +177,7 @@ do { \
#define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
@@ -169,6 +187,7 @@ do { \
volatile __typeof__((parm7)) arg7 = parm7; \
volatile __typeof__((parm8)) arg8 = parm8; \
volatile __typeof__((parm9)) arg9 = parm9; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
@@ -177,7 +196,7 @@ do { \
#define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \
do { \
- __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \
+ STAP_UNINLINE_LABEL(label); \
volatile __typeof__((parm1)) arg1 = parm1; \
volatile __typeof__((parm2)) arg2 = parm2; \
volatile __typeof__((parm3)) arg3 = parm3; \
@@ -188,6 +207,7 @@ do { \
volatile __typeof__((parm8)) arg8 = parm8; \
volatile __typeof__((parm9)) arg9 = parm9; \
volatile __typeof__((parm10)) arg10 = parm10; \
+ STAP_UNINLINE; \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
diff --git a/main.cxx b/main.cxx
index 3b88a1c8..794a5891 100644
--- a/main.cxx
+++ b/main.cxx
@@ -36,8 +36,6 @@ extern "C" {
#include <sys/times.h>
#include <sys/time.h>
#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <time.h>
#include <elfutils/libdwfl.h>
#include <getopt.h>
@@ -293,14 +291,9 @@ int pending_interrupts;
extern "C"
void handle_interrupt (int sig)
{
- if (pending_interrupts == 0)
- kill (0, sig); // Forward signals to child processes if any.
-
+ kill_stap_spawn(sig);
pending_interrupts ++;
- // NB: the "2" below is intended to skip the effect of the self-induced
- // deferred signal coming from the kill() above.
-
- if (pending_interrupts > 2) // XXX: should be configurable? time-based?
+ if (pending_interrupts > 1) // XXX: should be configurable? time-based?
{
char msg[] = "Too many interrupts received, exiting.\n";
int rc = write (2, msg, sizeof(msg)-1);
@@ -324,7 +317,7 @@ setup_signals (sighandler_t handler)
sigaddset (&sa.sa_mask, SIGINT);
sigaddset (&sa.sa_mask, SIGTERM);
}
- sa.sa_flags = 0;
+ sa.sa_flags = SA_RESTART;
sigaction (SIGHUP, &sa, NULL);
sigaction (SIGPIPE, &sa, NULL);
@@ -332,62 +325,10 @@ setup_signals (sighandler_t handler)
sigaction (SIGTERM, &sa, NULL);
}
-pid_t runner_pid;
-int runner (int, char * const []);
-
-// Passes on signals to runner process.
-// In practise passes signal to runner process process group,
-// since run_pass() uses system() to spawn child processes,
-// which makes the process ignore SIGINT during the command run.
-extern "C"
-void waiter_handler (int sig)
-{
- // Process group is negative process id.
- kill (-1 * runner_pid, sig);
-}
-
-// Just sits there till the runner exits and then exits the same way.
-void waiter()
-{
- int status;
- setup_signals (&waiter_handler);
- while (waitpid (runner_pid, &status, 0) != runner_pid);
-
- // Exit as our runner child exitted.
- if (WIFEXITED(status))
- exit (WEXITSTATUS(status));
-
- // Or simulate as if we were killed by the same signal.
- if (WIFSIGNALED(status))
- {
- int sig = WTERMSIG(status);
- signal (sig, SIG_DFL);
- raise (sig);
- }
-
- // Should not happen, exit as if error.
- exit(-1);
-}
int
main (int argc, char * const argv [])
{
- // Fork to make sure runner gets its own process group, while
- // the waiter sits in the original process group of the shell
- // and forwards any signals.
- runner_pid = fork ();
- if (runner_pid == 0)
- return runner (argc, argv);
- if (runner_pid > 0)
- waiter ();
-
- perror ("couldn't fork");
- exit (-1);
-}
-
-int
-runner (int argc, char * const argv [])
-{
string cmdline_script; // -e PROGRAM
string script_file; // FILE
bool have_script = false;
@@ -899,16 +840,6 @@ runner (int argc, char * const argv [])
// directory.
s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
- // We want a new process group so we can use kill (0, sig) to send a
- // signal to all children (but not the parent). As done in
- // handle_interrupt ().
- if (setpgrp() != 0)
- {
- const char* e = strerror (errno);
- if (! s.suppress_warnings)
- cerr << "Warning: failed to set new process group: " << e << endl;
- }
-
// Set up our handler to catch routine signals, to allow clean
// and reasonably timely exit.
setup_signals(&handle_interrupt);
@@ -1251,7 +1182,7 @@ pass_5:
string cleanupcmd = "rm -rf ";
cleanupcmd += s.tmpdir;
if (s.verbose>1) clog << "Running " << cleanupcmd << endl;
- int status = system (cleanupcmd.c_str());
+ int status = stap_system (cleanupcmd.c_str());
if (status != 0 && s.verbose>1)
clog << "Cleanup command failed, status: " << status << endl;
}
diff --git a/man/stapprobes.iosched.3stap.in b/man/stapprobes.iosched.3stap.in
index e08dce8c..873251ac 100644
--- a/man/stapprobes.iosched.3stap.in
+++ b/man/stapprobes.iosched.3stap.in
@@ -96,5 +96,5 @@ Fires when a request is completed
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.process.3stap.in b/man/stapprobes.kprocess.3stap.in
index 3b5e751d..4f5e7903 100644
--- a/man/stapprobes.process.3stap.in
+++ b/man/stapprobes.kprocess.3stap.in
@@ -1,7 +1,7 @@
.\" -*- nroff -*-
-.TH STAPPROBES.PROCESS 3stap @DATE@ "Intel, IBM"
+.TH STAPPROBES.KPROCESS 3stap @DATE@ "Intel, IBM"
.SH NAME
-stapprobes.process \- systemtap process probe points
+stapprobes.kprocess \- systemtap kernel process probe points
.\" macros
.de SAMPLE
@@ -18,12 +18,12 @@ stapprobes.process \- systemtap process probe points
.SH DESCRIPTION
-This family of probe points is used to probe the process activities.
+This family of probe points is used to probe the kernel's process activities.
It contains the following probe points:
.P
.TP
-.B process.create
+.B kprocess.create
Fires whenever a new process is successfully created, either as a
result of one of the fork syscall variants, or a new kernel thread.
@@ -38,7 +38,7 @@ result of one of the fork syscall variants, or a new kernel thread.
.P
.TP
-.B process.start
+.B kprocess.start
Fires immediately before a new process begins execution.
@@ -48,7 +48,7 @@ Fires immediately before a new process begins execution.
.P
.TP
-.B process.exec
+.B kprocess.exec
Fires whenever a process attempts to exec to a new program
@@ -59,7 +59,7 @@ Fires whenever a process attempts to exec to a new program
.P
.TP
-.B process.exec_complete
+.B kprocess.exec_complete
Fires at the completion of an exec call
@@ -73,10 +73,10 @@ Fires at the completion of an exec call
.P
.TP
-.B process.exit
+.B kprocess.exit
Fires when a process terminates. This will always be followed by a
-process.release, though the latter may be delayed if the process
+kprocess.release, though the latter may be delayed if the process
waits in a zombie state.
.B Arguments:
@@ -86,10 +86,10 @@ waits in a zombie state.
.P
.TP
-.B process.release
+.B kprocess.release
Fires when a process is released from the kernel. This always
-follows a process.exit, though it may be delayed somewhat if the
+follows a kprocess.exit, though it may be delayed somewhat if the
process waits in a zombie state.
.B Arguments:
@@ -102,5 +102,5 @@ process waits in a zombie state.
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.netdev.3stap.in b/man/stapprobes.netdev.3stap.in
index c25fbd44..9b2e57ed 100644
--- a/man/stapprobes.netdev.3stap.in
+++ b/man/stapprobes.netdev.3stap.in
@@ -74,4 +74,4 @@ Fires when the network device wants to transmit a buffer
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.nfs.3stap.in b/man/stapprobes.nfs.3stap.in
index b6a81cde..579af533 100644
--- a/man/stapprobes.nfs.3stap.in
+++ b/man/stapprobes.nfs.3stap.in
@@ -1232,5 +1232,5 @@ Fires whenever nfs client renames a file on server
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.nfsd.3stap.in b/man/stapprobes.nfsd.3stap.in
index d3aea639..239d3b94 100644
--- a/man/stapprobes.nfsd.3stap.in
+++ b/man/stapprobes.nfsd.3stap.in
@@ -509,5 +509,5 @@ Fires whenever server receives NFS operation from client
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.pagefault.3stap.in b/man/stapprobes.pagefault.3stap.in
index b1c53a19..7d4f266e 100644
--- a/man/stapprobes.pagefault.3stap.in
+++ b/man/stapprobes.pagefault.3stap.in
@@ -36,5 +36,5 @@ Fires when there is a pagefault
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.rpc.3stap.in b/man/stapprobes.rpc.3stap.in
index a2622fe5..6061b206 100644
--- a/man/stapprobes.rpc.3stap.in
+++ b/man/stapprobes.rpc.3stap.in
@@ -579,5 +579,5 @@ Fires when a task is to be delayed
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.scsi.3stap.in b/man/stapprobes.scsi.3stap.in
index b595105a..afe16541 100644
--- a/man/stapprobes.scsi.3stap.in
+++ b/man/stapprobes.scsi.3stap.in
@@ -147,5 +147,5 @@ block device I/O requests
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.signal.3stap.in b/man/stapprobes.signal.3stap.in
index f42a7781..9b7ccd5f 100644
--- a/man/stapprobes.signal.3stap.in
+++ b/man/stapprobes.signal.3stap.in
@@ -505,5 +505,5 @@ Fires when flush all pending signals for a task
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.tcp.3stap.in b/man/stapprobes.tcp.3stap.in
index 3e607b69..88603f58 100644
--- a/man/stapprobes.tcp.3stap.in
+++ b/man/stapprobes.tcp.3stap.in
@@ -98,5 +98,5 @@ Fires when returning from tcp.disconnect
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/man/stapprobes.udp.3stap.in b/man/stapprobes.udp.3stap.in
index 3fbfd3e7..dae11578 100644
--- a/man/stapprobes.udp.3stap.in
+++ b/man/stapprobes.udp.3stap.in
@@ -98,5 +98,5 @@ Fires when returning from udp.disconnect
.SH SEE ALSO
.IR stap (1),
-.IR stapprobes (3stap),
+.IR stapprobes (3stap)
diff --git a/run-stap.in b/run-stap.in
index dfb53ab2..8b150ece 100644
--- a/run-stap.in
+++ b/run-stap.in
@@ -19,11 +19,8 @@ esac
# Set all the variables to find the source and build trees.
SYSTEMTAP_TAPSET="${srcdir}/tapset"
SYSTEMTAP_RUNTIME="${srcdir}/runtime"
-SYSTEMTAP_STAPIO="${builddir}/stapio"
-SYSTEMTAP_STAPRUN="sudo 'SYSTEMTAP_STAPIO=$SYSTEMTAP_STAPIO' \
- 'SYSTEMTAP_STAPRUN=${builddir}/staprun' \
- ${builddir}/staprun"
-export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN SYSTEMTAP_STAPIO
+SYSTEMTAP_STAPRUN="${builddir}/run-staprun"
+export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN
# If there were private elfutils libs built, use them.
if [ -d "$rundir/lib-elfutils" ]; then
diff --git a/run-staprun.in b/run-staprun.in
new file mode 100644
index 00000000..e0615556
--- /dev/null
+++ b/run-staprun.in
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+srcdir='@abs_top_srcdir@'
+builddir='@abs_top_builddir@'
+
+rundir="${0%/*}"
+[ "$rundir" == "$0" ] || builddir="$rundir"
+
+# Absolutify the paths.
+case "$srcdir" in
+/*) ;;
+*) srcdir=`cd "$srcdir" && pwd` || exit ;;
+esac
+case "$builddir" in
+/*) ;;
+*) builddir=`cd "$builddir" && pwd` || exit ;;
+esac
+
+exec sudo -P "SYSTEMTAP_STAPIO=${builddir}/stapio" \
+ "SYSTEMTAP_STAPRUN=${builddir}/run-staprun" \
+ "SYSTEMTAP_RUNTIME=${srcdir}/runtime" \
+ "SYSTEMTAP_REAL_UID=`id -ru`" \
+ "SYSTEMTAP_REAL_GID=`id -rg`" \
+ ${builddir}/staprun ${1+"$@"}
diff --git a/runtime/autoconf-asm-syscall.c b/runtime/autoconf-asm-syscall.c
new file mode 100644
index 00000000..bf7a273f
--- /dev/null
+++ b/runtime/autoconf-asm-syscall.c
@@ -0,0 +1,2 @@
+#include <asm/syscall.h>
+
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index 16ddb950..620e1615 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -29,11 +29,12 @@
& (((__typeof (base)) 1 << (nbits)) - 1))
#define store_bitfield(target, base, higherbits, nbits) \
- target = (target \
- &~ ((((__typeof (base)) 1 << (nbits)) - 1) \
- << (sizeof (base) * 8 - (higherbits) - (nbits))) \
- | ((__typeof (base)) (base) \
- << (sizeof (base) * 8 - (higherbits) - (nbits))))
+ target = ((target \
+ &~ ((((__typeof (target)) 1 << (nbits)) - 1) \
+ << (sizeof (target) * 8 - (higherbits) - (nbits)))) \
+ | ((((__typeof (target)) (base)) \
+ & (((__typeof (target)) 1 << (nbits)) - 1)) \
+ << (sizeof (target) * 8 - (higherbits) - (nbits))))
/* Given a DWARF register number, fetch its intptr_t (long) value from the
@@ -62,6 +63,10 @@
must work right for kernel addresses, and can use whatever existing
machine-specific kernel macros are convenient. */
+#if STP_SKIP_BADVARS
+#define DEREF_FAULT(addr) ({0; })
+#define STORE_DEREF_FAULT(addr) ({0; })
+#else
#define DEREF_FAULT(addr) ({ \
snprintf(c->error_buffer, sizeof(c->error_buffer), \
"kernel read fault at 0x%p (%s)", (void *)(intptr_t)(addr), #addr); \
@@ -75,7 +80,7 @@
c->last_error = c->error_buffer; \
goto deref_fault; \
})
-
+#endif
#if defined (STAPCONF_X86_UNIREGS) && defined (__i386__)
diff --git a/runtime/map-gen.c b/runtime/map-gen.c
index c4bdf2c7..fdb75089 100644
--- a/runtime/map-gen.c
+++ b/runtime/map-gen.c
@@ -26,6 +26,14 @@
#define JOIN5x(a,b,c,d,e,f) a##_##b##c##d##e##f
#define JOIN6(a,b,c,d,e,f,g) JOIN6x(a,b,c,d,e,f,g)
#define JOIN6x(a,b,c,d,e,f,g) a##_##b##c##d##e##f##g
+#define JOIN7(a,b,c,d,e,f,g,h) JOIN7x(a,b,c,d,e,f,g,h)
+#define JOIN7x(a,b,c,d,e,f,g,h) a##_##b##c##d##e##f##g##h
+#define JOIN8(a,b,c,d,e,f,g,h,i) JOIN8x(a,b,c,d,e,f,g,h,i)
+#define JOIN8x(a,b,c,d,e,f,g,h,i) a##_##b##c##d##e##f##g##h##i
+#define JOIN9(a,b,c,d,e,f,g,h,i,j) JOIN9x(a,b,c,d,e,f,g,h,i,j)
+#define JOIN9x(a,b,c,d,e,f,g,h,i,j) a##_##b##c##d##e##f##g##h##i##j
+#define JOIN10(a,b,c,d,e,f,g,h,i,j,k) JOIN10x(a,b,c,d,e,f,g,h,i,j,k)
+#define JOIN10x(a,b,c,d,e,f,g,h,i,j,k) a##_##b##c##d##e##f##g##h##i##j##k
#include "map.h"
@@ -162,6 +170,113 @@
#define KEY5_HASH JOIN(KEY5NAME,hash)
#endif /* defined(KEY5_TYPE) */
+#if defined (KEY6_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 6
+#if KEY6_TYPE == STRING
+#define KEY6TYPE char*
+#define KEY6NAME str
+#define KEY6N s
+#define KEY6STOR char key6[MAP_STRING_LENGTH]
+#define KEY6CPY(m) str_copy(m->key6, key6)
+#else
+#define KEY6TYPE int64_t
+#define KEY6NAME int64
+#define KEY6N i
+#define KEY6STOR int64_t key6
+#define KEY6CPY(m) m->key6=key6
+#endif
+#define KEY6_EQ_P JOIN(KEY6NAME,eq_p)
+#define KEY6_HASH JOIN(KEY6NAME,hash)
+#endif /* defined(KEY6_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY8_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 8
+#if KEY8_TYPE == STRING
+#define KEY8TYPE char*
+#define KEY8NAME str
+#define KEY8N s
+#define KEY8STOR char key8[MAP_STRING_LENGTH]
+#define KEY8CPY(m) str_copy(m->key8, key8)
+#else
+#define KEY8TYPE int64_t
+#define KEY8NAME int64
+#define KEY8N i
+#define KEY8STOR int64_t key8
+#define KEY8CPY(m) m->key8=key8
+#endif
+#define KEY8_EQ_P JOIN(KEY8NAME,eq_p)
+#define KEY8_HASH JOIN(KEY8NAME,hash)
+#endif /* defined(KEY8_TYPE) */
+
+#if defined (KEY9_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 9
+#if KEY9_TYPE == STRING
+#define KEY9TYPE char*
+#define KEY9NAME str
+#define KEY9N s
+#define KEY9STOR char key9[MAP_STRING_LENGTH]
+#define KEY9CPY(m) str_copy(m->key9, key9)
+#else
+#define KEY9TYPE int64_t
+#define KEY9NAME int64
+#define KEY9N i
+#define KEY9STOR int64_t key9
+#define KEY9CPY(m) m->key9=key9
+#endif
+#define KEY9_EQ_P JOIN(KEY9NAME,eq_p)
+#define KEY9_HASH JOIN(KEY9NAME,hash)
+#endif /* defined(KEY9_TYPE) */
+
+/* Not so many, cowboy! */
+#if defined (KEY10_TYPE)
+#error "excessive key arity == too many array indexes"
+#endif
+
+
+
#if KEY_ARITY == 1
#define KEYSYM(x) JOIN2(x,KEY1N,VALN)
#define ALLKEYS(x) x##1
@@ -187,6 +302,26 @@
#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5
#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5
#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);}
+#elif KEY_ARITY == 6
+#define KEYSYM(x) JOIN7(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);}
+#elif KEY_ARITY == 7
+#define KEYSYM(x) JOIN8(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);}
+#elif KEY_ARITY == 8
+#define KEYSYM(x) JOIN9(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);}
+#elif KEY_ARITY == 9
+#define KEYSYM(x) JOIN10(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,KEY9N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8, KEY9TYPE x##9
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);KEY9CPY(m);}
#endif
/* */
@@ -208,6 +343,18 @@ struct KEYSYM(map_node) {
KEY4STOR;
#if KEY_ARITY > 4
KEY5STOR;
+#if KEY_ARITY > 5
+ KEY6STOR;
+#if KEY_ARITY > 6
+ KEY7STOR;
+#if KEY_ARITY > 7
+ KEY8STOR;
+#if KEY_ARITY > 8
+ KEY9STOR;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -266,6 +413,34 @@ static key_data KEYSYM(map_get_key) (struct map_node *mn, int n, int *type)
if (type)
*type = type_to_enum(KEY5TYPE);
break;
+#if KEY_ARITY > 5
+ case 6:
+ ptr = (key_data)m->key6;
+ if (type)
+ *type = type_to_enum(KEY6TYPE);
+ break;
+#if KEY_ARITY > 6
+ case 7:
+ ptr = (key_data)m->key7;
+ if (type)
+ *type = type_to_enum(KEY7TYPE);
+ break;
+#if KEY_ARITY > 7
+ case 8:
+ ptr = (key_data)m->key8;
+ if (type)
+ *type = type_to_enum(KEY8TYPE);
+ break;
+#if KEY_ARITY > 8
+ case 9:
+ ptr = (key_data)m->key9;
+ if (type)
+ *type = type_to_enum(KEY9TYPE);
+ break;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -309,6 +484,34 @@ static unsigned int KEYSYM(keycheck) (ALLKEYSD(key))
if (key5 == NULL)
return 0;
#endif
+
+#if KEY_ARITY > 5
+#if KEY6_TYPE == STRING
+ if (key6 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 6
+#if KEY7_TYPE == STRING
+ if (key7 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 7
+#if KEY8_TYPE == STRING
+ if (key8 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 8
+#if KEY9_TYPE == STRING
+ if (key9 == NULL)
+ return 0;
+#endif
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -327,6 +530,18 @@ static unsigned int KEYSYM(hash) (ALLKEYSD(key))
hash ^= KEY4_HASH(key4);
#if KEY_ARITY > 4
hash ^= KEY5_HASH(key5);
+#if KEY_ARITY > 5
+ hash ^= KEY6_HASH(key6);
+#if KEY_ARITY > 6
+ hash ^= KEY7_HASH(key7);
+#if KEY_ARITY > 7
+ hash ^= KEY8_HASH(key8);
+#if KEY_ARITY > 8
+ hash ^= KEY9_HASH(key9);
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -411,6 +626,18 @@ static int KEYSYM(__stp_map_set) (MAP map, ALLKEYSD(key), VSTYPE val, int add)
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -462,6 +689,18 @@ static VALTYPE KEYSYM(_stp_map_get) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -498,6 +737,18 @@ static int KEYSYM(_stp_map_del) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -535,6 +786,18 @@ static int KEYSYM(_stp_map_exists) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -582,6 +845,34 @@ static int KEYSYM(_stp_map_exists) (MAP map, ALLKEYSD(key))
#undef KEY5STOR
#undef KEY5CPY
+#undef KEY6NAME
+#undef KEY6N
+#undef KEY6TYPE
+#undef KEY6_TYPE
+#undef KEY6STOR
+#undef KEY6CPY
+
+#undef KEY7NAME
+#undef KEY7N
+#undef KEY7TYPE
+#undef KEY7_TYPE
+#undef KEY7STOR
+#undef KEY7CPY
+
+#undef KEY8NAME
+#undef KEY8N
+#undef KEY8TYPE
+#undef KEY8_TYPE
+#undef KEY8STOR
+#undef KEY8CPY
+
+#undef KEY9NAME
+#undef KEY9N
+#undef KEY9TYPE
+#undef KEY9_TYPE
+#undef KEY9STOR
+#undef KEY9CPY
+
#undef KEY_ARITY
#undef ALLKEYS
#undef ALLKEYSD
diff --git a/runtime/pmap-gen.c b/runtime/pmap-gen.c
index 86c3dc42..c95adc6b 100644
--- a/runtime/pmap-gen.c
+++ b/runtime/pmap-gen.c
@@ -26,6 +26,14 @@
#define JOIN5x(a,b,c,d,e,f) a##_##b##c##d##e##f
#define JOIN6(a,b,c,d,e,f,g) JOIN6x(a,b,c,d,e,f,g)
#define JOIN6x(a,b,c,d,e,f,g) a##_##b##c##d##e##f##g
+#define JOIN7(a,b,c,d,e,f,g,h) JOIN7x(a,b,c,d,e,f,g,h)
+#define JOIN7x(a,b,c,d,e,f,g,h) a##_##b##c##d##e##f##g##h
+#define JOIN8(a,b,c,d,e,f,g,h,i) JOIN8x(a,b,c,d,e,f,g,h,i)
+#define JOIN8x(a,b,c,d,e,f,g,h,i) a##_##b##c##d##e##f##g##h##i
+#define JOIN9(a,b,c,d,e,f,g,h,i,j) JOIN9x(a,b,c,d,e,f,g,h,i,j)
+#define JOIN9x(a,b,c,d,e,f,g,h,i,j) a##_##b##c##d##e##f##g##h##i##j
+#define JOIN10(a,b,c,d,e,f,g,h,i,j,k) JOIN10x(a,b,c,d,e,f,g,h,i,j,k)
+#define JOIN10x(a,b,c,d,e,f,g,h,i,j,k) a##_##b##c##d##e##f##g##h##i##j##k
#include "map.h"
@@ -162,6 +170,113 @@
#define KEY5_HASH JOIN(KEY5NAME,hash)
#endif /* defined(KEY5_TYPE) */
+#if defined (KEY6_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 6
+#if KEY6_TYPE == STRING
+#define KEY6TYPE char*
+#define KEY6NAME str
+#define KEY6N s
+#define KEY6STOR char key6[MAP_STRING_LENGTH]
+#define KEY6CPY(m) str_copy(m->key6, key6)
+#else
+#define KEY6TYPE int64_t
+#define KEY6NAME int64
+#define KEY6N i
+#define KEY6STOR int64_t key6
+#define KEY6CPY(m) m->key6=key6
+#endif
+#define KEY6_EQ_P JOIN(KEY6NAME,eq_p)
+#define KEY6_HASH JOIN(KEY6NAME,hash)
+#endif /* defined(KEY6_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY7_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 7
+#if KEY7_TYPE == STRING
+#define KEY7TYPE char*
+#define KEY7NAME str
+#define KEY7N s
+#define KEY7STOR char key7[MAP_STRING_LENGTH]
+#define KEY7CPY(m) str_copy(m->key7, key7)
+#else
+#define KEY7TYPE int64_t
+#define KEY7NAME int64
+#define KEY7N i
+#define KEY7STOR int64_t key7
+#define KEY7CPY(m) m->key7=key7
+#endif
+#define KEY7_EQ_P JOIN(KEY7NAME,eq_p)
+#define KEY7_HASH JOIN(KEY7NAME,hash)
+#endif /* defined(KEY7_TYPE) */
+
+#if defined (KEY8_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 8
+#if KEY8_TYPE == STRING
+#define KEY8TYPE char*
+#define KEY8NAME str
+#define KEY8N s
+#define KEY8STOR char key8[MAP_STRING_LENGTH]
+#define KEY8CPY(m) str_copy(m->key8, key8)
+#else
+#define KEY8TYPE int64_t
+#define KEY8NAME int64
+#define KEY8N i
+#define KEY8STOR int64_t key8
+#define KEY8CPY(m) m->key8=key8
+#endif
+#define KEY8_EQ_P JOIN(KEY8NAME,eq_p)
+#define KEY8_HASH JOIN(KEY8NAME,hash)
+#endif /* defined(KEY8_TYPE) */
+
+#if defined (KEY9_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 9
+#if KEY9_TYPE == STRING
+#define KEY9TYPE char*
+#define KEY9NAME str
+#define KEY9N s
+#define KEY9STOR char key9[MAP_STRING_LENGTH]
+#define KEY9CPY(m) str_copy(m->key9, key9)
+#else
+#define KEY9TYPE int64_t
+#define KEY9NAME int64
+#define KEY9N i
+#define KEY9STOR int64_t key9
+#define KEY9CPY(m) m->key9=key9
+#endif
+#define KEY9_EQ_P JOIN(KEY9NAME,eq_p)
+#define KEY9_HASH JOIN(KEY9NAME,hash)
+#endif /* defined(KEY9_TYPE) */
+
+/* Not so many, cowboy! */
+#if defined (KEY10_TYPE)
+#error "excessive key arity == too many array indexes"
+#endif
+
+
+
#if KEY_ARITY == 1
#define KEYSYM(x) JOIN2(x,KEY1N,VALN)
#define ALLKEYS(x) x##1
@@ -187,6 +302,26 @@
#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5
#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5
#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);}
+#elif KEY_ARITY == 6
+#define KEYSYM(x) JOIN7(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);}
+#elif KEY_ARITY == 7
+#define KEYSYM(x) JOIN8(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);}
+#elif KEY_ARITY == 8
+#define KEYSYM(x) JOIN9(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);}
+#elif KEY_ARITY == 9
+#define KEYSYM(x) JOIN10(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,KEY9N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8, KEY9TYPE x##9
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);KEY9CPY(m);}
#endif
/* */
@@ -208,6 +343,18 @@ struct KEYSYM(pmap_node) {
KEY4STOR;
#if KEY_ARITY > 4
KEY5STOR;
+#if KEY_ARITY > 5
+ KEY6STOR;
+#if KEY_ARITY > 6
+ KEY7STOR;
+#if KEY_ARITY > 7
+ KEY8STOR;
+#if KEY_ARITY > 8
+ KEY9STOR;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -238,6 +385,18 @@ static int KEYSYM(pmap_key_cmp) (struct map_node *m1, struct map_node *m2)
&& KEY4_EQ_P(n1->key4, n2->key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n1->key5, n2->key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n1->key6, n2->key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n1->key7, n2->key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n1->key8, n2->key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n1->key9, n2->key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -282,6 +441,34 @@ static void KEYSYM(pmap_copy_keys) (struct map_node *m1, struct map_node *m2)
#else
dst->key5 = src->key5;
#endif
+#if KEY_ARITY > 5
+#if KEY6_TYPE == STRING
+ str_copy (dst->key6, src->key6);
+#else
+ dst->key6 = src->key6;
+#endif
+#if KEY_ARITY > 6
+#if KEY7_TYPE == STRING
+ str_copy (dst->key7, src->key7);
+#else
+ dst->key7 = src->key7;
+#endif
+#if KEY_ARITY > 7
+#if KEY8_TYPE == STRING
+ str_copy (dst->key8, src->key8);
+#else
+ dst->key8 = src->key8;
+#endif
+#if KEY_ARITY > 8
+#if KEY9_TYPE == STRING
+ str_copy (dst->key9, src->key9);
+#else
+ dst->key9 = src->key9;
+#endif
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -330,6 +517,34 @@ static key_data KEYSYM(pmap_get_key) (struct map_node *mn, int n, int *type)
if (type)
*type = type_to_enum(KEY5TYPE);
break;
+#if KEY_ARITY > 5
+ case 6:
+ ptr = (key_data)m->key6;
+ if (type)
+ *type = type_to_enum(KEY6TYPE);
+ break;
+#if KEY_ARITY > 6
+ case 7:
+ ptr = (key_data)m->key7;
+ if (type)
+ *type = type_to_enum(KEY7TYPE);
+ break;
+#if KEY_ARITY > 7
+ case 8:
+ ptr = (key_data)m->key8;
+ if (type)
+ *type = type_to_enum(KEY8TYPE);
+ break;
+#if KEY_ARITY > 8
+ case 9:
+ ptr = (key_data)m->key9;
+ if (type)
+ *type = type_to_enum(KEY9TYPE);
+ break;
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -373,6 +588,34 @@ static unsigned int KEYSYM(pkeycheck) (ALLKEYSD(key))
if (key5 == NULL)
return 0;
#endif
+
+#if KEY_ARITY > 5
+#if KEY6_TYPE == STRING
+ if (key6 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 6
+#if KEY7_TYPE == STRING
+ if (key7 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 7
+#if KEY8_TYPE == STRING
+ if (key8 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 8
+#if KEY9_TYPE == STRING
+ if (key9 == NULL)
+ return 0;
+#endif
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -391,6 +634,18 @@ static unsigned int KEYSYM(phash) (ALLKEYSD(key))
hash ^= KEY4_HASH(key4);
#if KEY_ARITY > 4
hash ^= KEY5_HASH(key5);
+#if KEY_ARITY > 5
+ hash ^= KEY6_HASH(key6);
+#if KEY_ARITY > 6
+ hash ^= KEY7_HASH(key7);
+#if KEY_ARITY > 7
+ hash ^= KEY8_HASH(key8);
+#if KEY_ARITY > 8
+ hash ^= KEY9_HASH(key9);
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -504,6 +759,18 @@ static int KEYSYM(__stp_pmap_set) (MAP map, ALLKEYSD(key), VSTYPE val, int add)
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -587,6 +854,18 @@ static VALTYPE KEYSYM(_stp_pmap_get_cpu) (PMAP pmap, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -637,6 +916,18 @@ static VALTYPE KEYSYM(_stp_pmap_get) (PMAP pmap, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -669,6 +960,18 @@ static VALTYPE KEYSYM(_stp_pmap_get) (PMAP pmap, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -723,6 +1026,18 @@ static int KEYSYM(__stp_pmap_del) (MAP map, ALLKEYSD(key))
&& KEY4_EQ_P(n->key4, key4)
#if KEY_ARITY > 4
&& KEY5_EQ_P(n->key5, key5)
+#if KEY_ARITY > 5
+ && KEY6_EQ_P(n->key6, key6)
+#if KEY_ARITY > 6
+ && KEY7_EQ_P(n->key7, key7)
+#if KEY_ARITY > 7
+ && KEY8_EQ_P(n->key8, key8)
+#if KEY_ARITY > 8
+ && KEY9_EQ_P(n->key9, key9)
+#endif
+#endif
+#endif
+#endif
#endif
#endif
#endif
@@ -788,6 +1103,34 @@ static int KEYSYM(_stp_pmap_del) (PMAP pmap, ALLKEYSD(key))
#undef KEY5STOR
#undef KEY5CPY
+#undef KEY6NAME
+#undef KEY6N
+#undef KEY6TYPE
+#undef KEY6_TYPE
+#undef KEY6STOR
+#undef KEY6CPY
+
+#undef KEY7NAME
+#undef KEY7N
+#undef KEY7TYPE
+#undef KEY7_TYPE
+#undef KEY7STOR
+#undef KEY7CPY
+
+#undef KEY8NAME
+#undef KEY8N
+#undef KEY8TYPE
+#undef KEY8_TYPE
+#undef KEY8STOR
+#undef KEY8CPY
+
+#undef KEY9NAME
+#undef KEY9N
+#undef KEY9TYPE
+#undef KEY9_TYPE
+#undef KEY9STOR
+#undef KEY9CPY
+
#undef KEY_ARITY
#undef ALLKEYS
#undef ALLKEYSD
diff --git a/runtime/runtime.h b/runtime/runtime.h
index fc5d454f..c2e927cc 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -66,6 +66,13 @@ static struct
#define MAXTRACE 20
#endif
+/* dwarf unwinder only tested so far on i386 and x86_64. */
+#if (defined(__i386__) || defined(__x86_64__))
+#ifndef STP_USE_DWARF_UNWINDER
+#define STP_USE_DWARF_UNWINDER
+#endif
+#endif
+
#ifdef CONFIG_FRAME_POINTER
/* Just because frame pointers are available does not mean we can trust them. */
#ifndef STP_USE_DWARF_UNWINDER
@@ -73,19 +80,17 @@ static struct
#endif
#endif
-/* dwarf unwinder only tested so far on i386 and x86_64,
- but globally disabled for now */
-#if 0
-// !defined(STP_USE_FRAME_BUFFER) && (defined(__i386__) || defined(__x86_64__))
-#define STP_USE_DWARF_UNWINDER
-#endif
-
#include "alloc.c"
#include "print.c"
#include "string.c"
#include "io.c"
#include "arith.c"
#include "copy.c"
+#include "regs.c"
+#include "regs-ia64.c"
+
+#include "task_finder.c"
+
#include "sym.c"
#ifdef STP_PERFMON
#include "perf.c"
diff --git a/runtime/stack.c b/runtime/stack.c
index f6b1cd08..68fb9b1f 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -97,6 +97,12 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
&print_data);
}
#endif
+
+// Without KPROBES very little works atm.
+// But this file is unconditionally imported, while these two functions are only
+// used through context-unwind.stp.
+#if defined (CONFIG_KPROBES)
+
/** Prints the stack backtrace
* @param regs A pointer to the struct pt_regs.
*/
@@ -141,6 +147,8 @@ static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int ve
pb->len = 0;
}
+#endif /* CONFIG_KPROBES */
+
/** Prints the user stack backtrace
* @param str string
* @returns Same string as was input with trace info appended,
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index 8200ec9d..26b166c2 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -82,7 +82,7 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t)
num = tm.tm_year % 100;
goto numbering02;
case 'C':
- num = ((tm.tm_year + 1900 - 1) / 100) + 1;
+ num = ((tm.tm_year + 1900) / 100);
goto numbering;
case 'm':
num = tm.tm_mon + 1;
@@ -107,7 +107,7 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t)
if (num == 0) num = 12;
goto numbering02;
case 'j':
- ret = snprintf(c, end - c, "%03d", tm.tm_yday);
+ ret = snprintf(c, end - c, "%03d", tm.tm_yday + 1);
if (ret < 0) return ret;
c += ret;
break;
@@ -117,7 +117,10 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t)
case 'l':
num = tm.tm_hour % 12;
if (num == 0) num = 12;
- goto numbering;
+ ret = snprintf(c, end - c, "%2d", num);
+ if (ret < 0) return ret;
+ c += ret;
+ break;
case 'M':
num = tm.tm_min;
goto numbering02;
diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c
index 50f295b5..b9796241 100644
--- a/runtime/staprun/relay.c
+++ b/runtime/staprun/relay.c
@@ -185,7 +185,7 @@ static void *reader_thread(void *data)
dbug(3, "cpu=%d poll=%d errno=%d\n", cpu, rc, errno);
if (errno != EINTR) {
_perr("poll error");
- return(NULL);
+ goto error_out;
}
}
while ((rc = read(relay_fd[cpu], buf, sizeof(buf))) > 0) {
@@ -198,17 +198,24 @@ static void *reader_thread(void *data)
remove_file = 1;
if (open_outfile(fnum, cpu, remove_file) < 0) {
perr("Couldn't open file for cpu %d, exiting.", cpu);
- return(NULL);
+ goto error_out;
}
- wsize = 0;
+ wsize = rc;
}
if (write(out_fd[cpu], buf, rc) != rc) {
- perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu);
- return(NULL);
+ if (errno != EPIPE)
+ perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu);
+ goto error_out;
}
}
} while (!stop_threads);
- dbug(3, "exiting thread %d\n", cpu);
+ dbug(3, "exiting thread for cpu %d\n", cpu);
+ return(NULL);
+
+error_out:
+ /* Signal the main thread that we need to quit */
+ kill(getpid(), SIGTERM);
+ dbug(2, "exiting thread for cpu %d after error\n", cpu);
return(NULL);
}
diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c
index ef8fd0da..33d2daf3 100644
--- a/runtime/staprun/relay_old.c
+++ b/runtime/staprun/relay_old.c
@@ -239,14 +239,15 @@ static int process_subbufs(struct _stp_buf_info *info,
scb->rmfile = 1;
if (open_oldoutfile(scb->fnum, cpu, scb->rmfile) < 0) {
perr("Couldn't open file for cpu %d, exiting.", cpu);
- exit(1);
+ return -1;
}
- scb->wsize = 0;
+ scb->wsize = len;
}
if (len) {
if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) {
- _perr("Couldn't write to output file for cpu %d, exiting:", cpu);
- exit(1);
+ if (errno != EPIPE)
+ _perr("Couldn't write to output file for cpu %d, exiting:", cpu);
+ return -1;
}
}
subbufs_consumed++;
@@ -281,14 +282,17 @@ static void *reader_thread(void *data)
if (rc < 0) {
if (errno != EINTR) {
_perr("poll error");
- exit(1);
+ break;
}
err("WARNING: poll warning: %s\n", strerror(errno));
rc = 0;
}
rc = read(proc_fd[cpu], &status[cpu].info, sizeof(struct _stp_buf_info));
- subbufs_consumed = process_subbufs(&status[cpu].info, &scb);
+ rc = process_subbufs(&status[cpu].info, &scb);
+ if (rc < 0)
+ break;
+ subbufs_consumed = rc;
if (subbufs_consumed) {
if (subbufs_consumed > status[cpu].max_backlog)
status[cpu].max_backlog = subbufs_consumed;
@@ -301,6 +305,10 @@ static void *reader_thread(void *data)
if (status[cpu].info.flushing)
pthread_exit(NULL);
} while (1);
+
+ /* Signal the main thread that we need to quit */
+ kill(getpid(), SIGTERM);
+ pthread_exit(NULL);
}
/**
@@ -320,7 +328,7 @@ int write_realtime_data(void *data, ssize_t nb)
perr("Couldn't open file, exiting.");
return -1;
}
- global_scb.wsize = 0;
+ global_scb.wsize = nb;
}
bw = write(out_fd[0], data, nb);
if (bw >= 0 && bw != nb) {
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index e94e5d13..49b37988 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -316,8 +316,21 @@ int check_permissions(void)
int path_check = 0;
/* If we're root, we can do anything. */
- if (getuid() == 0)
+ if (getuid() == 0) {
+ /* ... like overriding the real UID */
+ const char *env_id = getenv("SYSTEMTAP_REAL_UID");
+ if (env_id && setreuid(atoi(env_id), -1))
+ err("WARNING: couldn't set staprun UID to '%s': %s",
+ env_id, strerror(errno));
+
+ /* ... or overriding the real GID */
+ env_id = getenv("SYSTEMTAP_REAL_GID");
+ if (env_id && setregid(atoi(env_id), -1))
+ err("WARNING: couldn't set staprun GID to '%s': %s",
+ env_id, strerror(errno));
+
return 1;
+ }
/* Lookup the gid for group "stapdev" */
errno = 0;
diff --git a/runtime/sym.c b/runtime/sym.c
index 1d88a862..f6f97ac2 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -13,6 +13,7 @@
#define _STP_SYM_C_
#include "string.c"
+#include "task_finder_vma.c"
/** @file sym.c
* @addtogroup sym Symbolic Functions
@@ -20,6 +21,62 @@
* @{
*/
+static void _stp_sym_init(void)
+{
+ static int initialized = 0;
+ if (! initialized) {
+ __stp_tf_vma_initialize();
+ initialized = 1;
+ }
+}
+
+/* Callback that needs to be registered (in tapsets.cxx for
+ emit_module_init) for every user task path or pid for which we
+ might need symbols or unwind info. */
+static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ char *path,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long offset,
+ unsigned long vm_flags)
+{
+ int i;
+ struct _stp_module *module = NULL;
+
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "mmap_cb: tsk %d:%d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n",
+ tsk->pid, tsk->tgid, path, addr, length, offset, vm_flags);
+#endif
+ if (path != NULL) {
+ for (i = 0; i < _stp_num_modules; i++) {
+ if (strcmp(path, _stp_modules[i]->path) == 0)
+ {
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "vm_cb: matched path %s to module\n",
+ path);
+#endif
+ module = _stp_modules[i];
+ break;
+ }
+ }
+ }
+ stap_add_vma_map_info(tsk->group_leader, addr, addr + length, offset,
+ module);
+ return 0;
+}
+
+static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length)
+{
+ stap_remove_vma_map_info(tsk->group_leader, addr, addr + length, 0);
+ return 0;
+}
+
/* XXX: this needs to be address-space-specific. */
static unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset)
{
@@ -71,35 +128,54 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio
return 0;
}
-
-/* Return module owner and fills in closest section of the address
- if found, return NULL otherwise.
+/* Return module owner and, if sec != NULL, fills in closest section
+ of the address if found, return NULL otherwise.
XXX: needs to be address-space-specific. */
static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
+ struct task_struct *task,
struct _stp_section **sec)
{
- struct _stp_module *m = NULL;
+ void *user = NULL;
unsigned midx = 0;
- unsigned long closest_section_offset = ~0;
+
+ // Try vma matching first if task given.
+ if (task)
+ {
+ unsigned long vm_start = 0;
+ if (stap_find_vma_map_info(task->group_leader, addr,
+ &vm_start, NULL,
+ NULL, &user) == 0)
+ if (user != NULL)
+ {
+ struct _stp_module *m = (struct _stp_module *)user;
+ if (sec)
+ *sec = &m->sections[0]; // XXX check actual section and relocate
+ dbug_sym(1, "found section %s in module %s at 0x%lx\n",
+ m->sections[0].name, m->name, vm_start);
+ if (strcmp(".dynamic", m->sections[0].name) == 0)
+ m->sections[0].addr = vm_start; // cheat...
+ return m;
+ }
+ }
+
for (midx = 0; midx < _stp_num_modules; midx++)
{
unsigned secidx;
for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++)
{
- unsigned long this_section_addr;
- unsigned long this_section_offset;
- this_section_addr = _stp_modules[midx]->sections[secidx].addr;
- if (addr < this_section_addr) continue;
- this_section_offset = addr - this_section_addr;
- if (this_section_offset < closest_section_offset)
- {
- closest_section_offset = this_section_offset;
- m = _stp_modules[midx];
- *sec = & m->sections[secidx];
+ unsigned long sec_addr;
+ unsigned long sec_size;
+ sec_addr = _stp_modules[midx]->sections[secidx].addr;
+ sec_size = _stp_modules[midx]->sections[secidx].size;
+ if (addr >= sec_addr && addr < sec_addr + sec_size)
+ {
+ if (sec)
+ *sec = & _stp_modules[midx]->sections[secidx];
+ return _stp_modules[midx];
}
}
}
- return m;
+ return NULL;
}
@@ -108,14 +184,15 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo
unsigned long *offset,
const char **modname,
/* char ** secname? */
- char *namebuf)
+ char *namebuf,
+ struct task_struct *task)
{
struct _stp_module *m = NULL;
struct _stp_section *sec = NULL;
struct _stp_symbol *s = NULL;
unsigned end, begin = 0;
- m = _stp_mod_sec_lookup(addr, &sec);
+ m = _stp_mod_sec_lookup(addr, task, &sec);
if (unlikely (m == NULL || sec == NULL))
return NULL;
@@ -240,7 +317,7 @@ static void _stp_symbol_print(unsigned long address)
const char *name;
unsigned long offset, size;
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL);
_stp_printf("%p", (int64_t) address);
@@ -265,7 +342,7 @@ static int _stp_func_print(unsigned long address, int verbose, int exact)
else
exstr = " (inexact)";
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL);
if (name) {
if (verbose) {
@@ -281,16 +358,29 @@ static int _stp_func_print(unsigned long address, int verbose, int exact)
return 0;
}
-static void _stp_symbol_snprint(char *str, size_t len, unsigned long address)
+/** Puts symbolic information of an address in a string.
+ * @param src The string to fill in.
+ * @param len The length of the given src string.
+ * @param address The address to lookup.
+ * @param add_mod Whether to include module name information if found.
+ */
+
+static void _stp_symbol_snprint(char *str, size_t len, unsigned long address,
+ struct task_struct *task, int add_mod)
{
const char *modname;
const char *name;
unsigned long offset, size;
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
- if (name)
- strlcpy(str, name, len);
- else
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL,
+ task);
+ if (name) {
+ if (add_mod && modname && *modname)
+ _stp_snprintf(str, len, "%s %s+%#lx/%#lx",
+ name, modname, offset, size);
+ else
+ strlcpy(str, name, len);
+ } else
_stp_snprintf(str, len, "%p", (int64_t) address);
}
diff --git a/runtime/sym.h b/runtime/sym.h
index 586b10ca..80c334fb 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -18,6 +18,7 @@ struct _stp_symbol {
struct _stp_section {
const char *name;
unsigned long addr; /* XXX: belongs in per-address-space tables */
+ unsigned long size; /* length of the address space module covers. */
struct _stp_symbol *symbols; /* ordered by address */
unsigned num_symbols;
};
diff --git a/runtime/syscall.h b/runtime/syscall.h
index ae451070..6d22ba83 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -1,5 +1,6 @@
-/* syscall defines and inlines
- * Copyright (C) 2008 Red Hat Inc.
+/*
+ * syscall defines and inlines
+ * Copyright (C) 2008-2009 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
@@ -89,9 +90,17 @@
#error "Unimplemented architecture"
#endif
+#ifdef STAPCONF_ASM_SYSCALL_H
+
+/* If the system has asm/syscall.h, use defines from it. */
+#include <asm/syscall.h>
+
+#else /* !STAPCONF_ASM_SYSCALL_H */
+
+/* If the system doesn't have asm/syscall.h, use our defines. */
#if defined(__i386__) || defined(__x86_64__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
#if defined(STAPCONF_X86_UNIREGS)
return regs->orig_ax;
@@ -104,37 +113,37 @@ __stp_user_syscall_nr(struct pt_regs *regs)
#endif
#if defined(__powerpc__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return regs->gpr[0];
}
#endif
#if defined(__ia64__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return regs->r15;
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline unsigned long
-__stp_user_syscall_nr(struct pt_regs *regs)
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
- // might need to be 'orig_gpr2'
+ // might need to be 'orig_gpr2'
return regs->gprs[2];
}
#endif
#if defined(__i386__) || defined(__x86_64__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
#ifdef CONFIG_IA32_EMULATION
// This code works, but isn't what we need. Since
-// __stp_user_syscall_arg() doesn't sign-extend, a value passed in as
+// syscall_get_syscall_arg() doesn't sign-extend, a value passed in as
// an argument and then returned won't compare correctly anymore. So,
// for now, disable this code.
# if 0
@@ -145,158 +154,233 @@ __stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
# endif
#endif
#if defined(STAPCONF_X86_UNIREGS)
- return &regs->ax;
+ return regs->ax;
#elif defined(__x86_64__)
- return &regs->rax;
+ return regs->rax;
#elif defined (__i386__)
- return &regs->eax;
+ return regs->eax;
#endif
}
#endif
#if defined(__powerpc__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->gpr[3];
+ return regs->gpr[3];
}
#endif
#if defined(__ia64__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->r8;
+ return regs->r8;
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline long *
-__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
- return &regs->gprs[2];
+ return regs->gprs[2];
}
#endif
#if defined(__i386__) || defined(__x86_64__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
-#if defined(__i386__)
- if (n > 5) {
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
}
+#if defined(__i386__)
#if defined(STAPCONF_X86_UNIREGS)
- return &regs->bx + n;
+ memcpy(args, &regs->bx + i, n * sizeof(args[0]));
#else
- return &regs->ebx + n;
+ memcpy(args, &regs->ebx + i, n * sizeof(args[0]));
#endif
#elif defined(__x86_64__)
#ifdef CONFIG_IA32_EMULATION
- if (test_tsk_thread_flag(task, TIF_IA32))
- switch (n) {
+ if (test_tsk_thread_flag(task, TIF_IA32)) {
+ switch (i) {
#if defined(STAPCONF_X86_UNIREGS)
- case 0: return &regs->bx;
- case 1: return &regs->cx;
- case 2: return &regs->dx;
- case 3: return &regs->si;
- case 4: return &regs->di;
- case 5: return &regs->bp;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->bx;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->cx;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->dx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->si;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->di;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->bp;
#else
- case 0: return &regs->rbx;
- case 1: return &regs->rcx;
- case 2: return &regs->rdx;
- case 3: return &regs->rsi;
- case 4: return &regs->rdi;
- case 5: return &regs->rbp;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->rbx;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->rcx;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->rdx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->rsi;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->rdi;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->rbp;
#endif
- default:
- _stp_error("syscall arg > 5");
- return NULL;
}
+ return;
+ }
#endif /* CONFIG_IA32_EMULATION */
- switch (n) {
+ switch (i) {
#if defined(STAPCONF_X86_UNIREGS)
- case 0: return &regs->di;
- case 1: return &regs->si;
- case 2: return &regs->dx;
- case 3: return &regs->r10;
- case 4: return &regs->r8;
- case 5: return &regs->r9;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->di;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->si;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->dx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->r10;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->r8;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->r9;
#else
- case 0: return &regs->rdi;
- case 1: return &regs->rsi;
- case 2: return &regs->rdx;
- case 3: return &regs->r10;
- case 4: return &regs->r8;
- case 5: return &regs->r9;
+ case 0:
+ if (!n--) break;
+ *args++ = regs->rdi;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->rsi;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->rdx;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->r10;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->r8;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->r9;
#endif
- default:
- _stp_error("syscall arg > 5");
- return NULL;
}
#endif /* CONFIG_X86_32 */
+ return;
}
#endif
#if defined(__powerpc__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
- switch (n) {
- case 0: return &regs->gpr[3];
- case 1: return &regs->gpr[4];
- case 2: return &regs->gpr[5];
- case 3: return &regs->gpr[6];
- case 4: return &regs->gpr[7];
- case 5: return &regs->gpr[8];
- default:
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
}
+ memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
}
#endif
#if defined(__ia64__)
-#define __stp_user_syscall_arg(task, regs, n) \
- ____stp_user_syscall_arg(task, regs, n, &c->unwaddr)
+#define syscall_get_arguments(task, regs, i, n, args) \
+ __ia64_syscall_get_arguments(task, regs, i, n, args, &c->unwaddr)
-static inline long *
-____stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n, unsigned long **cache)
+static inline void
+__ia64_syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args, unsigned long **cache)
{
- if (n > 5) {
- _stp_error("syscall arg > 5");
- return NULL;
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
+ }
+ switch (i) {
+ case 0:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 32, regs, cache);
+ case 1:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 33, regs, cache);
+ case 2:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 34, regs, cache);
+ case 3:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 35, regs, cache);
+ case 4:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 36, regs, cache);
+ case 5:
+ if (!n--) break;
+ *args++ = *__ia64_fetch_register(i + 37, regs, cache);
}
- return __ia64_fetch_register(n + 32, regs, cache);
}
#endif
#if defined(__s390__) || defined(__s390x__)
-static inline long *
-__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
- unsigned int n)
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
{
- /* If we were returning a value, we could check for TIF_31BIT
- * here and cast the value with '(u32)' to make sure it got
- * down to 32bits. But, since we're returning an address,
- * there isn't much we can do. */
- switch (n) {
- case 0: return &regs->orig_gpr2;
- case 1: return &regs->gprs[3];
- case 2: return &regs->gprs[4];
- case 3: return &regs->gprs[5];
- case 4: return &regs->gprs[6];
- case 5: return &regs->args[0];
- default:
- _stp_error("syscall arg > 5");
- return NULL;
+ unsigned long mask = -1UL;
+
+ if (i + n > 6) {
+ _stp_error("invalid syscall arg request");
+ return;
+ }
+#ifdef CONFIG_COMPAT
+ if (test_tsk_thread_flag(task, TIF_31BIT))
+ mask = 0xffffffff;
+#endif
+ switch (i) {
+ case 0:
+ if (!n--) break;
+ *args++ = regs->orig_gpr2 & mask;
+ case 1:
+ if (!n--) break;
+ *args++ = regs->gprs[3] & mask;
+ case 2:
+ if (!n--) break;
+ *args++ = regs->gprs[4] & mask;
+ case 3:
+ if (!n--) break;
+ *args++ = regs->gprs[5] & mask;
+ case 4:
+ if (!n--) break;
+ *args++ = regs->gprs[6] & mask;
+ case 5:
+ if (!n--) break;
+ *args++ = regs->args[0] & mask;
}
}
#endif
+#endif /* !STAPCONF_ASM_SYSCALL_H */
#endif /* _SYSCALL_H_ */
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 7949a81f..fa6c296e 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -2,8 +2,9 @@
#define TASK_FINDER_C
#if ! defined(CONFIG_UTRACE)
-#error "Need CONFIG_UTRACE!"
-#endif
+/* Dummy definitions for use in sym.c */
+struct stap_task_finder_target { };
+#else
#include <linux/utrace.h>
@@ -18,7 +19,6 @@
#include "syscall.h"
#include "utrace_compatibility.h"
-#include "task_finder_vma.c"
static LIST_HEAD(__stp_task_finder_list);
@@ -62,46 +62,26 @@ typedef int (*stap_task_finder_callback)(struct stap_task_finder_target *tgt,
int register_p,
int process_p);
-typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- int map_p, char *vm_path,
- unsigned long vm_start,
- unsigned long vm_end,
- unsigned long vm_pgoff);
-
-static int __stp_tf_vm_cb(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- int map_p, char *vm_path,
- unsigned long vm_start,
- unsigned long vm_end,
- unsigned long vm_pgoff)
-{
- int i;
-#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n",
- tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff);
-#endif
- if (map_p) {
- struct _stp_module *module = NULL;
- if (vm_path != NULL)
- for (i = 0; i < _stp_num_modules; i++)
- if (strcmp(vm_path, _stp_modules[i]->path) == 0)
- {
-#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "vm_cb: matched path %s to module\n", vm_path);
-#endif
- module = _stp_modules[i];
- break;
- }
- stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module);
- }
- else {
- stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff);
- }
- return 0;
-}
+typedef int
+(*stap_task_finder_mmap_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ char *path,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long offset,
+ unsigned long vm_flags);
+typedef int
+(*stap_task_finder_munmap_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length);
+
+typedef int
+(*stap_task_finder_mprotect_callback)(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ unsigned long addr,
+ unsigned long length,
+ int prot);
struct stap_task_finder_target {
/* private: */
@@ -110,14 +90,18 @@ struct stap_task_finder_target {
struct list_head callback_list;
struct utrace_engine_ops ops;
unsigned engine_attached:1;
- unsigned vm_events:1;
+ unsigned mmap_events:1;
+ unsigned munmap_events:1;
+ unsigned mprotect_events:1;
size_t pathlen;
/* public: */
const char *pathname;
pid_t pid;
stap_task_finder_callback callback;
- stap_task_finder_vm_callback vm_callback;
+ stap_task_finder_mmap_callback mmap_callback;
+ stap_task_finder_munmap_callback munmap_callback;
+ stap_task_finder_mprotect_callback mprotect_callback;
};
#ifdef UTRACE_ORIG_VERSION
@@ -145,19 +129,6 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
#ifdef UTRACE_ORIG_VERSION
static u32
-__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs);
-#else
-static u32
-__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
- struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs);
-#endif
-
-#ifdef UTRACE_ORIG_VERSION
-static u32
__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
struct task_struct *tsk,
struct pt_regs *regs);
@@ -189,12 +160,12 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
// Make sure everything is initialized properly.
new_tgt->engine_attached = 0;
- new_tgt->vm_events = 0;
+ new_tgt->mmap_events = 0;
+ new_tgt->munmap_events = 0;
+ new_tgt->mprotect_events = 0;
memset(&new_tgt->ops, 0, sizeof(new_tgt->ops));
new_tgt->ops.report_death = &__stp_utrace_task_finder_target_death;
new_tgt->ops.report_quiesce = &__stp_utrace_task_finder_target_quiesce;
- new_tgt->ops.report_syscall_entry = \
- &__stp_utrace_task_finder_target_syscall_entry;
new_tgt->ops.report_syscall_exit = \
&__stp_utrace_task_finder_target_syscall_exit;
@@ -208,7 +179,7 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
&& strcmp(tgt->pathname, new_tgt->pathname) == 0)
/* pid-based target (a specific pid or all
* pids) */
- || (new_tgt->pathlen == 0
+ || (new_tgt->pathlen == 0 && tgt->pathlen == 0
&& tgt->pid == new_tgt->pid))) {
found_node = 1;
break;
@@ -226,9 +197,13 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
// Add this target to the callback list for this task.
list_add_tail(&new_tgt->callback_list, &tgt->callback_list_head);
- // If the new target has a vm_callback, remember this.
- if (new_tgt->vm_callback != NULL)
- tgt->vm_events = 1;
+ // If the new target has any m* callbacks, remember this.
+ if (new_tgt->mmap_callback != NULL)
+ tgt->mmap_events = 1;
+ if (new_tgt->munmap_callback != NULL)
+ tgt->munmap_events = 1;
+ if (new_tgt->mprotect_callback != NULL)
+ tgt->mprotect_events = 1;
return 0;
}
@@ -411,15 +386,14 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
/*
* __STP_TASK_BASE_EVENTS: base events for stap_task_finder_target's
- * without vm_callback's
+ * without map callback's
*
* __STP_TASK_VM_BASE_EVENTS: base events for
- * stap_task_finder_target's with vm_callback's
+ * stap_task_finder_target's with map callback's
*/
#define __STP_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH))
#define __STP_TASK_VM_BASE_EVENTS (__STP_TASK_BASE_EVENTS \
- | UTRACE_EVENT(SYSCALL_ENTRY)\
| UTRACE_EVENT(SYSCALL_EXIT))
/*
@@ -431,8 +405,10 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
#define __STP_ATTACHED_TASK_EVENTS (__STP_TASK_BASE_EVENTS \
| UTRACE_EVENT(QUIESCE))
-#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \
- ((tgt)->vm_events ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS)
+#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \
+ (((tgt)->mmap_events || (tgt)->munmap_events \
+ || (tgt)->mprotect_events) \
+ ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS)
static int
__stp_utrace_attach(struct task_struct *tsk,
@@ -548,11 +524,113 @@ __stp_call_callbacks(struct stap_task_finder_target *tgt,
}
}
+static void
+__stp_call_mmap_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, char *path,
+ unsigned long addr, unsigned long length,
+ unsigned long offset, unsigned long vm_flags)
+{
+ struct list_head *cb_node;
+ int rc;
+
+ if (tgt == NULL || tsk == NULL)
+ return;
+
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__,
+ "pid %d, a/l/o/p/path 0x%lx 0x%lx 0x%lx %c%c%c%c %s\n",
+ tsk->pid, addr, length, offset,
+ vm_flags & VM_READ ? 'r' : '-',
+ vm_flags & VM_WRITE ? 'w' : '-',
+ vm_flags & VM_EXEC ? 'x' : '-',
+ vm_flags & VM_MAYSHARE ? 's' : 'p',
+ path);
+#endif
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+
+ cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL || cb_tgt->mmap_callback == NULL)
+ continue;
+
+ rc = cb_tgt->mmap_callback(cb_tgt, tsk, path, addr, length,
+ offset, vm_flags);
+ if (rc != 0) {
+ _stp_error("mmap callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
+ }
+}
+
+static void
+__stp_call_mmap_callbacks_with_vma(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk,
+ struct vm_area_struct *vma)
+{
+ char *mmpath_buf;
+ char *mmpath;
+ int rc;
+
+ // Allocate space for a path
+ mmpath_buf = _stp_kmalloc(PATH_MAX);
+ if (mmpath_buf == NULL) {
+ _stp_error("Unable to allocate space for path");
+ return;
+ }
+
+ // Grab the path associated with this vma.
+#ifdef STAPCONF_DPATH_PATH
+ mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX);
+#else
+ mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
+ mmpath_buf, PATH_MAX);
+#endif
+ if (mmpath == NULL || IS_ERR(mmpath)) {
+ rc = -PTR_ERR(mmpath);
+ _stp_error("Unable to get path (error %d) for pid %d",
+ rc, (int)tsk->pid);
+ }
+ else {
+ __stp_call_mmap_callbacks(tgt, tsk, mmpath, vma->vm_start,
+ vma->vm_end - vma->vm_start,
+ (vma->vm_pgoff << PAGE_SHIFT),
+ vma->vm_flags);
+ }
+ _stp_kfree(mmpath_buf);
+}
+
+static inline void
+__stp_call_munmap_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, unsigned long addr,
+ unsigned long length)
+{
+ struct list_head *cb_node;
+ int rc;
+
+ if (tgt == NULL || tsk == NULL)
+ return;
+
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+
+ cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL || cb_tgt->munmap_callback == NULL)
+ continue;
+
+ rc = cb_tgt->munmap_callback(cb_tgt, tsk, addr, length);
+ if (rc != 0) {
+ _stp_error("munmap callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
+ }
+}
+
static inline void
-__stp_call_vm_callbacks(struct stap_task_finder_target *tgt,
- struct task_struct *tsk, int map_p, char *vm_path,
- unsigned long vm_start, unsigned long vm_end,
- unsigned long vm_pgoff)
+__stp_call_mprotect_callbacks(struct stap_task_finder_target *tgt,
+ struct task_struct *tsk, unsigned long addr,
+ unsigned long length, int prot)
{
struct list_head *cb_node;
int rc;
@@ -565,13 +643,13 @@ __stp_call_vm_callbacks(struct stap_task_finder_target *tgt,
cb_tgt = list_entry(cb_node, struct stap_task_finder_target,
callback_list);
- if (cb_tgt == NULL || cb_tgt->vm_callback == NULL)
+ if (cb_tgt == NULL || cb_tgt->mprotect_callback == NULL)
continue;
- rc = cb_tgt->vm_callback(cb_tgt, tsk, map_p, vm_path,
- vm_start, vm_end, vm_pgoff);
+ rc = cb_tgt->mprotect_callback(cb_tgt, tsk, addr, length,
+ prot);
if (rc != 0) {
- _stp_error("vm callback for %d failed: %d",
+ _stp_error("mprotect callback for %d failed: %d",
(int)tsk->pid, rc);
}
}
@@ -898,16 +976,16 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
__stp_call_callbacks(tgt, tsk, 1, (tsk->pid == tsk->tgid));
/* If this is just a thread other than the thread group leader,
- don't bother inform vm_callback clients about its memory map,
+ don't bother inform map callback clients about its memory map,
since they will simply duplicate each other. */
- if (tgt->vm_events == 1 && tsk->tgid == tsk->pid) {
+ if (tgt->mmap_events == 1 && tsk->tgid == tsk->pid) {
struct mm_struct *mm;
char *mmpath_buf;
char *mmpath;
struct vm_area_struct *vma;
int rc;
- /* Call the vm_callback for every vma associated with
+ /* Call the mmap_callback for every vma associated with
* a file. */
mm = get_task_mm(tsk);
if (! mm)
@@ -934,12 +1012,13 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
mmpath_buf, PATH_MAX);
#endif
if (mmpath) {
- __stp_call_vm_callbacks(tgt, tsk, 1,
- mmpath,
- vma->vm_start,
- vma->vm_end,
- (vma->vm_pgoff
- << PAGE_SHIFT));
+ __stp_call_mmap_callbacks(tgt, tsk,
+ mmpath,
+ vma->vm_start,
+ vma->vm_end - vma->vm_start,
+ (vma->vm_pgoff
+ << PAGE_SHIFT),
+ vma->vm_flags);
}
else {
_stp_dbug(__FUNCTION__, __LINE__,
@@ -974,112 +1053,6 @@ __stp_find_file_based_vma(struct mm_struct *mm, unsigned long addr)
#ifdef UTRACE_ORIG_VERSION
static u32
-__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
-#else
-static u32
-__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
- struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
-#endif
-{
- struct stap_task_finder_target *tgt = engine->data;
- unsigned long syscall_no;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
- unsigned long *arg0_addr, arg0;
- int rc;
-#if defined(__ia64__)
- struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
-#endif
-
- if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
- debug_task_finder_detach();
- return UTRACE_DETACH;
- }
-
- if (tgt == NULL || tgt->vm_events == 0)
- return UTRACE_RESUME;
-
- // See if syscall is one we're interested in.
- //
- // FIXME: do we need to handle mremap()?
- syscall_no = __stp_user_syscall_nr(regs);
- if (syscall_no != MMAP_SYSCALL_NO(tsk)
- && syscall_no != MMAP2_SYSCALL_NO(tsk)
- && syscall_no != MPROTECT_SYSCALL_NO(tsk)
- && syscall_no != MUNMAP_SYSCALL_NO(tsk))
- return UTRACE_RESUME;
-
- __stp_tf_handler_start();
-
- // We need the first syscall argument to see what address
- // we're operating on.
- arg0_addr = __stp_user_syscall_arg(tsk, regs, 0);
- if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) {
- _stp_error("couldn't read syscall arg 0 for pid %d: %d",
- tsk->pid, rc);
- }
- else if (arg0 != (unsigned long)NULL) {
- mm = get_task_mm(tsk);
- if (mm) {
- down_read(&mm->mmap_sem);
-
- // If we can find a matching vma associated
- // with a file, save off its details.
- vma = __stp_find_file_based_vma(mm, arg0);
- if (vma != NULL) {
- __stp_tf_add_vma(tsk, arg0, vma);
- }
-
- up_read(&mm->mmap_sem);
- mmput(mm);
- }
- }
- __stp_tf_handler_end();
- return UTRACE_RESUME;
-}
-
-static void
-__stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt,
- struct task_struct *tsk,
- struct vm_area_struct *vma)
-{
- char *mmpath_buf;
- char *mmpath;
- int rc;
-
- // Allocate space for a path
- mmpath_buf = _stp_kmalloc(PATH_MAX);
- if (mmpath_buf == NULL) {
- _stp_error("Unable to allocate space for path");
- return;
- }
-
- // Grab the path associated with this vma.
-#ifdef STAPCONF_DPATH_PATH
- mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX);
-#else
- mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
- mmpath_buf, PATH_MAX);
-#endif
- if (mmpath == NULL || IS_ERR(mmpath)) {
- rc = -PTR_ERR(mmpath);
- _stp_error("Unable to get path (error %d) for pid %d",
- rc, (int)tsk->pid);
- }
- else {
- __stp_call_vm_callbacks(tgt, tsk, 1, mmpath,
- vma->vm_start, vma->vm_end,
- (vma->vm_pgoff << PAGE_SHIFT));
- }
- _stp_kfree(mmpath_buf);
-}
-
-#ifdef UTRACE_ORIG_VERSION
-static u32
__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
struct task_struct *tsk,
struct pt_regs *regs)
@@ -1092,13 +1065,12 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
#endif
{
struct stap_task_finder_target *tgt = engine->data;
- unsigned long syscall_no;
- unsigned long *rv_addr, rv;
- unsigned long *arg0_addr, arg0;
+ long syscall_no;
+ unsigned long rv;
+ unsigned long args[3];
int rc;
struct mm_struct *mm;
struct vm_area_struct *vma;
- struct __stp_tf_vma_entry *entry = NULL;
#if defined(__ia64__)
struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
#endif
@@ -1108,35 +1080,35 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
return UTRACE_DETACH;
}
- if (tgt == NULL || tgt->vm_events == 0)
+ if (tgt == NULL)
return UTRACE_RESUME;
// See if syscall is one we're interested in.
//
// FIXME: do we need to handle mremap()?
- syscall_no = __stp_user_syscall_nr(regs);
+ syscall_no = syscall_get_nr(tsk, regs);
if (syscall_no != MMAP_SYSCALL_NO(tsk)
&& syscall_no != MMAP2_SYSCALL_NO(tsk)
&& syscall_no != MPROTECT_SYSCALL_NO(tsk)
&& syscall_no != MUNMAP_SYSCALL_NO(tsk))
return UTRACE_RESUME;
- // Get return value
- rv_addr = __stp_user_syscall_return_value(tsk, regs);
- if ((rc = __stp_get_user(rv, rv_addr)) != 0) {
- _stp_error("couldn't read syscall return value for pid %d: %d",
- tsk->pid, rc);
+ // The syscall is one we're interested in, but do we have a
+ // handler for it?
+ if (((syscall_no == MMAP_SYSCALL_NO(tsk)
+ || syscall_no == MMAP2_SYSCALL_NO(tsk)) && tgt->mmap_events == 0)
+ || (syscall_no == MPROTECT_SYSCALL_NO(tsk)
+ && tgt->mprotect_events == 0)
+ || (syscall_no == MUNMAP_SYSCALL_NO(tsk)
+ && tgt->munmap_events == 0))
return UTRACE_RESUME;
- }
+
+ // Get return value
+ rv = syscall_get_return_value(tsk, regs);
// We need the first syscall argument to see what address we
// were operating on.
- arg0_addr = __stp_user_syscall_arg(tsk, regs, 0);
- if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) {
- _stp_error("couldn't read syscall arg 0 for pid %d: %d",
- tsk->pid, rc);
- return UTRACE_RESUME;
- }
+ syscall_get_arguments(tsk, regs, 0, 1, args);
#ifdef DEBUG_TASK_FINDER_VMA
_stp_dbug(__FUNCTION__, __LINE__,
@@ -1147,109 +1119,45 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
: ((syscall_no == MPROTECT_SYSCALL_NO(tsk)) ? "mprotect"
: ((syscall_no == MUNMAP_SYSCALL_NO(tsk)) ? "munmap"
: "UNKNOWN")))),
- arg0, rv);
+ args[0], rv);
#endif
__stp_tf_handler_start();
- // Try to find the vma info we might have saved.
- if (arg0 != (unsigned long)NULL)
- entry = __stp_tf_get_vma_entry(tsk, arg0);
+ if (syscall_no == MUNMAP_SYSCALL_NO(tsk)) {
+ // We need the 2nd syscall argument for the length.
+ syscall_get_arguments(tsk, regs, 1, 1, &args[1]);
+ // Call the callbacks
+ __stp_call_munmap_callbacks(tgt, tsk, args[0], args[1]);
+ }
+ else if (syscall_no == MMAP_SYSCALL_NO(tsk)
+ || syscall_no == MMAP2_SYSCALL_NO(tsk)) {
- // If entry is NULL, this means we didn't find a file based
- // vma to store in the syscall_entry routine. This could mean
- // we just created a new vma.
- if (entry == NULL) {
mm = get_task_mm(tsk);
if (mm) {
down_read(&mm->mmap_sem);
vma = __stp_find_file_based_vma(mm, rv);
- if (vma != NULL) {
- __stp_call_vm_callbacks_with_vma(tgt, tsk, vma);
- }
- up_read(&mm->mmap_sem);
- mmput(mm);
- }
- }
- // If we found saved vma information, try to match it up with
- // what currently exists.
- else {
-#ifdef DEBUG_TASK_FINDER_VMA
- _stp_dbug(__FUNCTION__, __LINE__,
- "** found stored vma 0x%lx/0x%lx/0x%lx!\n",
- entry->vm_start, entry->vm_end, entry->vm_pgoff);
-#endif
- mm = get_task_mm(tsk);
- if (mm) {
- down_read(&mm->mmap_sem);
- vma = __stp_find_file_based_vma(mm, entry->vm_start);
-
- // We couldn't find the vma at all. The
- // original vma was deleted.
- if (vma == NULL) {
- // FIXME: We'll need to figure out to
- // retrieve the path of a deleted
- // vma.
-
- __stp_call_vm_callbacks(tgt, tsk, 0, NULL,
- entry->vm_start,
- entry->vm_end,
- (entry->vm_pgoff
- << PAGE_SHIFT));
- }
- // If nothing has changed, there is no
- // need to call the callback.
- else if (vma->vm_start == entry->vm_start
- && vma->vm_end == entry->vm_end
- && vma->vm_pgoff == entry->vm_pgoff) {
- // do nothing
+ // Call the callbacks
+ if (vma) {
+ __stp_call_mmap_callbacks_with_vma(tgt, tsk,
+ vma);
}
- // The original vma has been changed. It is
- // possible that calling mprotect (e.g.) split
- // up an existing vma into 2 or 3 new vma's
- // (assuming it protected a portion of the
- // original vma at the beginning, middle, or
- // end). Try to determine what happened.
- else {
- unsigned long tmp;
-
- // First report that the original vma
- // is gone.
- //
- // FIXME: We'll need to figure out to
- // retrieve the path of a deleted
- // vma.
- __stp_call_vm_callbacks(tgt, tsk, 0, NULL,
- entry->vm_start,
- entry->vm_end,
- (entry->vm_pgoff
- << PAGE_SHIFT));
-
- // Now find all the new vma's that
- // made up the original vma's address
- // space and call the callback on each
- // new vma.
- tmp = entry->vm_start;
- while (((vma = __stp_find_file_based_vma(mm,
- tmp))
- != NULL)
- && vma->vm_end <= entry->vm_end) {
- __stp_call_vm_callbacks_with_vma(tgt,
- tsk,
- vma);
- if (vma->vm_end >= entry->vm_end)
- break;
- tmp = vma->vm_end;
- }
- }
up_read(&mm->mmap_sem);
mmput(mm);
}
+ }
+ else {
+ // We need the 2nd syscall argument for the length and
+ // the 3rd argument for the protection.
+ syscall_get_arguments(tsk, regs, 1, 2, &args[1]);
- // Cleanup by deleting the saved vma info.
- __stp_tf_remove_vma_entry(entry);
+ // Call the callbacks
+ __stp_call_mprotect_callbacks(tgt, tsk, args[0], args[1],
+ args[2]);
}
+
+syscall_exit_done:
__stp_tf_handler_end();
return UTRACE_RESUME;
}
@@ -1274,8 +1182,6 @@ stap_start_task_finder(void)
return ENOMEM;
}
- __stp_tf_vma_initialize();
-
atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING);
rcu_read_lock();
@@ -1391,5 +1297,5 @@ stap_stop_task_finder(void)
debug_task_finder_report();
}
-
+#endif /* defined(CONFIG_UTRACE) */
#endif /* TASK_FINDER_C */
diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c
index 83b206e5..ed9c6f4f 100644
--- a/runtime/task_finder_vma.c
+++ b/runtime/task_finder_vma.c
@@ -1,13 +1,19 @@
#include <linux/list.h>
#include <linux/jhash.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
// When handling memcpy() syscall tracing to notice memory map
// changes, we need to cache memcpy() entry parameter values for
// processing at memcpy() exit.
-// __stp_tf_vma_mutex protects the hash table.
-static DEFINE_MUTEX(__stp_tf_vma_mutex);
+// __stp_tf_vma_lock protects the hash table.
+// Documentation/spinlocks.txt suggest we can be a bit more clever
+// if we guarantee that in interrupt context we only read, not write
+// the datastructures. We should never change the hash table or the
+// contents in interrupt context (which should only ever call
+// stap_find_vma_map_info for getting stored vma info). So we might
+// want to look into that if this seems a bottleneck.
+static DEFINE_RWLOCK(__stp_tf_vma_lock);
#define __STP_TF_HASH_BITS 4
#define __STP_TF_TABLE_SIZE (1 << __STP_TF_HASH_BITS)
@@ -26,8 +32,8 @@ struct __stp_tf_vma_entry {
unsigned long vm_pgoff;
// Is that enough? Should we store a dcookie for vm_file?
- // Module that this vma entry is mapped from, if any.
- struct _stp_module *module;
+ // User data (possibly stp_module)
+ void *user;
};
static struct __stp_tf_vma_entry
@@ -40,23 +46,24 @@ static struct hlist_head __stp_tf_vma_table[__STP_TF_TABLE_SIZE];
static struct hlist_head __stp_tf_vma_map[__STP_TF_TABLE_SIZE];
// __stp_tf_vma_initialize(): Initialize the free list. Grabs the
-// mutex.
+// spinlock.
static void
__stp_tf_vma_initialize(void)
{
int i;
struct hlist_head *head = &__stp_tf_vma_free_list[0];
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
for (i = 0; i < TASK_FINDER_VMA_ENTRY_ITEMS; i++) {
hlist_add_head(&__stp_tf_vma_free_list_items[i].hlist, head);
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
}
// __stp_tf_vma_get_free_entry(): Returns an entry from the free list
-// or NULL. The __stp_tf_vma_mutex must be locked before calling this
+// or NULL. The __stp_tf_vma_lock must be write locked before calling this
// function.
static struct __stp_tf_vma_entry *
__stp_tf_vma_get_free_entry(void)
@@ -77,7 +84,7 @@ __stp_tf_vma_get_free_entry(void)
// __stp_tf_vma_put_free_entry(): Puts an entry back on the free
-// list. The __stp_tf_vma_mutex must be locked before calling this
+// list. The __stp_tf_vma_lock must be write locked before calling this
// function.
static void
__stp_tf_vma_put_free_entry(struct __stp_tf_vma_entry *entry)
@@ -101,7 +108,7 @@ __stp_tf_vma_hash(struct task_struct *tsk, unsigned long addr)
// Get vma_entry if the vma is present in the vma hash table.
-// Returns NULL if not present.
+// Returns NULL if not present. Takes a read lock on __stp_tf_vma_lock.
static struct __stp_tf_vma_entry *
__stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr)
{
@@ -109,20 +116,22 @@ __stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr)
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ read_lock_irqsave(&__stp_tf_vma_lock, flags);
head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)];
hlist_for_each_entry(entry, node, head, hlist) {
if (tsk->pid == entry->pid
&& addr == entry->addr) {
- mutex_unlock(&__stp_tf_vma_mutex);
+ read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return entry;
}
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return NULL;
}
// Add the vma info to the vma hash table.
+// Takes a write lock on __stp_tf_vma_lock.
static int
__stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
struct vm_area_struct *vma)
@@ -131,7 +140,8 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)];
hlist_for_each_entry(entry, node, head, hlist) {
if (tsk->pid == entry->pid
@@ -141,7 +151,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
"vma (pid: %d, vm_start: 0x%lx) present?\n",
tsk->pid, vma->vm_start);
#endif
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -EBUSY; /* Already there */
}
}
@@ -149,7 +159,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
// Get an element from the free list.
entry = __stp_tf_vma_get_free_entry();
if (!entry) {
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -ENOMEM;
}
entry->pid = tsk->pid;
@@ -158,11 +168,12 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
entry->vm_end = vma->vm_end;
entry->vm_pgoff = vma->vm_pgoff;
hlist_add_head(&entry->hlist, head);
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return 0;
}
// Remove the vma entry from the vma hash table.
+// Takes a write lock on __stp_tf_vma_lock.
static int
__stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry)
{
@@ -171,10 +182,11 @@ __stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry)
int found = 0;
if (entry != NULL) {
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
hlist_del(&entry->hlist);
__stp_tf_vma_put_free_entry(entry);
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
}
return 0;
}
@@ -189,7 +201,7 @@ __stp_tf_vma_map_hash(struct task_struct *tsk)
}
// Get vma_entry if the vma is present in the vma map hash table.
-// Returns NULL if not present. The __stp_tf_vma_mutex must be locked
+// Returns NULL if not present. The __stp_tf_vma_lock must be read locked
// before calling this function.
static struct __stp_tf_vma_entry *
__stp_tf_get_vma_map_entry_internal(struct task_struct *tsk,
@@ -214,13 +226,16 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk,
static int
stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
unsigned long vm_end, unsigned long vm_pgoff,
- struct _stp_module *module)
+ void *user)
{
struct hlist_head *head;
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ // Take a write lock, since we are most likely going to write
+ // after reading.
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start);
if (entry != NULL) {
#if 0
@@ -228,14 +243,14 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
"vma (pid: %d, vm_start: 0x%lx) present?\n",
tsk->pid, entry->vm_start);
#endif
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -EBUSY; /* Already there */
}
// Get an element from the free list.
entry = __stp_tf_vma_get_free_entry();
if (!entry) {
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return -ENOMEM;
}
@@ -245,11 +260,11 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
entry->vm_start = vm_start;
entry->vm_end = vm_end;
entry->vm_pgoff = vm_pgoff;
- entry->module = module;
+ entry->user = user;
head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
hlist_add_head(&entry->hlist, head);
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return 0;
}
@@ -263,23 +278,26 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start,
struct hlist_node *node;
struct __stp_tf_vma_entry *entry;
- mutex_lock(&__stp_tf_vma_mutex);
+ // Take a write lock since we are most likely going to delete
+ // after reading.
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_vma_lock, flags);
entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start);
if (entry != NULL) {
hlist_del(&entry->hlist);
__stp_tf_vma_put_free_entry(entry);
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return 0;
}
// Finds vma info if the vma is present in the vma map hash table.
-// Returns ESRCH if not present. The __stp_tf_vma_mutex must *not* be
+// Returns ESRCH if not present. The __stp_tf_vma_lock must *not* be
// locked before calling this function.
static int
stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
unsigned long *vm_start, unsigned long *vm_end,
- unsigned long *vm_pgoff)
+ unsigned long *vm_pgoff, void **user)
{
struct hlist_head *head;
struct hlist_node *node;
@@ -287,7 +305,8 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
struct __stp_tf_vma_entry *found_entry = NULL;
int rc = ESRCH;
- mutex_lock(&__stp_tf_vma_mutex);
+ unsigned long flags;
+ read_lock_irqsave(&__stp_tf_vma_lock, flags);
head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
hlist_for_each_entry(entry, node, head, hlist) {
if (tsk->pid == entry->pid
@@ -304,31 +323,10 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr,
*vm_end = found_entry->vm_end;
if (vm_pgoff != NULL)
*vm_pgoff = found_entry->vm_pgoff;
+ if (user != NULL)
+ *user = found_entry->user;
rc = 0;
}
- mutex_unlock(&__stp_tf_vma_mutex);
+ read_unlock_irqrestore(&__stp_tf_vma_lock, flags);
return rc;
}
-
-// Get vma_entry of the address (vm_start/vm_end) if the vma is
-// present in the vma hash table containing.
-// Returns NULL if not present.
-static struct __stp_tf_vma_entry *
-__stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr)
-{
- struct hlist_head *head;
- struct hlist_node *node;
- struct __stp_tf_vma_entry *entry;
-
- mutex_lock(&__stp_tf_vma_mutex);
- head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)];
- hlist_for_each_entry(entry, node, head, hlist) {
- if (tsk->pid == entry->pid
- && addr >= entry->vm_start && addr < entry->vm_end) {
- mutex_unlock(&__stp_tf_vma_mutex);
- return entry;
- }
- }
- mutex_unlock(&__stp_tf_vma_mutex);
- return NULL;
-}
diff --git a/runtime/unwind.c b/runtime/unwind.c
index 9c704e28..f7b19def 100644
--- a/runtime/unwind.c
+++ b/runtime/unwind.c
@@ -581,7 +581,7 @@ static int unwind(struct unwind_frame_info *frame)
if (UNW_PC(frame) == 0)
return -EINVAL;
- m = _stp_mod_sec_lookup (pc, &s);
+ m = _stp_mod_sec_lookup (pc, current, &s);
if (unlikely(m == NULL)) {
dbug_unwind(1, "No module found for pc=%lx", pc);
return -EINVAL;
diff --git a/runtime/uprobes/.gitignore b/runtime/uprobes/.gitignore
new file mode 100644
index 00000000..c8172c41
--- /dev/null
+++ b/runtime/uprobes/.gitignore
@@ -0,0 +1,7 @@
+/*.o
+/*.cmd
+/.tmp_versions
+/Module.*
+/modules.order
+/uprobes.ko
+/uprobes.mod.c
diff --git a/staptree.h b/staptree.h
index 5125cd85..7e9506bb 100644
--- a/staptree.h
+++ b/staptree.h
@@ -231,6 +231,7 @@ struct target_symbol: public symbol
};
std::string base_name;
std::vector<std::pair<component_type, std::string> > components;
+ std::string probe_context_var;
semantic_error* saved_conversion_error;
target_symbol(): saved_conversion_error (0) {}
void print (std::ostream& o) const;
diff --git a/tapset/DEVGUIDE b/tapset/DEVGUIDE
index e6bc3fb8..693521a8 100644
--- a/tapset/DEVGUIDE
+++ b/tapset/DEVGUIDE
@@ -59,8 +59,8 @@ For example, process execs can occur in either the do_execve() or the
compat_do_execve() functions. The following alias inserts probes at the
beginning of those functions:
-probe process.exec = kernel.function("do_execve"),
- kernel.function("compat_do_execve") {
+probe kprocess.exec = kernel.function("do_execve"),
+ kernel.function("compat_do_execve") {
< probe body >
}
@@ -87,7 +87,7 @@ process is retrieved by calling task_pid() and passing it the task_struct
pointer. In this case, the auxiliary function is an embedded C function
that's defined in the task tapset (task.stp).
-probe process.create = kernel.function("copy_process").return {
+probe kprocess.create = kernel.function("copy_process").return {
task = $return
new_pid = task_pid(task)
}
diff --git a/tapset/ansi.stp b/tapset/ansi.stp
new file mode 100644
index 00000000..0152fb37
--- /dev/null
+++ b/tapset/ansi.stp
@@ -0,0 +1,70 @@
+# ANSI escape sequences tapset
+# Copyright (C) 2009 Red Hat, Inc., Eugene Teo <eteo@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# Based on some previous work done by Masami Hiramatsu for stapgames.
+# Reference: http://en.wikipedia.org/wiki/ANSI_escape_code
+#
+
+function ansi_clear_screen() {
+ print("\033[1;1H\033[J")
+}
+
+# Foreground colors | Background colors
+# Black 30 | Black 40
+# Blue 34 | Red 41
+# Green 32 | Green 42
+# Cyan 36 | Yellow 43
+# Red 31 | Blue 44
+# Purple 35 | Magenta 45
+# Brown 33 | Cyan 46
+# Light Gray 37 | White 47
+function ansi_set_color(fg:long) {
+ printf("\033[%dm", fg)
+}
+
+function ansi_set_color2(fg:long, bg:long) {
+ printf("\033[%d;%dm", bg, fg)
+}
+
+# All attributes off 0
+# Intensity: Bold 1
+# Underline: Single 4
+# Blink: Slow 5
+# Blink: Rapid 6
+# Image: Negative 7
+function ansi_set_color3(fg:long, bg:long, attr:long) {
+ attr_str = attr ? sprintf(";%dm", attr) : "m"
+ printf("\033[%d;%d%s", bg, fg, attr_str)
+}
+
+function ansi_reset_color() {
+ ansi_set_color3(0, 0, 0)
+}
+
+function ansi_new_line() {
+ printf("\12")
+}
+
+function ansi_cursor_move(x:long, y:long) {
+ printf("\033[%d;%dH", y, x)
+}
+
+function ansi_cursor_hide() {
+ print("\033[>5I")
+}
+
+function ansi_cursor_save() {
+ print("\033[s")
+}
+
+function ansi_cursor_restore() {
+ print("\033[u")
+}
+
+function ansi_cursor_show() {
+ print("\033[>5h")
+}
diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp
index a3aae408..783f1b7b 100644
--- a/tapset/context-symbols.stp
+++ b/tapset/context-symbols.stp
@@ -66,7 +66,7 @@ function probefunc:string () %{ /* pure */
#else
((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)PAGE_OFFSET)) {
#endif
- _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs));
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs), current, 0);
if (THIS->__retvalue[0] == '.') /* powerpc symbol has a dot*/
strlcpy(THIS->__retvalue,THIS->__retvalue + 1,MAXSTRINGLEN);
} else {
@@ -89,8 +89,59 @@ function probemod:string () %{ /* pure */
while (*ptr != '"' && --len && *ptr)
*dst++ = *ptr++;
*dst = 0;
- } else {
- /* XXX: need a PC- and symbol-table-based fallback. */
- THIS->__retvalue[0] = '\0';
- }
+ } else if (CONTEXT->regs) {
+ struct _stp_module *m;
+ m = _stp_mod_sec_lookup (REG_IP(CONTEXT->regs), current, NULL);
+ if (m && m->name)
+ strlcpy (THIS->__retvalue, m->name, MAXSTRINGLEN);
+ else
+ strlcpy (THIS->__retvalue, "<unknown>", MAXSTRINGLEN);
+ } else
+ strlcpy (THIS->__retvalue, "<unknown>", MAXSTRINGLEN);
+%}
+
+/**
+ * sfunction modname - Return the kernel module name loaded at the address.
+ * @addr: The address.
+ *
+ * Description: Returns the module name associated with the given
+ * address if known. If not known it will return the string "<unknown>".
+ * If the address was not in a kernel module, but in the kernel itself,
+ * then the string "kernel" will be returned.
+ */
+function modname:string (addr: long) %{ /* pure */
+ struct _stp_module *m;
+ m = _stp_mod_sec_lookup (THIS->addr, current, NULL);
+ if (m && m->name)
+ strlcpy (THIS->__retvalue, m->name, MAXSTRINGLEN);
+ else
+ strlcpy (THIS->__retvalue, "<unknown>", MAXSTRINGLEN);
+%}
+
+/**
+ * sfunction symname - Return the symbol associated with the given address.
+ * @addr: The address to translate.
+ *
+ * Description: Returns the (function) symbol name associated with the
+ * given address if known. If not known it will return the hex string
+ * representation of addr.
+ */
+function symname:string (addr: long) %{ /* pure */
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
+ NULL, 0);
+%}
+
+/**
+ * sfunction symdata - Return the symbol and module offset for the address.
+ * @addr: The address to translate.
+ *
+ * Description: Returns the (function) symbol name associated with the
+ * given address if known, plus the module name (between brackets) and
+ * the offset inside the module, plus the size of the symbol function.
+ * If any element is not known it will be ommitted and if the symbol name
+ * is unknown it will return the hex string for the given address.
+ */
+function symdata:string (addr: long) %{ /* pure */
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
+ NULL, 1);
%}
diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp
index 90d4e0f4..b3d19e29 100644
--- a/tapset/context-unwind.stp
+++ b/tapset/context-unwind.stp
@@ -56,7 +56,8 @@ function backtrace:string () %{ /* pure */
function caller:string() %{ /* pure */
if (CONTEXT->pi)
_stp_symbol_snprint( THIS->__retvalue, MAXSTRINGLEN,
- (unsigned long)_stp_ret_addr_r(CONTEXT->pi));
+ (unsigned long)_stp_ret_addr_r(CONTEXT->pi),
+ current, 0);
else
strlcpy(THIS->__retvalue,"unknown",MAXSTRINGLEN);
%}
diff --git a/tapset/context.stp b/tapset/context.stp
index 9f4be0e6..36d68c8d 100644
--- a/tapset/context.stp
+++ b/tapset/context.stp
@@ -11,6 +11,11 @@
//provide information such as a backtrace to where the event occured and the current register values for the
//processor.
// </tapsetdescription>
+
+%{
+#include <asm/processor.h>
+%}
+
/**
* sfunction print_regs - Print a register dump.
*/
@@ -227,3 +232,23 @@ function stack_unused:long () %{ /* pure */
THIS->__retvalue = (long)&a & (THREAD_SIZE-1);
%}
+/**
+ * sfunction uaddr - User space address of current running task.
+ *
+ * Description: Returns the address in userspace that the current
+ * task was at when the probe occured. When the current running task
+ * isn't a user space thread, or the address cannot be found, zero
+ * is returned.
+ */
+function uaddr:long () %{ /* pure */
+ int64_t addr = 0;
+ if (current->mm)
+ {
+ struct pt_regs *uregs;
+ uregs = task_pt_regs(current);
+ if (uregs)
+ addr = (int64_t) REG_IP(uregs);
+ }
+ THIS->__retvalue = addr;
+%}
+
diff --git a/tapset/errno.stp b/tapset/errno.stp
index eda9bff1..011ff7e2 100644
--- a/tapset/errno.stp
+++ b/tapset/errno.stp
@@ -345,12 +345,20 @@ static const int Maxerrno = sizeof(errlist)/sizeof(char *);
function errno_str:string (err:long) %{ /* pure */
long e = THIS->err;
- if (e < 0 && e > -Maxerrno && errlist[-e])
- strlcpy (THIS->__retvalue, errlist[-e], MAXSTRINGLEN);
- else if (e > 0 && e < Maxerrno && errlist[e])
+ e = (e > 0 ? e : -e);
+ if (e > 0 && e < Maxerrno && errlist[e])
strlcpy (THIS->__retvalue, errlist[e], MAXSTRINGLEN);
%}
+function errno_p:long (err:long) %{ /* pure */
+ long e = THIS->err;
+ e = (e > 0 ? e : -e);
+ if (e > 0 && e < Maxerrno && errlist[e])
+ THIS->__retvalue = e;
+ else
+ THIS->__retvalue = 0;
+%}
+
%{
static long _stp_returnval(struct pt_regs *regs) {
if (regs) {
diff --git a/tapset/i686/syscalls.stp b/tapset/i686/syscalls.stp
index 8e69f622..2a89c19d 100644
--- a/tapset/i686/syscalls.stp
+++ b/tapset/i686/syscalls.stp
@@ -119,7 +119,7 @@ probe syscall.set_zone_reclaim.return =
#
probe syscall.sigaltstack = kernel.function("sys_sigaltstack") {
name = "sigaltstack"
- ussp = %( kernel_vr < "2.6.25" %? $ebx %: $bx %)
+ ussp = %( kernel_vr < "2.6.25" %? $ebx %: %( kernel_vr < "2.6.29" %? $bx %: $regs->bx %) %)
argstr = sprintf("%p", ussp)
}
probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return {
diff --git a/tapset/ip.stp b/tapset/ip.stp
index 1e2e263c..299d88d2 100644
--- a/tapset/ip.stp
+++ b/tapset/ip.stp
@@ -7,6 +7,10 @@
//
// Based on previous work done by Arnaldo Carvalho de Melo <acme@redhat.com>
+%{
+#include <linux/skbuff.h>
+%}
+
/**
* sfunction ip_ntop - returns a string representation from an integer IP number
* @addr: the ip represented as an integer
@@ -30,3 +34,45 @@ function __ip_sock_daddr:long (sock:long)
{
return @cast(sock, "inet_sock")->daddr
}
+
+/* Get the IP header for recent (> 2.6.21) kernels */
+function __get_skb_iphdr_new:long(skb:long)
+%{ /* pure */
+ struct sk_buff *skb;
+ skb = (struct sk_buff *)(long)THIS->skb;
+ /* as done by skb_network_header() */
+ #ifdef NET_SKBUFF_DATA_USES_OFFSET
+ THIS->__retvalue = (long)(kread(&(skb->head)) + kread(&(skb->network_header)));
+ #else
+ THIS->__retvalue = (long)kread(&(skb->network_header));
+ #endif
+ CATCH_DEREF_FAULT();
+%}
+
+/* Get the IP header from a sk_buff struct */
+function __get_skb_iphdr:long(skb:long){
+%( kernel_v < "2.6.21" %?
+ iphdr = @cast(skb, "sk_buff")->nh->raw
+ return iphdr
+%:
+ return __get_skb_iphdr_new(skb)
+%)
+}
+
+/* return the source next layer protocol for a given sk_buff structure */
+function __ip_skb_proto:long (iphdr)
+{
+ return @cast(iphdr, "iphdr")->protocol
+}
+
+/* return the source IP address for a given sk_buff structure */
+function __ip_skb_saddr:long (iphdr)
+{
+ return @cast(iphdr, "iphdr")->saddr
+}
+
+/* return the destination IP address for a given skb */
+function __ip_skb_daddr:long (iphdr)
+{
+ return @cast(iphdr, "iphdr")->daddr
+}
diff --git a/tapset/process.stp b/tapset/kprocess.stp
index e39f740a..316e03ce 100644
--- a/tapset/process.stp
+++ b/tapset/kprocess.stp
@@ -1,4 +1,4 @@
-// process tapset
+// kernel process tapset
// Copyright (C) 2006 Intel Corporation.
//
// This file is part of systemtap, and is free software. You can
@@ -15,7 +15,7 @@ function _IS_ERR:long(ptr:long) %{ /* pure */
/**
- * probe process.create - Fires whenever a new process is successfully created
+ * probe kprocess.create - Fires whenever a new process is successfully created
* @new_pid: The PID of the newly created process
*
* Context:
@@ -24,7 +24,7 @@ function _IS_ERR:long(ptr:long) %{ /* pure */
* Fires whenever a new process is successfully created, either as a result of
* <command>fork</command> (or one of its syscall variants), or a new kernel thread.
*/
-probe process.create = kernel.function("copy_process").return {
+probe kprocess.create = kernel.function("copy_process").return {
task = $return
if (_IS_ERR(task)) next
new_pid = task_pid(task)
@@ -32,7 +32,7 @@ probe process.create = kernel.function("copy_process").return {
/**
- * probe process.start - Starting new process
+ * probe kprocess.start - Starting new process
*
* Context:
* Newly created process.
@@ -40,11 +40,11 @@ probe process.create = kernel.function("copy_process").return {
* Fires immediately before a new process begins execution.
*
*/
-probe process.start = kernel.function("schedule_tail") { }
+probe kprocess.start = kernel.function("schedule_tail") { }
/**
- * probe process.exec - Attempt to exec to a new program
+ * probe kprocess.exec - Attempt to exec to a new program
* @filename: The path to the new executable
*
* Context:
@@ -52,7 +52,7 @@ probe process.start = kernel.function("schedule_tail") { }
*
* Fires whenever a process attempts to exec to a new program.
*/
-probe process.exec =
+probe kprocess.exec =
kernel.function("do_execve"),
kernel.function("compat_do_execve") ?
{
@@ -61,7 +61,7 @@ probe process.exec =
/**
- * probe process.exec_complete - Return from exec to a new program
+ * probe kprocess.exec_complete - Return from exec to a new program
* @errno: The error number resulting from the exec
* @success: A boolean indicating whether the exec was successful
*
@@ -71,7 +71,7 @@ probe process.exec =
*
* Fires at the completion of an exec call.
*/
-probe process.exec_complete =
+probe kprocess.exec_complete =
kernel.function("do_execve").return,
kernel.function("compat_do_execve").return ?
{
@@ -81,23 +81,23 @@ probe process.exec_complete =
/**
- * probe process.exit - Exit from process
+ * probe kprocess.exit - Exit from process
* @code: The exit code of the process
*
* Context:
* The process which is terminating.
*
* Fires when a process terminates. This will always be followed by a
- * process.release, though the latter may be delayed if the process waits in a
+ * kprocess.release, though the latter may be delayed if the process waits in a
* zombie state.
*/
-probe process.exit = kernel.function("do_exit") {
+probe kprocess.exit = kernel.function("do_exit") {
code = $code
}
/**
- * probe process.release - Process released
+ * probe kprocess.release - Process released
* @task: A task handle to the process being released
* @pid: PID of the process being released
*
@@ -106,10 +106,10 @@ probe process.exit = kernel.function("do_exit") {
* termination, else the context of the process itself.
*
* Fires when a process is released from the kernel. This always follows a
- * process.exit, though it may be delayed somewhat if the process waits in a
+ * kprocess.exit, though it may be delayed somewhat if the process waits in a
* zombie state.
*/
-probe process.release = kernel.function("release_task") {
+probe kprocess.release = kernel.function("release_task") {
task = $p
pid = $p->pid;
}
diff --git a/tapset/tcp.stp b/tapset/tcp.stp
index bb96b0cb..2c5dce7e 100644
--- a/tapset/tcp.stp
+++ b/tapset/tcp.stp
@@ -15,6 +15,7 @@
#include <net/sock.h>
#include <net/tcp.h>
#include <net/ip.h>
+#include <linux/skbuff.h>
%}
// Get retransmission timeout in usecs. RTO is initialized from default
@@ -78,6 +79,70 @@ function __tcp_sock_dport:long (sock:long){
return @cast(sock, "inet_sock")->dport
}
+/* returns the TCP header for recent (<2.6.21) kernel */
+function __get_skb_tcphdr_new:long(skb:long)
+%{ /* pure */
+ struct sk_buff *skb;
+ skb = (struct sk_buff *)(long)THIS->skb;
+ /* as done by skb_transport_header() */
+ #ifdef NET_SKBUFF_DATA_USES_OFFSET
+ THIS->__retvalue = (long)(kread(&(skb->head)) + kread(&(skb->transport_header)));
+ #else
+ THIS->__retvalue = (long)kread(&(skb->transport_header));
+ #endif
+ CATCH_DEREF_FAULT();
+%}
+
+/* returns the TCP header for a given sk_buff structure */
+function __get_skb_tcphdr:long(skb:long){
+%( kernel_v < "2.6.21" %?
+ tcphdr = @cast(skb, "sk_buff")->h->raw
+ return tcphdr
+%:
+ return __get_skb_tcphdr_new(skb)
+%)
+}
+
+/* returns TCP URG flag for a given sk_buff structure */
+function __tcp_skb_urg:long (tcphdr){
+ return @cast(tcphdr, "tcphdr")->urg
+}
+
+/* returns TCP ACK flag for a given sk_buff structure */
+function __tcp_skb_ack:long (tcphdr){
+ return @cast(tcphdr, "tcphdr")->ack
+}
+
+/* returns TCP PSH flag for a given sk_buff structure */
+function __tcp_skb_psh:long (tcphdr){
+ return @cast(tcphdr, "tcphdr")->psh
+}
+
+/* returns TCP RST flag for a given sk_buff structure */
+function __tcp_skb_rst:long (tcphdr){
+ return @cast(tcphdr, "tcphdr")->rst
+}
+
+/* returns TCP SYN flag for a given sk_buff structure */
+function __tcp_skb_syn:long (tcphdr){
+ return @cast(tcphdr, "tcphdr")->syn
+}
+
+/* returns TCP FIN flag for a given sk_buff structure */
+function __tcp_skb_fin:long (tcphdr){
+ return @cast(tcphdr, "tcphdr")->fin
+}
+
+/* returns TCP source port for a given sk_buff structure */
+function __tcp_skb_sport:long (tcphdr){
+ return ntohs(@cast(tcphdr, "tcphdr")->source)
+}
+
+/* returns TCP destination port for a given sk_buff structure */
+function __tcp_skb_dport:long (tcphdr){
+ return @cast(tcphdr, "tcphdr")->dest
+}
+
/* return the TCP source port for a given sock */
function __tcp_sock_sport:long (sock:long){
return @cast(sock, "inet_sock")->sport
@@ -300,3 +365,32 @@ probe tcp.setsockopt.return = kernel.function("tcp_setsockopt").return {
ret = $return
}
+/**
+ * probe tcp.receive - Called when a TCP packet is received
+ * @saddr: A string representing the source IP address
+ * @daddr: A string representing the destination IP address
+ * @sport: TCP source port
+ * @dport: TCP destination port
+ * @urg: TCP URG flag
+ * @ack: TCP ACK flag
+ * @psh: TCP PSH flag
+ * @rst: TCP RST flag
+ * @syn: TCP SYN flag
+ * @fin: TCP FIN flag
+ */
+probe tcp.receive = kernel.function("tcp_v4_rcv") {
+ iphdr = __get_skb_iphdr($skb)
+ saddr = ip_ntop(__ip_skb_saddr(iphdr))
+ daddr = ip_ntop(__ip_skb_daddr(iphdr))
+ protocol = __ip_skb_proto(iphdr)
+
+ tcphdr = __get_skb_tcphdr($skb)
+ dport = __tcp_skb_dport(tcphdr)
+ sport = __tcp_skb_sport(tcphdr)
+ urg = __tcp_skb_urg(tcphdr)
+ ack = __tcp_skb_ack(tcphdr)
+ psh = __tcp_skb_psh(tcphdr)
+ rst = __tcp_skb_rst(tcphdr)
+ syn = __tcp_skb_syn(tcphdr)
+ fin = __tcp_skb_fin(tcphdr)
+}
diff --git a/tapset/ucontext-symbols.stp b/tapset/ucontext-symbols.stp
new file mode 100644
index 00000000..3813a8bf
--- /dev/null
+++ b/tapset/ucontext-symbols.stp
@@ -0,0 +1,52 @@
+// User context symbols tapset
+// Copyright (C) 2009 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.
+
+// <tapsetdescription>
+// User context symbol functions provide additional information about
+// addresses from an application. These functions can provide
+// information about the user space map (library) that the event occured or
+// the function symbol of an address.
+// </tapsetdescription>
+
+%{
+#ifndef STP_NEED_SYMBOL_DATA
+#define STP_NEED_SYMBOL_DATA 1
+#endif
+#ifndef STP_NEED_VMA_TRACKER
+#define STP_NEED_VMA_TRACKER 1
+#endif
+%}
+
+/**
+ * sfunction usymname - Return the symbol of an address in the current task.
+ * @addr: The address to translate.
+ *
+ * Description: Returns the (function) symbol name associated with the
+ * given address if known. If not known it will return the hex string
+ * representation of addr.
+ */
+function usymname:string (addr: long) %{ /* pure */
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
+ current, 0);
+%}
+
+/**
+ * sfunction usymdata - Return the symbol and module offset of an address.
+ * @addr: The address to translate.
+ *
+ * Description: Returns the (function) symbol name associated with the
+ * given address in the current task if known, plus the module name
+ * (between brackets) and the offset inside the module (shared library),
+ * plus the size of the symbol function. If any element is not known it
+ * will be ommitted and if the symbol name is unknown it will return the
+ * hex string for the given address.
+ */
+function usymdata:string (addr: long) %{ /* pure */
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
+ current, 1);
+%}
diff --git a/tapset/utrace.stp b/tapset/utrace.stp
index 34cb32c5..00f427e6 100644
--- a/tapset/utrace.stp
+++ b/tapset/utrace.stp
@@ -6,13 +6,15 @@
%}
function _utrace_syscall_nr:long () %{
- THIS->__retvalue = __stp_user_syscall_nr(CONTEXT->regs); /* pure */
+ THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs); /* pure */
%}
function _utrace_syscall_arg:long (n:long) %{
- THIS->__retvalue = *__stp_user_syscall_arg(current, CONTEXT->regs, (int)THIS->n); /* pure */
+ unsigned long arg = 0; /* pure */
+ syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg);
+ THIS->__retvalue = arg;
%}
function _utrace_syscall_return:long () %{
- THIS->__retvalue = *__stp_user_syscall_return_value(current, CONTEXT->regs); /* pure */
+ THIS->__retvalue = syscall_get_return_value(current, CONTEXT->regs); /* pure */
%}
diff --git a/tapsets.cxx b/tapsets.cxx
index 50ee563a..c63151e1 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1339,7 +1339,12 @@ struct dwflpp
}
void
- iterate_over_cu_labels (string label_val, Dwarf_Die *cu, void *data,
+ iterate_over_cu_labels (string label_val,
+ string function,
+ Dwarf_Die *cu,
+ vector<derived_probe *> & results,
+ probe_point *base_loc,
+ void *data,
void (* callback)(const string &,
const char *,
int,
@@ -1364,14 +1369,30 @@ struct dwflpp
Dwarf_Attribute *attr = dwarf_attr (&die, DW_AT_name, &attr_mem);
int tag = dwarf_tag(&die);
const char *name = dwarf_formstring (attr);
- if (tag == DW_TAG_subprogram && name != 0)
+ if (name == 0)
+ continue;
+ switch (tag)
{
+ case DW_TAG_label:
+ break;
+ case DW_TAG_subprogram:
function_name = name;
+ default:
+ if (dwarf_haschildren (&die))
+ iterate_over_cu_labels (label_val, function, &die, results, base_loc, q, callback);
+ continue;
+ }
+
+ if (strcmp(function_name.c_str(), function.c_str()) == 0
+ || (name_has_wildcard(function)
+ && function_name_matches_pattern (function_name, function)))
+ {
}
- else if (tag == DW_TAG_label && name != 0
- && ((strncmp(name, sym, strlen(sym)) == 0)
- || (name_has_wildcard (sym)
- && function_name_matches_pattern (name, sym))))
+ else
+ continue;
+ if (strcmp(name, sym) == 0
+ || (name_has_wildcard(sym)
+ && function_name_matches_pattern (name, sym)))
{
const char *file = dwarf_decl_file (&die);
// Get the line number for this label
@@ -1403,19 +1424,18 @@ struct dwflpp
int nscopes = 0;
nscopes = dwarf_getscopes_die (&die, &scopes);
if (nscopes > 1)
- callback(function_name.c_str(), file,
- (int)dline, &scopes[1], stmt_addr, q);
- }
- if (dwarf_haschildren (&die) && tag != DW_TAG_structure_type
- && tag != DW_TAG_union_type)
- {
- iterate_over_cu_labels (label_val, &die, q, callback);
+ {
+ callback(function_name.c_str(), file,
+ (int)dline, &scopes[1], stmt_addr, q);
+ if (sess.listing_mode)
+ results.back()->locations[0]->components.push_back
+ (new probe_point::component(TOK_LABEL, new literal_string (name)));
+ }
}
}
while (dwarf_siblingof (&die, &die) == 0);
}
-
void collect_srcfiles_matching (string const & pattern,
set<char const *> & filtered_srcfiles)
{
@@ -1796,6 +1816,7 @@ struct dwflpp
find_variable_and_frame_base (Dwarf_Die *scope_die,
Dwarf_Addr pc,
string const & local,
+ const target_symbol *e,
Dwarf_Die *vardie,
Dwarf_Attribute *fb_attr_mem)
{
@@ -1823,7 +1844,8 @@ struct dwflpp
+ (dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + (dwarf_diename(cu) ?: "<unknown>")
+ ")"))
- + " while searching for local '" + local + "'");
+ + " while searching for local '" + local + "'",
+ e->tok);
}
int declaring_scope = dwarf_getscopevar (scopes, nscopes,
@@ -1841,7 +1863,8 @@ struct dwflpp
+ (dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + (dwarf_diename(cu) ?: "<unknown>")
+ ")"))
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
for (int inner = 0; inner < nscopes; ++inner)
@@ -1868,7 +1891,8 @@ struct dwflpp
translate_location(struct obstack *pool,
Dwarf_Attribute *attr, Dwarf_Addr pc,
Dwarf_Attribute *fb_attr,
- struct location **tail)
+ struct location **tail,
+ const target_symbol *e)
{
Dwarf_Op *expr;
size_t len;
@@ -1887,12 +1911,13 @@ struct dwflpp
/* Fall through. */
case 0: /* Shouldn't happen. */
- throw semantic_error ("not accessible at this address");
+ throw semantic_error ("not accessible at this address", e->tok);
default: /* Shouldn't happen. */
case -1:
throw semantic_error (string ("dwarf_getlocation_addr failed") +
- string (dwarf_errmsg (-1)));
+ string (dwarf_errmsg (-1)),
+ e->tok);
}
return c_translate_location (pool, &loc2c_error, this,
@@ -1976,13 +2001,12 @@ struct dwflpp
translate_components(struct obstack *pool,
struct location **tail,
Dwarf_Addr pc,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
Dwarf_Die *vardie,
Dwarf_Die *die_mem,
Dwarf_Attribute *attr_mem)
{
- Dwarf_Die *die = die_mem;
+ Dwarf_Die *die = NULL;
Dwarf_Die struct_die;
Dwarf_Attribute temp_attr;
@@ -1991,12 +2015,15 @@ struct dwflpp
if (vardie)
*die_mem = *vardie;
+ if (e->components.empty())
+ return die_mem;
+
static unsigned int func_call_level ;
static unsigned int dwarf_error_flag ; // indicates current error is dwarf error
static unsigned int dwarf_error_count ; // keeps track of no of dwarf errors
static semantic_error saved_dwarf_error("");
- while (i < components.size())
+ while (i < e->components.size())
{
/* XXX: This would be desirable, but we don't get the target_symbol token,
and printing that gives us the file:line number too early anyway. */
@@ -2007,6 +2034,7 @@ struct dwflpp
obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str());
#endif
+ die = die ? dwarf_formref_die (attr_mem, die_mem) : die_mem;
const int typetag = dwarf_tag (die);
switch (typetag)
{
@@ -2017,8 +2045,8 @@ struct dwflpp
break;
case DW_TAG_pointer_type:
- if (components[i].first == target_symbol::comp_literal_array_index)
- throw semantic_error ("cannot index pointer");
+ if (e->components[i].first == target_symbol::comp_literal_array_index)
+ throw semantic_error ("cannot index pointer", e->tok);
// XXX: of course, we should support this the same way C does,
// by explicit pointer arithmetic etc. PR4166.
@@ -2026,16 +2054,17 @@ struct dwflpp
break;
case DW_TAG_array_type:
- if (components[i].first == target_symbol::comp_literal_array_index)
+ if (e->components[i].first == target_symbol::comp_literal_array_index)
{
c_translate_array (pool, 1, 0 /* PR9768 */, die, tail,
- NULL, lex_cast<Dwarf_Word>(components[i].second));
+ NULL, lex_cast<Dwarf_Word>(e->components[i].second));
++i;
}
else
throw semantic_error("bad field '"
- + components[i].second
- + "' for array type");
+ + e->components[i].second
+ + "' for array type",
+ e->tok);
break;
case DW_TAG_structure_type:
@@ -2046,7 +2075,8 @@ struct dwflpp
Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die));
if (tmpdie == NULL)
throw semantic_error ("unresolved struct "
- + string (dwarf_diename_integrate (die) ?: "<anonymous>"));
+ + string (dwarf_diename_integrate (die) ?: "<anonymous>"),
+ e->tok);
*die_mem = *tmpdie;
}
switch (dwarf_child (die, die_mem))
@@ -2057,7 +2087,8 @@ struct dwflpp
default: /* Shouldn't happen */
throw semantic_error (string (typetag == DW_TAG_union_type ? "union" : "struct")
+ string (dwarf_diename_integrate (die) ?: "<anonymous>")
- + string (dwarf_errmsg (-1)));
+ + string (dwarf_errmsg (-1)),
+ e->tok);
break;
case 0:
@@ -2066,7 +2097,7 @@ struct dwflpp
while (dwarf_tag (die) != DW_TAG_member
|| ({ const char *member = dwarf_diename_integrate (die);
- member == NULL || string(member) != components[i].second; }))
+ member == NULL || string(member) != e->components[i].second; }))
{
if ( dwarf_diename (die) == NULL ) // handling Anonymous structs/unions
{
@@ -2079,19 +2110,19 @@ struct dwflpp
{
dwarf_error_flag ++ ;
dwarf_error_count ++;
- throw semantic_error(" Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:"<anonymous>"));
+ throw semantic_error(" Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:"<anonymous>"), e->tok);
}
if ( !dwarf_formref_die (&temp_attr, &temp_die))
{
dwarf_error_flag ++ ;
dwarf_error_count ++;
- throw semantic_error(" Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:"<anonymous>"));
+ throw semantic_error(" Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:"<anonymous>"), e->tok);
}
func_call_level ++ ;
- Dwarf_Die *result_die = translate_components(pool, tail, pc, components, &temp_die, &temp_die_2, &temp_attr );
+ Dwarf_Die *result_die = translate_components(pool, tail, pc, e, &temp_die, &temp_die_2, &temp_attr);
func_call_level -- ;
@@ -2129,35 +2160,38 @@ struct dwflpp
but just use the containing union's location. */
if (typetag != DW_TAG_union_type)
throw semantic_error ("no location for field '"
- + components[i].second
- + "' :" + string(dwarf_errmsg (-1)));
+ + e->components[i].second
+ + "' :" + string(dwarf_errmsg (-1)),
+ e->tok);
}
else
- translate_location (pool, attr_mem, pc, NULL, tail);
+ translate_location (pool, attr_mem, pc, NULL, tail, e);
++i;
break;
case DW_TAG_base_type:
throw semantic_error ("field '"
- + components[i].second
+ + e->components[i].second
+ "' vs. base type "
- + string(dwarf_diename_integrate (die) ?: "<anonymous type>"));
+ + string(dwarf_diename_integrate (die) ?: "<anonymous type>"),
+ e->tok);
break;
case -1:
- throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)));
+ throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)),
+ e->tok);
break;
default:
throw semantic_error (string(dwarf_diename_integrate (die) ?: "<anonymous type>")
+ ": unexpected type tag "
- + lex_cast<string>(dwarf_tag (die)));
+ + lex_cast<string>(dwarf_tag (die)),
+ e->tok);
break;
}
/* Now iterate on the type in DIE's attribute. */
if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL)
- throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)));
- die = dwarf_formref_die (attr_mem, die_mem);
+ throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), e->tok);
}
return die;
}
@@ -2165,23 +2199,23 @@ struct dwflpp
Dwarf_Die *
resolve_unqualified_inner_typedie (Dwarf_Die *typedie_mem,
- Dwarf_Attribute *attr_mem)
+ Dwarf_Attribute *attr_mem,
+ const target_symbol *e)
{
- ;
Dwarf_Die *typedie;
int typetag = 0;
while (1)
{
typedie = dwarf_formref_die (attr_mem, typedie_mem);
if (typedie == NULL)
- throw semantic_error ("cannot get type: " + string(dwarf_errmsg (-1)));
+ throw semantic_error ("cannot get type: " + string(dwarf_errmsg (-1)), e->tok);
typetag = dwarf_tag (typedie);
if (typetag != DW_TAG_typedef &&
typetag != DW_TAG_const_type &&
typetag != DW_TAG_volatile_type)
break;
if (dwarf_attr_integrate (typedie, DW_AT_type, attr_mem) == NULL)
- throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)));
+ throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)), e->tok);
}
return typedie;
}
@@ -2194,6 +2228,7 @@ struct dwflpp
Dwarf_Die *die,
Dwarf_Attribute *attr_mem,
bool lvalue,
+ const target_symbol *e,
string &,
string &,
exp_type & ty)
@@ -2207,7 +2242,7 @@ struct dwflpp
char const *dname;
string diestr;
- typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem);
+ typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem, e);
typetag = dwarf_tag (typedie);
/* Then switch behavior depending on the type of fetch/store we
@@ -2220,7 +2255,7 @@ struct dwflpp
diestr = (dname != NULL) ? dname : "<unknown>";
throw semantic_error ("unsupported type tag "
+ lex_cast<string>(typetag)
- + " for " + diestr);
+ + " for " + diestr, e->tok);
break;
case DW_TAG_structure_type:
@@ -2228,7 +2263,7 @@ struct dwflpp
dname = dwarf_diename(die);
diestr = (dname != NULL) ? dname : "<unknown>";
throw semantic_error ("struct/union '" + diestr
- + "' is being accessed instead of a member of the struct/union");
+ + "' is being accessed instead of a member of the struct/union", e->tok);
break;
case DW_TAG_enumeration_type:
@@ -2247,7 +2282,7 @@ struct dwflpp
{
// clog << "bad type1 " << encoding << " diestr" << endl;
throw semantic_error ("unsupported type (mystery encoding " + lex_cast<string>(encoding) + ")" +
- " for " + diestr);
+ " for " + diestr, e->tok);
}
if (encoding == DW_ATE_float
@@ -2256,7 +2291,7 @@ struct dwflpp
{
// clog << "bad type " << encoding << " diestr" << endl;
throw semantic_error ("unsupported type (encoding " + lex_cast<string>(encoding) + ")" +
- " for " + diestr);
+ " for " + diestr, e->tok);
}
}
@@ -2278,7 +2313,7 @@ struct dwflpp
Dwarf_Word pointee_encoding;
Dwarf_Word pointee_byte_size = 0;
- pointee_typedie = resolve_unqualified_inner_typedie (&pointee_typedie_mem, attr_mem);
+ pointee_typedie = resolve_unqualified_inner_typedie (&pointee_typedie_mem, attr_mem, e);
if (dwarf_attr_integrate (pointee_typedie, DW_AT_byte_size, attr_mem))
dwarf_formudata (attr_mem, &pointee_byte_size);
@@ -2290,7 +2325,7 @@ struct dwflpp
{
ty = pe_long;
if (typetag == DW_TAG_array_type)
- throw semantic_error ("cannot write to array address");
+ throw semantic_error ("cannot write to array address", e->tok);
assert (typetag == DW_TAG_pointer_type);
c_translate_pointer_store (pool, 1, 0 /* PR9768 */, typedie, tail,
"THIS->value");
@@ -2355,15 +2390,14 @@ struct dwflpp
literal_stmt_for_local (Dwarf_Die *scope_die,
Dwarf_Addr pc,
string const & local,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
bool lvalue,
exp_type & ty)
{
Dwarf_Die vardie;
Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
- fb_attr = find_variable_and_frame_base (scope_die, pc, local,
+ fb_attr = find_variable_and_frame_base (scope_die, pc, local, e,
&vardie, &fb_attr_mem);
if (sess.verbose>2)
@@ -2379,7 +2413,8 @@ struct dwflpp
"attribute for local '" + local
+ "' (dieoffset: "
+ lex_cast_hex<string>(dwarf_dieoffset (&vardie))
- + ")");
+ + ")",
+ e->tok);
}
#define obstack_chunk_alloc malloc
@@ -2392,27 +2427,29 @@ struct dwflpp
/* Given $foo->bar->baz[NN], translate the location of foo. */
struct location *head = translate_location (&pool,
- &attr_mem, pc, fb_attr, &tail);
+ &attr_mem, pc, fb_attr, &tail,
+ e);
if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL)
throw semantic_error("failed to retrieve type "
- "attribute for local '" + local + "'");
+ "attribute for local '" + local + "'",
+ e->tok);
/* Translate the ->bar->baz[NN] parts. */
- Dwarf_Die die_mem, *die = NULL;
- die = dwarf_formref_die (&attr_mem, &die_mem);
- die = translate_components (&pool, &tail, pc, components,
+ Dwarf_Die die_mem, *die = dwarf_formref_die (&attr_mem, &die_mem);
+ die = translate_components (&pool, &tail, pc, e,
die, &die_mem, &attr_mem);
if(!die)
{
- die = dwarf_formref_die (&attr_mem, &vardie);
+ die = dwarf_formref_die (&attr_mem, &die_mem);
stringstream alternatives;
if (die != NULL)
print_members(die,alternatives);
throw semantic_error("unable to find local '" + local + "'"
+ " near pc " + lex_cast_hex<string>(pc)
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
/* Translate the assignment part, either
@@ -2423,7 +2460,7 @@ struct dwflpp
string prelude, postlude;
translate_final_fetch_or_store (&pool, &tail, module_bias,
- die, &attr_mem, lvalue,
+ die, &attr_mem, lvalue, e,
prelude, postlude, ty);
/* Write the translation to a string. */
@@ -2434,8 +2471,7 @@ struct dwflpp
string
literal_stmt_for_return (Dwarf_Die *scope_die,
Dwarf_Addr pc,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
bool lvalue,
exp_type & ty)
{
@@ -2460,7 +2496,8 @@ struct dwflpp
" for "
+ string(dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + string(dwarf_diename(cu) ?: "<unknown>")
- + ")");
+ + ")",
+ e->tok);
}
// the function has no return value (e.g. "void" in C)
else if (nlocops == 0)
@@ -2468,7 +2505,8 @@ struct dwflpp
throw semantic_error("function "
+ string(dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + string(dwarf_diename(cu) ?: "<unknown>")
- + ") has no return value");
+ + ") has no return value",
+ e->tok);
}
struct location *head = c_translate_location (&pool, &loc2c_error, this,
@@ -2480,17 +2518,19 @@ struct dwflpp
/* Translate the ->bar->baz[NN] parts. */
Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr (scope_die, DW_AT_type, &attr_mem);
-
- Dwarf_Die vardie_mem;
- Dwarf_Die *vardie = dwarf_formref_die (attr, &vardie_mem);
-
- Dwarf_Die die_mem, *die = NULL;
- die = translate_components (&pool, &tail, pc, components,
- vardie, &die_mem, &attr_mem);
+ if (dwarf_attr_integrate (scope_die, DW_AT_type, &attr_mem) == NULL)
+ throw semantic_error("failed to retrieve return value type attribute for "
+ + string(dwarf_diename(scope_die) ?: "<unknown>")
+ + "(" + string(dwarf_diename(cu) ?: "<unknown>")
+ + ")",
+ e->tok);
+
+ Dwarf_Die die_mem, *die = dwarf_formref_die (&attr_mem, &die_mem);
+ die = translate_components (&pool, &tail, pc, e,
+ die, &die_mem, &attr_mem);
if(!die)
{
- die = dwarf_formref_die (&attr_mem, vardie);
+ die = dwarf_formref_die (&attr_mem, &die_mem);
stringstream alternatives;
if (die != NULL)
print_members(die,alternatives);
@@ -2500,7 +2540,8 @@ struct dwflpp
+ string(dwarf_diename(scope_die) ?: "<unknown>")
+ "(" + string(dwarf_diename(cu) ?: "<unknown>")
+ ")"
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
@@ -2512,7 +2553,7 @@ struct dwflpp
string prelude, postlude;
translate_final_fetch_or_store (&pool, &tail, module_bias,
- die, &attr_mem, lvalue,
+ die, &attr_mem, lvalue, e,
prelude, postlude, ty);
/* Write the translation to a string. */
@@ -2522,8 +2563,7 @@ struct dwflpp
string
literal_stmt_for_pointer (Dwarf_Die *type_die,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
+ const target_symbol *e,
bool lvalue,
exp_type & ty)
{
@@ -2545,7 +2585,7 @@ struct dwflpp
Dwarf_Attribute attr_mem;
Dwarf_Die die_mem, *die = NULL;
- die = translate_components (&pool, &tail, 0, components,
+ die = translate_components (&pool, &tail, 0, e,
type_die, &die_mem, &attr_mem);
if(!die)
{
@@ -2554,7 +2594,8 @@ struct dwflpp
print_members(die ?: type_die, alternatives);
throw semantic_error("unable to find member for struct "
+ string(dwarf_diename(die ?: type_die) ?: "<unknown>")
- + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")));
+ + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")),
+ e->tok);
}
@@ -2566,7 +2607,7 @@ struct dwflpp
string prelude, postlude;
translate_final_fetch_or_store (&pool, &tail, module_bias,
- die, &attr_mem, lvalue,
+ die, &attr_mem, lvalue, e,
prelude, postlude, ty);
/* Write the translation to a string. */
@@ -4093,7 +4134,7 @@ query_cu (Dwarf_Die * cudie, void * arg)
{
// If we have a pattern string with target *label*, we
// have to look at labels in all the matched srcfiles.
- q->dw.iterate_over_cu_labels (q->label_val, q->dw.cu, q, query_statement);
+ q->dw.iterate_over_cu_labels (q->label_val, q->function, q->dw.cu, q->results, q->base_loc, q, query_statement);
}
else
{
@@ -4865,7 +4906,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
{
ec->code = q.dw.literal_stmt_for_return (scope_die,
addr,
- e->components,
+ e,
lvalue,
fdecl->type);
}
@@ -4874,7 +4915,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
ec->code = q.dw.literal_stmt_for_local (scope_die,
addr,
e->base_name.substr(1),
- e->components,
+ e,
lvalue,
fdecl->type);
}
@@ -4906,8 +4947,9 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
literal_number* ln_zero = new literal_number (0);
ln_zero->tok = e->tok;
provide (ln_zero);
- q.sess.print_warning ("Bad variable being substituted with literal 0",
- e->tok);
+ if (!q.sess.suppress_warnings)
+ q.sess.print_warning ("Bad $context variable being substituted with literal 0",
+ e->tok);
}
delete fdecl;
delete ec;
@@ -5007,7 +5049,7 @@ dwarf_cast_query::handle_query_cu(Dwarf_Die * cudie)
{
try
{
- code = dw.literal_stmt_for_pointer (type_die, e.components,
+ code = dw.literal_stmt_for_pointer (type_die, &e,
lvalue, pe_type);
}
catch (const semantic_error& e)
@@ -5812,7 +5854,8 @@ dwarf_builder::build(systemtap_session & sess,
&& dw->function_name_matches_pattern
(probe_name.c_str(),
location->components[1]->arg->tok->content.c_str())))
- ;
+ {
+ }
else
continue;
const token* sv_tok = location->components[1]->arg->tok;
@@ -5833,7 +5876,7 @@ dwarf_builder::build(systemtap_session & sess,
return;
}
- if (probe_type == dwarf_no_probes)
+ else if (probe_type == dwarf_no_probes)
{
location->components[1]->functor = TOK_FUNCTION;
location->components[1]->arg = new literal_string("*");
@@ -6229,6 +6272,29 @@ module_info::~module_info()
delete sym_table;
}
+// Helper function to emit vma tracker callbacks.
+static void
+emit_vma_callback_probe_decl (systemtap_session& s,
+ string path,
+ int64_t pid)
+{
+ s.op->newline() << "{";
+ if (pid == 0)
+ {
+ s.op->line() << " .pathname=\"" << path << "\",";
+ s.op->line() << " .pid=0,";
+ }
+ else
+ {
+ s.op->line() << " .pathname=NULL,";
+ s.op->line() << " .pid=" << pid << ",";
+ }
+ s.op->line() << " .callback=NULL,";
+ s.op->line() << " .mmap_callback=&_stp_tf_mmap_cb,";
+ s.op->line() << " .munmap_callback=&_stp_tf_munmap_cb,";
+ s.op->line() << " .mprotect_callback=NULL,";
+ s.op->line() << " },";
+}
// ------------------------------------------------------------------------
@@ -6432,7 +6498,7 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline();
s.op->newline() << "/* ---- itrace probes ---- */";
- s.op->newline() << "#include \"task_finder.c\"";
+
s.op->newline() << "struct stap_itrace_probe {";
s.op->indent(1);
s.op->newline() << "struct stap_task_finder_target tgt;";
@@ -6474,6 +6540,25 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(-1) << "return rc;";
s.op->newline(-1) << "}";
+ // Emit vma callbacks.
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "static struct stap_task_finder_target stap_itrace_vmcbs[] = {";
+ s.op->indent(1);
+ if (! probes_by_path.empty())
+ {
+ for (p_b_path_iterator it = probes_by_path.begin();
+ it != probes_by_path.end(); it++)
+ emit_vma_callback_probe_decl (s, it->first, (int64_t)0);
+ }
+ if (! probes_by_pid.empty())
+ {
+ for (p_b_pid_iterator it = probes_by_pid.begin();
+ it != probes_by_pid.end(); it++)
+ emit_vma_callback_probe_decl (s, "", it->first);
+ }
+ s.op->newline(-1) << "};";
+ s.op->newline() << "#endif";
+
s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {";
s.op->indent(1);
@@ -6515,11 +6600,38 @@ itrace_derived_probe_group::emit_module_init (systemtap_session& s)
return;
s.op->newline();
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "_stp_sym_init();";
+ s.op->newline() << "/* ---- itrace vma callbacks ---- */";
+ s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_itrace_vmcbs); i++) {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_task_finder_target *r = &stap_itrace_vmcbs[i];";
+ s.op->newline() << "rc = stap_register_task_finder_target(r);";
+ s.op->newline(-1) << "}";
+ s.op->newline() << "#endif";
+
+ 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];";
+
+ // 'arch_has_single_step' needs to be defined for either single step mode
+ // or branch mode.
+ s.op->newline() << "if (!arch_has_single_step()) {";
+ s.op->indent(1);
+ s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");";
+ s.op->newline() << "rc = -EPERM;";
+ s.op->newline() << "break;";
+ s.op->newline(-1) << "}";
+ s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {";
+ s.op->indent(1);
+ s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");";
+ s.op->newline() << "rc = -EPERM;";
+ s.op->newline() << "break;";
+ s.op->newline(-1) << "}";
+
s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
s.op->newline(-1) << "}";
}
@@ -6580,9 +6692,6 @@ private:
bool flags_seen[UDPF_NFLAGS];
void emit_probe_decl (systemtap_session& s, utrace_derived_probe *p);
- void emit_vm_callback_probe_decl (systemtap_session& s, bool has_path,
- string path, int64_t pid,
- string vm_callback);
public:
utrace_derived_probe_group(): num_probes(0), flags_seen() { }
@@ -6907,7 +7016,9 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
}
s.op->line() << " .callback=&_stp_utrace_probe_cb,";
- s.op->line() << " .vm_callback=NULL,";
+ s.op->line() << " .mmap_callback=NULL,";
+ s.op->line() << " .munmap_callback=NULL,";
+ s.op->line() << " .mprotect_callback=NULL,";
s.op->line() << " },";
s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
s.op->line() << " .ph=&" << p->name << ",";
@@ -6964,40 +7075,6 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
void
-utrace_derived_probe_group::emit_vm_callback_probe_decl (systemtap_session& s,
- bool has_path,
- string path,
- int64_t pid,
- string vm_callback)
-{
- s.op->newline() << "{";
- s.op->line() << " .tgt={";
-
- if (has_path)
- {
- s.op->line() << " .pathname=\"" << path << "\",";
- s.op->line() << " .pid=0,";
- }
- else
- {
- s.op->line() << " .pathname=NULL,";
- s.op->line() << " .pid=" << pid << ",";
- }
-
- s.op->line() << " .callback=NULL,";
- s.op->line() << " .vm_callback=&" << vm_callback << ",";
- s.op->line() << " },";
- s.op->line() << " .pp=\"internal\",";
- s.op->line() << " .ph=NULL,";
- s.op->line() << " .flags=(UDPF_NONE),";
- s.op->line() << " .ops={ NULL },";
- s.op->line() << " .events=0,";
- s.op->line() << " .engine_attached=0,";
- s.op->line() << " },";
-}
-
-
-void
utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
{
if (probes_by_path.empty() && probes_by_pid.empty())
@@ -7005,7 +7082,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline();
s.op->newline() << "/* ---- utrace probes ---- */";
- s.op->newline() << "#include \"task_finder.c\"";
s.op->newline() << "enum utrace_derived_probe_flags {";
s.op->indent(1);
@@ -7213,6 +7289,25 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "return rc;";
s.op->newline(-1) << "}";
+ // Emit vma callbacks.
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "static struct stap_task_finder_target stap_utrace_vmcbs[] = {";
+ s.op->indent(1);
+ if (! probes_by_path.empty())
+ {
+ for (p_b_path_iterator it = probes_by_path.begin();
+ it != probes_by_path.end(); it++)
+ emit_vma_callback_probe_decl (s, it->first, (int64_t)0);
+ }
+ if (! probes_by_pid.empty())
+ {
+ for (p_b_pid_iterator it = probes_by_pid.begin();
+ it != probes_by_pid.end(); it++)
+ emit_vma_callback_probe_decl (s, "", it->first);
+ }
+ s.op->newline(-1) << "};";
+ s.op->newline() << "#endif";
+
s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {";
s.op->indent(1);
@@ -7222,12 +7317,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
for (p_b_path_iterator it = probes_by_path.begin();
it != probes_by_path.end(); it++)
{
- // Emit a "fake" probe decl that is really a hook for to get
- // our vm_callback called.
- string path = it->first;
- emit_vm_callback_probe_decl (s, true, path, (int64_t)0,
- "__stp_tf_vm_cb");
-
for (unsigned i = 0; i < it->second.size(); i++)
{
utrace_derived_probe *p = it->second[i];
@@ -7242,11 +7331,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
for (p_b_pid_iterator it = probes_by_pid.begin();
it != probes_by_pid.end(); it++)
{
- // Emit a "fake" probe decl that is really a hook for to get
- // our vm_callback called.
- emit_vm_callback_probe_decl (s, false, "", it->first,
- "__stp_tf_vm_cb");
-
for (unsigned i = 0; i < it->second.size(); i++)
{
utrace_derived_probe *p = it->second[i];
@@ -7265,6 +7349,16 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s)
return;
s.op->newline();
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "_stp_sym_init();";
+ s.op->newline() << "/* ---- utrace vma callbacks ---- */";
+ s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_vmcbs); i++) {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_task_finder_target *r = &stap_utrace_vmcbs[i];";
+ s.op->newline() << "rc = stap_register_task_finder_target(r);";
+ s.op->newline(-1) << "}";
+ s.op->newline() << "#endif";
+
s.op->newline() << "/* ---- utrace probes ---- */";
s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
s.op->indent(1);
@@ -7454,6 +7548,10 @@ uprobe_derived_probe::join_group (systemtap_session& s)
s.uprobe_derived_probes = new uprobe_derived_probe_group ();
s.uprobe_derived_probes->enroll (this);
task_finder_derived_probe_group::create_session_group (s);
+
+ // Ask buildrun.cxx to build extra module if needed, and
+ // signal staprun to load that module
+ s.need_uprobes = true;
}
@@ -7486,15 +7584,12 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
if (probes.empty()) return;
s.op->newline() << "/* ---- user probes ---- */";
- s.need_uprobes = true; // Ask buildrun.cxx to build extra module if needed
-
// If uprobes isn't in the kernel, pull it in from the runtime.
s.op->newline() << "#if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)";
s.op->newline() << "#include <linux/uprobes.h>";
s.op->newline() << "#else";
s.op->newline() << "#include \"uprobes/uprobes.h\"";
s.op->newline() << "#endif";
- s.op->newline() << "#include \"task_finder.c\"";
s.op->newline() << "#ifndef MULTIPLE_UPROBES";
s.op->newline() << "#define MULTIPLE_UPROBES 256"; // maximum possible armed uprobes per process() probe point
@@ -7512,6 +7607,21 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(-1) << "} stap_uprobes [MAXUPROBES];";
s.op->newline() << "DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration
+ // Emit vma callbacks.
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "static struct stap_task_finder_target stap_uprobe_vmcbs[] = {";
+ s.op->indent(1);
+ for (unsigned i = 0; i < probes.size(); i++)
+ {
+ uprobe_derived_probe* p = probes[i];
+ if (p->pid != 0)
+ emit_vma_callback_probe_decl (s, "", p->pid);
+ else
+ emit_vma_callback_probe_decl (s, p->module, (int64_t)0);
+ }
+ s.op->newline(-1) << "};";
+ s.op->newline() << "#endif";
+
s.op->newline() << "static struct stap_uprobe_spec {";
s.op->newline(1) << "struct stap_task_finder_target finder;";
s.op->newline() << "unsigned long address;";
@@ -7683,23 +7793,25 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(0) << "return stap_uprobe_change (tsk, register_p, 0, sups);";
s.op->newline(-1) << "}";
- // The task_finder_vm_callback we use for ET_DYN targets.
+ // The task_finder_mmap_callback we use for ET_DYN targets.
s.op->newline();
- s.op->newline() << "static int stap_uprobe_vmchange_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, unsigned long vm_start, unsigned long vm_end, unsigned long vm_pgoff) {";
+ s.op->newline() << "static int stap_uprobe_mmap_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, char *path, unsigned long addr, unsigned long length, unsigned long offset, unsigned long vm_flags) {";
s.op->newline(1) << "struct stap_uprobe_spec *sups = container_of(tgt, struct stap_uprobe_spec, finder);";
// 1 - shared libraries' executable segments load from offset 0 - ld.so convention
- s.op->newline() << "if (vm_pgoff != 0) return 0;";
+ s.op->newline() << "if (offset != 0) return 0;";
// 2 - the shared library we're interested in
- s.op->newline() << "if (vm_path == NULL || strcmp (vm_path, sups->pathname)) return 0;";
+ s.op->newline() << "if (path == NULL || strcmp (path, sups->pathname)) return 0;";
// 3 - probe address within the mapping limits; test should not fail
- s.op->newline() << "if (vm_end <= vm_start + sups->address) return 0;";
+ s.op->newline() << "if (sups->address >= addr && sups->address < (addr + length)) return 0;";
+ // 4 - mapping should be executable
+ s.op->newline() << "if (!(vm_flags & VM_EXEC)) return 0;";
s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA";
- s.op->newline() << "printk (KERN_INFO \"vmchange pid %d map_p %d path %s vms %p vme %p vmp %p\\n\", tsk->tgid, map_p, vm_path, (void*) vm_start, (void*) vm_end, (void*) vm_pgoff);";
+ s.op->newline() << "printk (KERN_INFO \"vmchange pid %d path %s addr %p length %lu offset %p\\n\", tsk->tgid, path, (void *) addr, length, (void*) offset);";
s.op->newline() << "printk (KERN_INFO \"sups %p pp %s path %s address %p\\n\", sups, sups->pp, sups->pathname ?: \"\", (void*) sups->address);";
s.op->newline() << "#endif";
- s.op->newline(0) << "return stap_uprobe_change (tsk, map_p, vm_start, sups);";
+ s.op->newline(0) << "return stap_uprobe_change (tsk, 1, addr, sups);";
s.op->newline(-1) << "}";
s.op->assert_0_indent();
@@ -7712,6 +7824,16 @@ void
uprobe_derived_probe_group::emit_module_init (systemtap_session& s)
{
if (probes.empty()) return;
+ s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER";
+ s.op->newline() << "_stp_sym_init();";
+ s.op->newline() << "/* ---- uprobe vma callbacks ---- */";
+ s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_uprobe_vmcbs); i++) {";
+ s.op->indent(1);
+ s.op->newline() << "struct stap_task_finder_target *r = &stap_uprobe_vmcbs[i];";
+ s.op->newline() << "rc = stap_register_task_finder_target(r);";
+ s.op->newline(-1) << "}";
+ s.op->newline() << "#endif";
+
s.op->newline() << "/* ---- user probes ---- */";
s.op->newline() << "for (j=0; j<MAXUPROBES; j++) {";
@@ -7727,7 +7849,7 @@ uprobe_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline(1) << "struct stap_uprobe_spec *sups = & stap_uprobe_specs[i];";
s.op->newline() << "probe_point = sups->pp;"; // for error messages
s.op->newline() << "if (sups->finder.pathname) sups->finder.callback = & stap_uprobe_process_found;";
- s.op->newline() << "else if (sups->pathname) sups->finder.vm_callback = & stap_uprobe_vmchange_found;";
+ s.op->newline() << "else if (sups->pathname) sups->finder.mmap_callback = & stap_uprobe_mmap_found;";
s.op->newline() << "rc = stap_register_task_finder_target (& sups->finder);";
// NB: if (rc), there is no need (XXX: nor any way) to clean up any
@@ -8583,6 +8705,7 @@ struct mark_derived_probe: public derived_probe
bool target_symbol_seen;
void join_group (systemtap_session& s);
+ void print_dupe_stamp (ostream& o);
void emit_probe_context_vars (translator_output* o);
void initialize_probe_context_vars (translator_output* o);
void printargs (std::ostream &o) const;
@@ -8686,36 +8809,9 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
// Remember that we've seen a target variable.
target_symbol_seen = true;
- // Synthesize a function.
- functiondecl *fdecl = new functiondecl;
- fdecl->tok = e->tok;
- embeddedcode *ec = new embeddedcode;
- ec->tok = e->tok;
-
- string fname = string("_mark_tvar_get")
- + "_" + e->base_name.substr(1)
- + "_" + lex_cast<string>(tick++);
-
- if (mark_args[argnum-1]->stp_type == pe_long)
- ec->code = string("THIS->__retvalue = CONTEXT->locals[0].")
- + probe_name + string(".__mark_arg")
- + lex_cast<string>(argnum) + string (";");
- else
- ec->code = string("strlcpy (THIS->__retvalue, CONTEXT->locals[0].")
- + probe_name + string(".__mark_arg")
- + lex_cast<string>(argnum) + string (", MAXSTRINGLEN);");
- ec->code += "/* pure */";
- fdecl->name = fname;
- fdecl->body = ec;
- fdecl->type = mark_args[argnum-1]->stp_type;
- sess.functions[fdecl->name]=fdecl;
-
- // Synthesize a functioncall.
- functioncall* n = new functioncall;
- n->tok = e->tok;
- n->function = fname;
- n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
- provide (n);
+ e->probe_context_var = "__mark_arg" + lex_cast<string>(argnum);
+ e->type = mark_args[argnum-1]->stp_type;
+ provide (e);
}
@@ -8966,6 +9062,15 @@ mark_derived_probe::join_group (systemtap_session& s)
void
+mark_derived_probe::print_dupe_stamp (ostream& o)
+{
+ if (target_symbol_seen)
+ for (unsigned i = 0; i < mark_args.size(); i++)
+ o << mark_args[i]->c_type << " __mark_arg" << (i+1) << endl;
+}
+
+
+void
mark_derived_probe::emit_probe_context_vars (translator_output* o)
{
// If we haven't seen a target symbol for this probe, quit.
@@ -9303,6 +9408,7 @@ struct tracepoint_derived_probe: public derived_probe
void build_args(dwflpp& dw, Dwarf_Die& func_die);
void printargs (std::ostream &o) const;
void join_group (systemtap_session& s);
+ void print_dupe_stamp(ostream& o);
void emit_probe_context_vars (translator_output* o);
};
@@ -9392,33 +9498,10 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
if (e->components.empty())
{
- // Synthesize a simple function to grab the parameter
- functiondecl *fdecl = new functiondecl;
- fdecl->tok = e->tok;
- embeddedcode *ec = new embeddedcode;
- ec->tok = e->tok;
-
- string fname = (string("_tracepoint_tvar_get")
- + "_" + e->base_name.substr(1)
- + "_" + lex_cast<string>(tick++));
-
- fdecl->name = fname;
- fdecl->body = ec;
- fdecl->type = pe_long;
-
- ec->code = (string("THIS->__retvalue = CONTEXT->locals[0].")
- + probe_name + string(".__tracepoint_arg_")
- + arg->name + string (";/* pure */"));
-
- dw.sess.functions[fdecl->name] = fdecl;
-
- // Synthesize a functioncall.
- functioncall* n = new functioncall;
- n->tok = e->tok;
- n->function = fname;
- n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
-
- provide (n);
+ // Just grab the value from the probe locals
+ e->probe_context_var = "__tracepoint_arg_" + arg->name;
+ e->type = pe_long;
+ provide (e);
}
else
{
@@ -9438,7 +9521,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
try
{
- ec->code = dw.literal_stmt_for_pointer (&arg->type_die, e->components,
+ ec->code = dw.literal_stmt_for_pointer (&arg->type_die, e,
lvalue, fdecl->type);
}
catch (const semantic_error& er)
@@ -9541,7 +9624,6 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
}
else if (e->base_name == "$$vars" || e->base_name == "$$parms")
{
- target_symbol *tsym = new target_symbol;
print_format* pf = new print_format;
// Convert $$vars to sprintf of a list of vars which we recursively evaluate
@@ -9565,6 +9647,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
if (i > 0)
pf->raw_components += " ";
pf->raw_components += args[i].name;
+ target_symbol *tsym = new target_symbol;
tsym->tok = e->tok;
tsym->base_name = "$" + args[i].name;
@@ -9795,6 +9878,15 @@ tracepoint_derived_probe::join_group (systemtap_session& s)
void
+tracepoint_derived_probe::print_dupe_stamp(ostream& o)
+{
+ for (unsigned i = 0; i < args.size(); i++)
+ if (args[i].used)
+ o << "__tracepoint_arg_" << args[i].name << endl;
+}
+
+
+void
tracepoint_derived_probe::emit_probe_context_vars (translator_output* o)
{
for (unsigned i = 0; i < args.size(); i++)
@@ -10134,11 +10226,16 @@ struct hrtimer_derived_probe: public derived_probe
int64_t interval, randomize;
- hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r):
+ hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r,
+ int64_t scale):
derived_probe (p, l), interval (i), randomize (r)
{
if ((i < min_ns_interval) || (i > max_ns_interval))
- throw semantic_error("interval value out of range");
+ throw semantic_error(string("interval value out of range (")
+ + lex_cast<string>(scale < min_ns_interval
+ ? min_ns_interval/scale : 1)
+ + ","
+ + lex_cast<string>(max_ns_interval/scale) + ")");
// randomize = 0 means no randomization
if ((r < 0) || (r > i))
@@ -10316,7 +10413,7 @@ timer_builder::build(systemtap_session & sess,
literal_map_t const & parameters,
vector<derived_probe *> & finished_results)
{
- int64_t period, rand=0;
+ int64_t scale=1, period, rand=0;
if (!get_param(parameters, "randomize", rand))
rand = 0;
@@ -10337,20 +10434,23 @@ timer_builder::build(systemtap_session & sess,
else if (get_param(parameters, "s", period)
|| get_param(parameters, "sec", period))
{
- period *= 1000000000;
- rand *= 1000000000;
+ scale = 1000000000;
+ period *= scale;
+ rand *= scale;
}
else if (get_param(parameters, "ms", period)
|| get_param(parameters, "msec", period))
{
- period *= 1000000;
- rand *= 1000000;
+ scale = 1000000;
+ period *= scale;
+ rand *= scale;
}
else if (get_param(parameters, "us", period)
|| get_param(parameters, "usec", period))
{
- period *= 1000;
- rand *= 1000;
+ scale = 1000;
+ period *= scale;
+ rand *= scale;
}
else if (get_param(parameters, "ns", period)
|| get_param(parameters, "nsec", period))
@@ -10373,7 +10473,7 @@ timer_builder::build(systemtap_session & sess,
}
else
finished_results.push_back(
- new hrtimer_derived_probe(base, location, period, rand));
+ new hrtimer_derived_probe(base, location, period, rand, scale));
}
void
diff --git a/testsuite/buildko/two.stp b/testsuite/buildko/two.stp
new file mode 100644
index 00000000..25350dc0
--- /dev/null
+++ b/testsuite/buildko/two.stp
@@ -0,0 +1,14 @@
+#! stap -p4
+
+# tests overwide arrays
+global a10
+global b10
+global c10
+global d10
+
+probe begin {
+ a10[0,"a",0,"a",0,"a",0,"a",0,"a"]="a";
+ b10["b",0,"b",0,"b",0,"b",0,"b",0]=0;
+ c10[0,"a",0,"a",0,"a",0,"a",0,"a"]<<<0;
+ d10["b",0,"b",0,"b",0,"b",0,"b",0]<<<0;
+}
diff --git a/testsuite/buildok/modname.stp b/testsuite/buildok/modname.stp
new file mode 100755
index 00000000..02229301
--- /dev/null
+++ b/testsuite/buildok/modname.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for modname()
+#
+probe begin
+{
+ log(modname(0))
+}
diff --git a/testsuite/buildok/process-all-probes.stp b/testsuite/buildok/process-all-probes.stp
index 91a96514..c754462b 100755
--- a/testsuite/buildok/process-all-probes.stp
+++ b/testsuite/buildok/process-all-probes.stp
@@ -2,11 +2,11 @@
// Tests if all probes in the process tapset are resolvable.
-probe process.create,
- process.start,
- process.exec,
- process.exec_complete,
- process.exit,
- process.release
+probe kprocess.create,
+ kprocess.start,
+ kprocess.exec,
+ kprocess.exec_complete,
+ kprocess.exit,
+ kprocess.release
{
}
diff --git a/testsuite/buildok/process_test.stp b/testsuite/buildok/process_test.stp
index 90de8b69..ba3fadf1 100755
--- a/testsuite/buildok/process_test.stp
+++ b/testsuite/buildok/process_test.stp
@@ -1,31 +1,31 @@
#! stap -p4
-probe process.create {
+probe kprocess.create {
log(pp())
log(sprint(task))
}
-probe process.start {
+probe kprocess.start {
log(pp())
}
-probe process.exec {
+probe kprocess.exec {
log(pp())
log(filename)
}
-probe process.exec_complete {
+probe kprocess.exec_complete {
log(pp())
log(sprint(errno))
log(sprint(success))
}
-probe process.exit {
+probe kprocess.exit {
log(pp())
log(sprint(code))
}
-probe process.release {
+probe kprocess.release {
log(pp())
log(sprint(task))
}
diff --git a/testsuite/buildok/symdata.stp b/testsuite/buildok/symdata.stp
new file mode 100755
index 00000000..d7e803a9
--- /dev/null
+++ b/testsuite/buildok/symdata.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for symdata()
+#
+probe begin
+{
+ log(symdata(0))
+}
diff --git a/testsuite/buildok/symname.stp b/testsuite/buildok/symname.stp
new file mode 100755
index 00000000..e082d1a5
--- /dev/null
+++ b/testsuite/buildok/symname.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for symname()
+#
+probe begin
+{
+ log(symname(0))
+}
diff --git a/testsuite/buildok/thirty.stp b/testsuite/buildok/thirty.stp
new file mode 100644
index 00000000..042bae56
--- /dev/null
+++ b/testsuite/buildok/thirty.stp
@@ -0,0 +1,49 @@
+#! stap -p4
+
+# tests wide arrays
+global a1, a2, a3, a4, a5, a6, a7, a8, a9
+global b1, b2, b3, b4, b5, b6, b7, b8, b9
+global c1, c2, c3, c4, c5, c6, c7, c8, c9
+global d1, d2, d3, d4, d5, d6, d7, d8, d9
+
+probe begin {
+ a1[0]="a";
+ a2[0,"a"]="a";
+ a3[0,"a",0]="a";
+ a4[0,"a",0,"a"]="a";
+ a5[0,"a",0,"a",0]="a";
+ a6[0,"a",0,"a",0,"a"]="a";
+ a7[0,"a",0,"a",0,"a",0]="a";
+ a8[0,"a",0,"a",0,"a",0,"a"]="a";
+ a9[0,"a",0,"a",0,"a",0,"a",0]="a";
+
+ b1["b"]=0;
+ b2["b",0]=0;
+ b3["b",0,"b"]=0;
+ b4["b",0,"b",0]=0;
+ b5["b",0,"b",0,"b"]=0;
+ b6["b",0,"b",0,"b",0]=0;
+ b7["b",0,"b",0,"b",0,"b"]=0;
+ b8["b",0,"b",0,"b",0,"b",0]=0;
+ b9["b",0,"b",0,"b",0,"b",0,"b"]=0;
+
+ c1[0]<<<0;
+ c2[0,"a"]<<<0;
+ c3[0,"a",0]<<<0;
+ c4[0,"a",0,"a"]<<<0;
+ c5[0,"a",0,"a",0]<<<0;
+ c6[0,"a",0,"a",0,"a"]<<<0;
+ c7[0,"a",0,"a",0,"a",0]<<<0;
+ c8[0,"a",0,"a",0,"a",0,"a"]<<<0;
+ c9[0,"a",0,"a",0,"a",0,"a",0]<<<0;
+
+ d1["b"]<<<0;
+ d2["b",0]<<<0;
+ d3["b",0,"b"]<<<0;
+ d4["b",0,"b",0]<<<0;
+ d5["b",0,"b",0,"b"]<<<0;
+ d6["b",0,"b",0,"b",0]<<<0;
+ d7["b",0,"b",0,"b",0,"b"]<<<0;
+ d8["b",0,"b",0,"b",0,"b",0]<<<0;
+ d9["b",0,"b",0,"b",0,"b",0,"b"]<<<0;
+}
diff --git a/testsuite/buildok/twentysix.stp b/testsuite/buildok/twentysix.stp
deleted file mode 100755
index 3fb7526f..00000000
--- a/testsuite/buildok/twentysix.stp
+++ /dev/null
@@ -1,7 +0,0 @@
-#! stap -up4
-
-global a
-probe begin
-{
- a [1,2,3,4,5,6] = 0
-}
diff --git a/testsuite/buildok/uaddr.stp b/testsuite/buildok/uaddr.stp
new file mode 100755
index 00000000..8acfc495
--- /dev/null
+++ b/testsuite/buildok/uaddr.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for uaddr()
+#
+probe begin
+{
+ printf("uaddr: 0x%x\n", uaddr())
+}
diff --git a/testsuite/buildok/usymdata.stp b/testsuite/buildok/usymdata.stp
new file mode 100755
index 00000000..48c1f36f
--- /dev/null
+++ b/testsuite/buildok/usymdata.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for usymdata()
+#
+probe begin
+{
+ log(usymdata(0))
+}
diff --git a/testsuite/buildok/usymname.stp b/testsuite/buildok/usymname.stp
new file mode 100755
index 00000000..57e3f9c2
--- /dev/null
+++ b/testsuite/buildok/usymname.stp
@@ -0,0 +1,8 @@
+#! stap -p4
+#
+# Test the translatability for usymname()
+#
+probe begin
+{
+ log(usymname(0))
+}
diff --git a/testsuite/lib/stap_run.exp b/testsuite/lib/stap_run.exp
index a4beaa12..3043eeed 100644
--- a/testsuite/lib/stap_run.exp
+++ b/testsuite/lib/stap_run.exp
@@ -30,6 +30,7 @@ proc stap_run { TEST_NAME {LOAD_GEN_FUNCTION ""} {OUTPUT_CHECK_STRING ""} args }
if [file readable $test_file_name] {
lappend cmd $test_file_name
}
+ send_log "executing: $cmd\n"
eval spawn $cmd
expect {
-timeout 180
diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp
index 554e88ed..98108fa5 100644
--- a/testsuite/lib/systemtap.exp
+++ b/testsuite/lib/systemtap.exp
@@ -16,6 +16,16 @@ proc use_server_p {} {
}
+proc utrace_p {} {
+ set path "/proc/kallsyms"
+ if {! [catch {exec grep -q utrace_attach $path} dummy]} {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+
proc print_systemtap_version {} {
set version [exec /bin/uname -r]
set location "/boot/vmlinux-$version"
@@ -75,7 +85,7 @@ proc setup_server {} {
# Make sure that the necessary resources are available to run the client/server.
if {[installtest_p]} then {
- if {[exec /usr/bin/which stap-client-connect] == ""} then {
+ if {[catch {exec /usr/bin/which stap-client-connect} dummy]} then {
print "Unable to start a server: stap-client-connect is not found in PATH"
return 0
}
@@ -83,7 +93,7 @@ proc setup_server {} {
print "Unable to start a server: [exec pwd]/../stap-client-connect is not found"
return 0
}
- if {[exec /usr/bin/which avahi-publish-service] == ""} then {
+ if {[catch {exec /usr/bin/which avahi-publish-service} dummy]} then {
print "Unable to start a server: avahi-publish-service is not found in PATH"
return 0
}
diff --git a/testsuite/semok/badvar.stp b/testsuite/semok/badvar.stp
index b3bd2d67..677187a3 100755
--- a/testsuite/semok/badvar.stp
+++ b/testsuite/semok/badvar.stp
@@ -1,7 +1,9 @@
-#! stap --skip-badvars
+#! /bin/sh
+stap -p2 --skip-badvars -e '
probe syscall.read {
if ($foo == 0)
printf ("Voila! It works..\n")
exit ()
}
+'
diff --git a/testsuite/systemtap.base/bitfield.exp b/testsuite/systemtap.base/bitfield.exp
new file mode 100644
index 00000000..16451369
--- /dev/null
+++ b/testsuite/systemtap.base/bitfield.exp
@@ -0,0 +1,3 @@
+# test that bitfield r/w works correctly
+set test "bitfield"
+stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g
diff --git a/testsuite/systemtap.base/bitfield.stp b/testsuite/systemtap.base/bitfield.stp
new file mode 100644
index 00000000..c2ff4929
--- /dev/null
+++ b/testsuite/systemtap.base/bitfield.stp
@@ -0,0 +1,46 @@
+%{
+#include <linux/tcp.h>
+static struct tcphdr foo = {0};
+%}
+
+function get_ptr:long() %{ THIS->__retvalue = (long)&foo; /* pure */ %}
+function get_ack:long() %{ THIS->__retvalue = foo.ack; /* pure */ %}
+function get_urg:long() %{ THIS->__retvalue = foo.urg; /* pure */ %}
+
+function check:long(ack:long, urg:long) {
+ ptr = get_ptr()
+
+ /* set the bits with cast */
+ @cast(ptr, "tcphdr")->ack = ack
+ @cast(ptr, "tcphdr")->urg = urg
+
+ /* check that reading with embedded-C is ok */
+ real_ack = get_ack()
+ real_urg = get_urg()
+ errors = (ack != real_ack) + (urg != real_urg)
+
+ /* check that reading with a cast is ok */
+ cast_ack = @cast(ptr, "tcphdr")->ack
+ cast_urg = @cast(ptr, "tcphdr")->urg
+ errors += (ack != cast_ack) + (urg != cast_urg)
+
+ if (errors)
+ printf("bitfield had %d errors; expect(%d%d), real(%d%d), cast(%d%d)\n",
+ errors, ack, urg, real_ack, real_urg, cast_ack, cast_urg)
+
+ return errors
+}
+
+probe begin {
+ println("systemtap starting probe")
+
+ errors = check(0, 0)
+ errors += check(0, 1)
+ errors += check(1, 0)
+ errors += check(1, 1)
+
+ println("systemtap ending probe")
+ if (errors == 0)
+ println("systemtap test success")
+ exit()
+}
diff --git a/testsuite/systemtap.base/bz5274.exp b/testsuite/systemtap.base/bz5274.exp
index 92441e9e..2f76a43f 100755
--- a/testsuite/systemtap.base/bz5274.exp
+++ b/testsuite/systemtap.base/bz5274.exp
@@ -17,14 +17,7 @@ if {! [installtest_p]} {
return
}
-# Try to find utrace_attach symbol in /proc/kallsyms
-# copy from utrace_p5.exp
-set utrace_support_found 0
-set path "/proc/kallsyms"
-if {! [catch {exec grep -q utrace_attach $path} dummy]} {
- set utrace_support_found 1
-}
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
catch {exec rm -f $test}
untested "$test -p5"
return
diff --git a/testsuite/systemtap.base/bz6850.exp b/testsuite/systemtap.base/bz6850.exp
index b96ed95c..32ecdaf5 100644
--- a/testsuite/systemtap.base/bz6850.exp
+++ b/testsuite/systemtap.base/bz6850.exp
@@ -3,14 +3,7 @@ set test bz6850
catch {exec gcc -g -o bz6850 $srcdir/$subdir/bz6850.c} err
if {$err == "" && [file exists bz6850]} then { pass "$test compile" } else { fail "$test compile" }
-# Try to find utrace_attach symbol in /proc/kallsyms
-# copy from utrace_p5.exp
-set utrace_support_found 0
-set path "/proc/kallsyms"
-if {! [catch {exec grep -q utrace_attach $path} dummy]} {
- set utrace_support_found 1
-}
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
catch {exec rm -f $test}
untested "$test -p4"
untested "$test -p5"
diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp
index e215bfe7..5da0dfaf 100644
--- a/testsuite/systemtap.base/itrace.exp
+++ b/testsuite/systemtap.base/itrace.exp
@@ -2,7 +2,6 @@
# Initialize variables
-set utrace_support_found 0
set exepath "[pwd]/ls_[pid]"
set itrace1_script {
@@ -48,6 +47,26 @@ set itrace2_script {
}
set itrace2_script_output "itraced = 5\r\n"
+set itrace3_script {
+ global branches = 0
+ probe begin
+ {
+ printf("systemtap starting probe\n")
+ }
+ probe process("%s").insn.block
+ {
+ branches += 1
+ if (branches == 5)
+ exit()
+ }
+
+
+ probe end { printf("systemtap ending probe\n")
+ printf("itraced block mode = %%d\n", branches)
+ }
+}
+set itrace3_script_output "itraced block mode = 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
@@ -72,14 +91,8 @@ proc run_ls_5_sec {} {
}
-# 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} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested $TEST_NAME
@@ -90,7 +103,7 @@ if {$utrace_support_found == 0} {
set TEST_NAME "itrace2"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested $TEST_NAME
@@ -99,5 +112,16 @@ if {$utrace_support_found == 0} {
stap_run $TEST_NAME run_ls_5_sec $itrace2_script_output -e $script
}
+set TEST_NAME "itrace3"
+if {![utrace_p]} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} elseif {![installtest_p]} {
+ untested $TEST_NAME
+} else {
+ send_log "ATTENTION: if arch_has_block_step is not defined for this arch, this testcase will fail\n"
+ set script [format $itrace3_script $exepath]
+ stap_run $TEST_NAME run_ls_5_sec $itrace3_script_output -e $script
+}
+
# Cleanup
exec rm -f $exepath
diff --git a/testsuite/systemtap.base/labels.exp b/testsuite/systemtap.base/labels.exp
index 6db81c54..88ed4619 100644
--- a/testsuite/systemtap.base/labels.exp
+++ b/testsuite/systemtap.base/labels.exp
@@ -1,14 +1,6 @@
set test "labels"
if {![installtest_p]} {untested $test; return}
-
-# Try to find utrace_attach symbol in /proc/kallsyms
-# copy from utrace_p5.exp
-set utrace_support_found 0
-set path "/proc/kallsyms"
-if {! [catch {exec grep -q utrace_attach $path} dummy]} {
- set utrace_support_found 1
-}
-if {$utrace_support_found == 0} { untested "$test"; return }
+if {![utrace_p]} { untested $test; return }
# Compile a C program to use as the user-space probing target
set label_srcpath "[pwd]/labels.c"
@@ -18,15 +10,22 @@ set label_flags "additional_flags=-g"
set fp [open $label_srcpath "w"]
puts $fp "
int
+foo ()
+{
+init_an_int:
+ return 1;
+}
+int
main ()
{
sleep(5);
+ foo();
int a = 0;
int b = 0;
char *c;
init_an_int:
a = 2;
-init_another_int:
+init_an_int_again:
b = 3;
c = \"abc\";
ptr_inited:
@@ -38,8 +37,9 @@ close $fp
set label_stppath "[pwd]/labels.stp"
set fp [open $label_stppath "w"]
puts $fp "
-probe process(\"labels.x\").function(\"main*@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)}
-probe process(\"labels.x\").function(\"main*@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)}
+probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)}
+probe process(\"labels.x\").function(\"main@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)}
+probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_an_int\") {printf (\"init_an_int\\n\")}
"
close $fp
@@ -55,20 +55,35 @@ if { $res != "" } {
pass "compiling labels.c -g"
}
+# list of labels
+
+spawn stap -l "process(\"$label_exepath\").function(\"*\").label(\"*\")"
+
+wait
+expect {
+ -timeout 180
+ -re {process.*function.*labels.c:5...label..init_an_int.*process.*function.*labels.c:16...label..init_an_int.*process.*function.*labels.c:18...label..init_an_int_again} { incr ok; exp_continue }
+ timeout { fail "$test (timeout)" }
+ eof { }
+}
+
+if {$ok == 1} { pass "$test -l .label" } { fail "$test -l .label $ok" }
+
# label in an executable
+set ok 0
verbose -log "spawn stap -c $label_exepath $label_stppath"
spawn stap -c $label_exepath $label_stppath
wait
expect {
-timeout 180
- -re {VARS a=0x0 b=0x0.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue }
+ -re {VARS a=0x0 b=0x0.*init_an_int.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue }
timeout { fail "$test (timeout)" }
eof { }
}
-if {$ok == 1} { pass "$test exe .label" } { fail "$test exe .label" }
+if {$ok == 1} { pass "$test exe .label" } { fail "$test exe .label $ok" }
# address of label in an executable
@@ -76,7 +91,7 @@ set label_shpath "[pwd]/label.sh"
set fp [open $label_shpath "w"]
puts $fp "
readelf --debug-dump $label_exepath | awk \"
-/init_another_int/ {have_label=1}
+/init_an_int_again/ {have_label=1}
/DW_AT_low_pc/ {if (have_label) {print \$3;exit;}}
\"
"
@@ -111,7 +126,7 @@ if { $res != "" } {
# label in a shared object
-spawn stap -p2 -l "process\(\"$label_sopath\"\).function\(\"\*\"\).label\(\"init_another_int\"\)"
+spawn stap -p2 -l "process\(\"$label_sopath\"\).function\(\"\*\"\).label\(\"init_an_int_again\"\)"
expect {
-timeout 180
-re {process.*function} { incr ok; exp_continue }
@@ -119,7 +134,7 @@ expect {
eof { }
}
-if {$ok == 1} { pass "$test so .label" } { fail "$test so .label" }
+if {$ok == 1} { pass "$test so .label" } { fail "$test so .label $ok" }
# address of label in a shared object
@@ -127,7 +142,7 @@ set label_shpath "[pwd]/label.sh"
set fp [open $label_shpath "w"]
puts $fp "
readelf --debug-dump $label_sopath | awk \"
-/init_another_int/ {have_label=1}
+/init_an_int_again/ {have_label=1}
/DW_AT_low_pc/ {if (have_label) {print \$3;exit;}}
\"
"
diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp
index 46fa5a28..c3aed91e 100644
--- a/testsuite/systemtap.base/sdt.exp
+++ b/testsuite/systemtap.base/sdt.exp
@@ -36,7 +36,7 @@ if { $res != "" } {
pass "compiling $test.c $extra_flag"
}
-if {[installtest_p]} {
+if {[installtest_p] && [utrace_p]} {
stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog
} else {
untested "$test $extra_flag"
@@ -61,7 +61,7 @@ if { $res != "" } {
pass "compiling $test.c c++ $extra_flag"
}
-if {[installtest_p]} {
+if {[installtest_p] && [utrace_p]} {
stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog
} else {
untested "$test c++ $extra_flag"
diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp
index 820626b8..07ff83e9 100644
--- a/testsuite/systemtap.base/static_uprobes.exp
+++ b/testsuite/systemtap.base/static_uprobes.exp
@@ -124,15 +124,7 @@ if { $res != "" } {
}
if {![installtest_p]} {untested $test; return}
-
-# Try to find utrace_attach symbol in /proc/kallsyms
-# copy from utrace_p5.exp
-set utrace_support_found 0
-set path "/proc/kallsyms"
-if {! [catch {exec grep -q utrace_attach $path} dummy]} {
- set utrace_support_found 1
-}
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$test"
catch {exec rm -f $sup_srcpath}
return
@@ -196,7 +188,7 @@ set ok 0
spawn stap -l "process(\"./sdt_types.x\").mark(\"*\")"
expect {
-timeout 180
- -re {mark\(\".*\"\)} { incr ok; exp_continue }
+ -re {mark\(\"[a-z_]+\"\)} { incr ok; exp_continue }
timeout { fail "$test C (timeout)" }
eof { }
}
diff --git a/testsuite/systemtap.base/stmt_rel.exp b/testsuite/systemtap.base/stmt_rel.exp
index be51fef9..619c91a5 100644
--- a/testsuite/systemtap.base/stmt_rel.exp
+++ b/testsuite/systemtap.base/stmt_rel.exp
@@ -1,8 +1,42 @@
-# test integer limits. Set and print variables and print constants.
-
set test "stmt_rel"
-set ::result_string {PASS bio_init
-PASS line number
-PASS wildcard}
-stap_run2 $srcdir/$subdir/$test.stp
+set line1 ""
+spawn stap -l "kernel.statement(\"bio_init@fs/bio.c+2\")"
+expect {
+ -timeout 180
+ -re {[0-9][0-9][0-9]} { regexp "\[0-9\]\[0-9\]\[0-9\]" $expect_out(0,string) line1; }
+ timeout { fail "$test C (timeout)" }
+ eof { }
+}
+
+set line2 ""
+spawn stap -l "kernel.statement(\"bio_init@fs/bio.c+3\")"
+expect {
+ -timeout 180
+ -re {[0-9][0-9][0-9]} { regexp "\[0-9\]\[0-9\]\[0-9\]" $expect_out(0,string) line2; }
+ timeout { fail "$test C (timeout)" }
+ eof { }
+}
+
+if { $line1 < $line2 } {
+ pass "$test line numbers"
+} else {
+ fail "$test line numbers"
+}
+
+set ok 0
+spawn stap -l "kernel.statement(\"bio_init@fs/bio.c:*\")"
+expect {
+ -timeout 180
+ -re {[0-9][0-9][0-9]} { incr ok; exp_continue }
+ timeout { fail "$test C (timeout)" }
+ eof { }
+}
+
+# bio_init drifts a bit in different kernels.
+# maybe 3, 4 or 15 lines in it.
+if { $ok >= 3 } {
+ pass "$test wildcard"
+} else {
+ fail "$test wildcard ($ok)"
+}
diff --git a/testsuite/systemtap.base/stmt_rel.stp b/testsuite/systemtap.base/stmt_rel.stp
deleted file mode 100644
index cfe77317..00000000
--- a/testsuite/systemtap.base/stmt_rel.stp
+++ /dev/null
@@ -1,71 +0,0 @@
-global stack2pp, stack2func, stack3pp, stack3func
-global wildcardpp, wild_count
-
-probe kernel.statement("bio_init@fs/bio.c+2") {
- # stack2 = tokenize(backtrace(), " ")
- stack2func = probefunc()
- stack2pp = pp()
-}
-probe kernel.statement("bio_init@fs/bio.c+3") {
- # stack3 = tokenize(backtrace(), " " )
- stack3func = probefunc()
- stack3pp = pp()
-}
-
-probe kernel.statement("bio_put@fs/bio.c:*") {
- line = tokenize(pp(),":")
- line = tokenize("",":")
- line = substr(line,0,strlen(line)-2)
- wildcardpp[strtol(line,10)]++
-
- if (wild_count++ <= 10) {
- next
- }
-
- stack2pp = tokenize(stack2pp,":")
- stack2pp = tokenize("",":")
- stack3pp = tokenize(stack3pp,":")
- stack3pp = tokenize("",":")
-
- stack2line = strtol (substr(stack2pp,0,strlen(stack2pp)-2), 10)
- stack3line = strtol (substr(stack3pp,0,strlen(stack3pp)-2), 10)
-
- # Did functions for both bio_init probes match?
- if (stack2func == stack3func) {
- printf ("PASS %s\n", stack2func)
- }
- else {
- printf ("FAIL %s %s\n", stack2func, stack3func)
- }
-
- # Was line # for bio_init probe +2 < line # for bio_init probe +3?
- if ((stack2line + 1) == stack3line) {
- printf ("PASS line number\n")
- }
- else {
- printf ("FAIL line number %d %d\n", stack2line, stack3line)
- }
-
- # This test does not take optimized code into account
- # Was address for bio_init probe +2 < address for bio_init probe +3?
- # if (stack2 < stack3) {
- # printf ("PASS address\n")
- # }
- # else {
- # printf ("FAIL address %s %s\n", stack2, stack3)
- # }
-
- # Did wildcard probe hit at least 4 different statements?
- foreach ([i] in wildcardpp) {
- statement_count += 1
- }
- if (statement_count >= 4) {
- printf ("PASS wildcard\n")
- }
- else
- {
- printf ("FAIL wildcard %d\n", statement_count)
- }
-
- exit()
-}
diff --git a/testsuite/systemtap.base/uprobes.exp b/testsuite/systemtap.base/uprobes.exp
index 89250e7b..6344cbf0 100644
--- a/testsuite/systemtap.base/uprobes.exp
+++ b/testsuite/systemtap.base/uprobes.exp
@@ -18,14 +18,7 @@ if [file exists $path] then { pass "$test prep" } else { fail "$test prep" }
catch {exec gcc -g -o jennie jennie.c} err
if {$err == "" && [file exists jennie]} then { pass "$test compile" } else { fail "$test compile" }
-# Try to find utrace_attach symbol in /proc/kallsyms
-# copy from utrace_p5.exp
-set utrace_support_found 0
-set path "/proc/kallsyms"
-if {! [catch {exec grep -q utrace_attach $path} dummy]} {
- set utrace_support_found 1
-}
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$test -p4"; untested "$test -p5"
catch {exec rm -f jennie.c jennie}
return
diff --git a/testsuite/systemtap.base/uprobes_exe.c b/testsuite/systemtap.base/uprobes_exe.c
index 447434c6..b4811335 100644
--- a/testsuite/systemtap.base/uprobes_exe.c
+++ b/testsuite/systemtap.base/uprobes_exe.c
@@ -15,13 +15,15 @@ int lib_main (void);
void
main_func (int foo)
{
- ; // nothing here...
+ if (foo > 1)
+ main_func (foo - 1);
+ else
+ lib_main();
}
int
main (int argc, char *argv[], char *envp[])
{
- main_func(1);
- lib_main();
+ main_func (3);
return 0;
}
diff --git a/testsuite/systemtap.base/uprobes_lib.c b/testsuite/systemtap.base/uprobes_lib.c
index c9d70625..25297b6b 100644
--- a/testsuite/systemtap.base/uprobes_lib.c
+++ b/testsuite/systemtap.base/uprobes_lib.c
@@ -10,7 +10,8 @@
void
lib_func (int bar)
{
- ; // nothing here...
+ if (bar > 1)
+ lib_func (bar - 1);
}
void
diff --git a/testsuite/systemtap.base/uprobes_lib.exp b/testsuite/systemtap.base/uprobes_lib.exp
index ae1b72e8..313c01b6 100644
--- a/testsuite/systemtap.base/uprobes_lib.exp
+++ b/testsuite/systemtap.base/uprobes_lib.exp
@@ -10,29 +10,37 @@ set testflags "additional_flags=-g additional_flags=-O"
set testlibflags "$testflags additional_flags=-fPIC additional_flags=-shared"
set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir"
-# Only run on make installcheck
-if {! [installtest_p]} { untested "$test"; return }
-
# Compile our test program and library.
set res [target_compile $testsrclib $testso executable $testlibflags]
if { $res != "" } {
verbose "target_compile for $testso failed: $res" 2
- fail "unable to compile $testsrclib"
+ fail "$test compile $testsrclib"
return
+} else {
+ pass "$test compile $testsrclib"
}
+
set res [target_compile $testsrc $testexe executable $maintestflags]
if { $res != "" } {
verbose "target_compile failed: $res" 2
- fail "unable to compile $testsrc"
+ fail "$test compile $testsrc"
return
+} else {
+ pass "$test compile $testsrc"
}
-# XXX main_func needs another/extra test. Disabled for now.
-# Enable (and in uprobes_lib.stp) after PR9940 is fixed.
-# set ::result_string {main_func
-# lib_func}
-set ::result_string {lib_func}
+set ::result_string {main
+main_func
+main_func
+main_func
+lib_main
+lib_func
+lib_func
+lib_func}
+# Only run on make installcheck
+if {! [installtest_p]} { untested "$test"; return }
+if {! [utrace_p]} { untested $test; return }
stap_run2 $srcdir/$subdir/$test.stp -c $testexe
#exec rm -f $testexe $testso
diff --git a/testsuite/systemtap.base/uprobes_lib.stp b/testsuite/systemtap.base/uprobes_lib.stp
index bc6cc249..459351a4 100644
--- a/testsuite/systemtap.base/uprobes_lib.stp
+++ b/testsuite/systemtap.base/uprobes_lib.stp
@@ -1,8 +1,14 @@
-/* - Not activated probe... Seems always skipped?
+probe process("uprobes_exe").function("main") {
+ printf("main\n");
+}
+
probe process("uprobes_exe").function("main_func") {
printf("main_func\n");
}
-*/
+
+probe process("libuprobes_lib.so").function("lib_main") {
+ printf("lib_main\n");
+}
probe process("libuprobes_lib.so").function("lib_func") {
printf("lib_func\n");
diff --git a/testsuite/systemtap.base/uprobes_uname.exp b/testsuite/systemtap.base/uprobes_uname.exp
new file mode 100644
index 00000000..65e1ff70
--- /dev/null
+++ b/testsuite/systemtap.base/uprobes_uname.exp
@@ -0,0 +1,46 @@
+set test "uprobes_uname"
+set testpath "$srcdir/$subdir"
+set testsrc "$testpath/uprobes_exe.c"
+set testsrclib "$testpath/uprobes_lib.c"
+set testexe "./uprobes_exe"
+set testlibname "uprobes_lib"
+set testlibdir "."
+set testso "$testlibdir/lib${testlibname}.so"
+set testflags "additional_flags=-g additional_flags=-O"
+set testlibflags "$testflags additional_flags=-fPIC additional_flags=-shared"
+set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir"
+
+# Compile our test program and library.
+set res [target_compile $testsrclib $testso executable $testlibflags]
+if { $res != "" } {
+ verbose "target_compile for $testso failed: $res" 2
+ fail "$test compile $testsrclib"
+ return
+} else {
+ pass "$test compile $testsrclib"
+}
+
+set res [target_compile $testsrc $testexe executable $maintestflags]
+if { $res != "" } {
+ verbose "target_compile failed: $res" 2
+ fail "$test compile $testsrc"
+ return
+} else {
+ pass "$test compile $testsrc"
+}
+
+set ::result_string {exe: main=main
+exe: main_func=main_func
+exe: main_func=main_func
+exe: main_func=main_func
+lib: lib_main=lib_main
+lib: lib_func=lib_func
+lib: lib_func=lib_func
+lib: lib_func=lib_func}
+
+# Only run on make installcheck
+if {! [installtest_p]} { untested "$test"; return }
+if {! [utrace_p]} { untested $test; return }
+stap_run2 $srcdir/$subdir/$test.stp -c $testexe
+
+#exec rm -f $testexe $testso
diff --git a/testsuite/systemtap.base/uprobes_uname.stp b/testsuite/systemtap.base/uprobes_uname.stp
new file mode 100644
index 00000000..a44d78d3
--- /dev/null
+++ b/testsuite/systemtap.base/uprobes_uname.stp
@@ -0,0 +1,7 @@
+probe process("uprobes_exe").function("*") {
+ printf("exe: %s=%s\n",probefunc(), usymname(uaddr()));
+}
+
+probe process("libuprobes_lib.so").function("*") {
+ printf("lib: %s=%s\n",probefunc(), usymname(uaddr()));
+}
diff --git a/testsuite/systemtap.base/utrace_p4.exp b/testsuite/systemtap.base/utrace_p4.exp
index 1467d9c8..8d323a8a 100644
--- a/testsuite/systemtap.base/utrace_p4.exp
+++ b/testsuite/systemtap.base/utrace_p4.exp
@@ -7,8 +7,6 @@
# utrace doesn't exist in the kernel, marks the tests as 'untested'.
# Initialize variables
-set utrace_support_found 0
-
set begin_script {"probe process(\"/bin/ls\").begin { print(\"ls begin\") }"}
set end_script {"probe process(\"/bin/ls\").end { print(\"ls end\") }"}
set syscall_script {"probe process(\"/bin/ls\").syscall { printf(\"|%d\", \$syscall) }"}
@@ -24,18 +22,12 @@ set pid_syscall_return_script {"probe process(123).syscall.return { printf(\"|%d
set pid_thread_begin_script {"probe process(123).thread.begin { print(\"123 thread.begin\") }"}
set pid_thread_end_script {"probe process(123).thread.end { print(\"123 thread.end\") }"}
-# 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
-}
-
#
# Do some utrace compile tests.
#
set TEST_NAME "UTRACE_P4_01"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a begin script using a path
@@ -43,7 +35,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_01_pid"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a begin script using a pid
@@ -51,7 +43,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_02"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a end script using a path
@@ -59,7 +51,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_02_pid"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a end script using a pid
@@ -67,7 +59,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_03"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a syscall script using a path
@@ -75,7 +67,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_03_pid"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a syscall script using a pid
@@ -83,7 +75,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_04"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a syscall return script using a path
@@ -91,7 +83,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_04_pid"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling a syscall return script using a pid
@@ -99,7 +91,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_05"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling an thread.begin script using a path
@@ -107,7 +99,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_05_pid"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling an thread.begin script using a pid
@@ -115,7 +107,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_06"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling an thread.end script using a path
@@ -123,7 +115,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_06_pid"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling an thread.end script using a pid
@@ -131,7 +123,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P4_07"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
# Try compiling an system-wide begin script
diff --git a/testsuite/systemtap.base/utrace_p5.exp b/testsuite/systemtap.base/utrace_p5.exp
index 33281350..3d432dc3 100644
--- a/testsuite/systemtap.base/utrace_p5.exp
+++ b/testsuite/systemtap.base/utrace_p5.exp
@@ -1,7 +1,6 @@
# Utrace run (pass 5) tests.
# Initialize variables
-set utrace_support_found 0
set exepath "[pwd]/cat_[pid]"
set multi_srcpath "$srcdir/systemtap.base/utrace_p5_multi.c"
set multi_exepath "[pwd]/utrace_p5_multi_[pid]"
@@ -90,12 +89,6 @@ set bz6841_script {
}
set bz6841_script_output ".+ issues syscall \\d+ times\r\n"
-# 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 up our own copy of /bin/cat, 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
@@ -138,7 +131,7 @@ proc run_utrace_p5_multi {} {
}
set TEST_NAME "UTRACE_P5_01"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested "$TEST_NAME"
@@ -148,7 +141,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P5_02"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested "$TEST_NAME"
@@ -158,7 +151,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P5_03"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested "$TEST_NAME"
@@ -168,7 +161,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P5_04"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested "$TEST_NAME"
@@ -178,7 +171,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P5_05"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested "$TEST_NAME"
@@ -189,7 +182,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P5_06"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested "$TEST_NAME"
@@ -200,7 +193,7 @@ if {$utrace_support_found == 0} {
}
set TEST_NAME "UTRACE_P5_07"
-if {$utrace_support_found == 0} {
+if {![utrace_p]} {
untested "$TEST_NAME : no kernel utrace support found"
} elseif {![installtest_p]} {
untested "$TEST_NAME"
diff --git a/testsuite/systemtap.context/args.tcl b/testsuite/systemtap.context/args.tcl
index 7cb79cdf..cffaeaef 100644
--- a/testsuite/systemtap.context/args.tcl
+++ b/testsuite/systemtap.context/args.tcl
@@ -1,6 +1,6 @@
spawn stap $srcdir/$subdir/args.stp
expect {
- -timeout 240
+ -timeout 60
"READY" {
exec echo 1 > /proc/stap_test_cmd
expect {
diff --git a/testsuite/systemtap.context/backtrace.tcl b/testsuite/systemtap.context/backtrace.tcl
index ca60c369..6edda812 100644
--- a/testsuite/systemtap.context/backtrace.tcl
+++ b/testsuite/systemtap.context/backtrace.tcl
@@ -8,7 +8,7 @@ set m6 0
spawn stap -DMAXSTRINGLEN=256 $srcdir/$subdir/backtrace.stp
#exp_internal 1
expect {
- -timeout 240
+ -timeout 60
"Systemtap probe: begin\r\n" {
pass "backtrace of begin probe"
exec echo 0 > /proc/stap_test_cmd
diff --git a/testsuite/systemtap.context/context.exp b/testsuite/systemtap.context/context.exp
index 010db445..cec09b29 100644
--- a/testsuite/systemtap.context/context.exp
+++ b/testsuite/systemtap.context/context.exp
@@ -80,6 +80,7 @@ if {[build_modules] == 0} {
}
foreach test $testlist {
+ send_log "sourcing: $srcdir/$subdir/$test.tcl\n"
source $srcdir/$subdir/$test.tcl
}
diff --git a/testsuite/systemtap.context/num_args.tcl b/testsuite/systemtap.context/num_args.tcl
index 7d12b433..62ac8dd3 100644
--- a/testsuite/systemtap.context/num_args.tcl
+++ b/testsuite/systemtap.context/num_args.tcl
@@ -3,7 +3,7 @@ foreach arglist $arglists {
set tag [concat numeric $arglist]
eval spawn stap $arglist $srcdir/$subdir/num_args.stp
expect {
- -timeout 240
+ -timeout 60
"READY" {
exec echo 1 > /proc/stap_test_cmd
expect {
diff --git a/testsuite/systemtap.context/pid.tcl b/testsuite/systemtap.context/pid.tcl
index a2c091f1..70a87345 100644
--- a/testsuite/systemtap.context/pid.tcl
+++ b/testsuite/systemtap.context/pid.tcl
@@ -2,7 +2,7 @@ set tests [list execname pexecname pid ppid tid uid euid gid egid]
spawn stap $srcdir/$subdir/pid.stp
#exp_internal 1
expect {
- -timeout 240
+ -timeout 60
"READY" {
set pid [exec echo 1 > /proc/stap_test_cmd &]
set ppid {[0-9]*}
diff --git a/testsuite/systemtap.context/usymbols.c b/testsuite/systemtap.context/usymbols.c
new file mode 100644
index 00000000..7c590724
--- /dev/null
+++ b/testsuite/systemtap.context/usymbols.c
@@ -0,0 +1,39 @@
+/* usymbol test case
+ * 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.
+ *
+ * Uses signal to tranfer user space addresses into the kernel where a
+ * probe on sigaction will extract them and produce the symbols. To
+ * poke into the executable we get the sa_handler from the main executable,
+ * and then the library through calling signal.
+ *
+ * FIXME. We call into the library to get the right symbol. If we
+ * register the handler from the main executable. We need to handle
+ * @plt symbols (setting a handler in the main executable that is in a
+ * shared library will have the @plt address, not the address inside
+ * the shared library).
+ */
+
+#include <signal.h>
+typedef void (*sighandler_t)(int);
+
+// function from our library
+int lib_main (void);
+
+void
+main_handler (int signum)
+{
+ /* dummy handler, just used for the address... */
+}
+
+int
+main (int argc, char *argv[], char *envp[])
+{
+ // Use SIGFPE since we never expect that to be triggered.
+ signal(SIGFPE, main_handler);
+ lib_main();
+}
diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp
new file mode 100644
index 00000000..39b3b442
--- /dev/null
+++ b/testsuite/systemtap.context/usymbols.exp
@@ -0,0 +1,82 @@
+set test "./usymbols"
+set testpath "$srcdir/$subdir"
+set testsrc "$testpath/usymbols.c"
+set testsrclib "$testpath/usymbols_lib.c"
+set testexe "[pwd]/usymbols"
+set testlibname "usymbols"
+set testlibdir "[pwd]"
+set testso "$testlibdir/lib${testlibname}.so"
+set testflags "additional_flags=-g additional_flags=-O"
+set testlibflags "testflags additional_flags=-fPIC additional_flags=-shared"
+set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir"
+
+# Only run on make installcheck and utrace present.
+if {! [installtest_p]} { untested "$test"; return }
+if {! [utrace_p]} { untested "$test"; return }
+
+# Compile our test program and library.
+set res [target_compile $testsrclib $testso executable $testlibflags]
+if { $res != "" } {
+ verbose "target_compile for $testso failed: $res" 2
+ fail "unable to compile $testsrclib"
+ return
+}
+set res [target_compile $testsrc $testexe executable $maintestflags]
+if { $res != "" } {
+ verbose "target_compile failed: $res" 2
+ fail "unable to compile $testsrc"
+ return
+}
+
+# We need the execname() trick to work around (the workaround of) PR6964
+# otherwise we get also the rt_sigactions of stapio. Get the handler
+# (comes from the executable or the library).
+set testscript {
+ probe syscall.rt_sigaction {
+ if (pid() == target() && execname() == "%s") {
+ handler = $act->sa_handler;
+ printf("handler: %%s\n", usymname(handler));
+ }
+ }
+ /* track through uprobes, so as to make sure we have the symbols */
+ probe process("%s").function("*") { printf(""); }
+}
+
+set output {handler: main_handler
+handler: lib_handler}
+
+# Got to run stap with both the exe and the libraries used as -d args.
+# XXX Note how we need the fully resolved (absolute) path...
+set script [format $testscript usymbols $testexe]
+catch {eval exec [concat ldd $testexe | grep $testlibname]} libpath
+set libpath [lindex [split $libpath " "] 2]
+send_log "libpath: $libpath\n"
+if {[string equal "link" [file type $libpath]]} {
+ set libpath [file join [file dirname $libpath] [file readlink $libpath]]
+}
+send_log "libpath: $libpath\n"
+
+set cmd [concat stap -d $libpath -d $testexe -c $testexe -e {$script}]
+send_log "cmd: $cmd\n"
+catch {eval exec $cmd} res
+send_log "cmd output: $res\n"
+
+set n 0
+set m [llength [split $output "\n"]]
+set expected [split $output "\n"]
+foreach line [split $res "\n"] {
+ if {![string equal $line [lindex $expected $n]]} {
+ fail usymbols
+ send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\", "
+ send_log "Got \"$line\"\n"
+ return
+ }
+ incr n
+}
+if { $n != $m } {
+ fail usymbols
+ send_log "Got \"$n\" lines, expected \"$m\" lines\n"
+} else {
+ pass usymbols
+}
+exec rm -f $testexe $testso
diff --git a/testsuite/systemtap.context/usymbols_lib.c b/testsuite/systemtap.context/usymbols_lib.c
new file mode 100644
index 00000000..faccb39b
--- /dev/null
+++ b/testsuite/systemtap.context/usymbols_lib.c
@@ -0,0 +1,29 @@
+/* usymbol test case - library helper
+ * 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.
+ *
+ * Uses signal to tranfer user space addresses into the kernel where a
+ * probe on sigaction will extract them and produce the symbols. To
+ * poke into the executable we get the sa_handler set through signal
+ * from this library.
+ */
+
+#include <signal.h>
+typedef void (*sighandler_t)(int);
+
+void
+lib_handler (int signum)
+{
+ /* dummy handler, just used for the address... */
+}
+
+void
+lib_main ()
+{
+ // Use SIGFPE since we never expect that to be triggered.
+ signal(SIGFPE, lib_handler);
+}
diff --git a/testsuite/systemtap.examples/general/ansi_colors.meta b/testsuite/systemtap.examples/general/ansi_colors.meta
new file mode 100644
index 00000000..2818c235
--- /dev/null
+++ b/testsuite/systemtap.examples/general/ansi_colors.meta
@@ -0,0 +1,13 @@
+title: Color Table for ansi_set_color2() and ansi_set_color3()
+name: ansi_colors.stp
+version: 1.0
+author: Eugene Teo
+keywords: format
+subsystem: none
+status: production
+exit: fixed
+output: text
+scope: system-wide
+description: The script prints a table showing the available color combinations for the ansi_set_color2() and ans_set_color3() functions in the ansi.stp tapset.
+test_check: stap -p4 ansi_colors.stp
+test_installcheck: stap ansi_colors.stp
diff --git a/testsuite/systemtap.examples/general/ansi_colors.stp b/testsuite/systemtap.examples/general/ansi_colors.stp
index ae954e69..01e58b9c 100755
--- a/testsuite/systemtap.examples/general/ansi_colors.stp
+++ b/testsuite/systemtap.examples/general/ansi_colors.stp
@@ -1,21 +1,30 @@
-#! /usr/bin/env stap
+#!/usr/bin/env stap
+# ansi_colors.stp
+# Copyright (C) 2006-2009 Red Hat, Inc., Eugene Teo <eteo@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
probe begin {
- printf("a \\ b |");
- for (c = 40; c < 48; c++)
- printf(" %d ", c);
- printf("\12");
- for (l = 0; l < 71; l++)
- printf("-");
- printf("\12");
+ printf("fg,t \\ bg |");
+ for (c = 40; c < 48; c++)
+ printf(" %d ", c);
+ ansi_new_line()
+ for (l = 0; l < 75; l++)
+ printf("-");
+ ansi_new_line()
- for (r = 30; r < 38; r++)
- for (t = 0; t < 2; t++) {
- printf("%d |", r);
- for (c = 40; c < 48; c++)
- printf("\033[%d;%d%s %s \033[0;0m",
- r, c, !t ? "m" : ";1m", !t ? "Normal" : "Bold ");
- printf("\12");
- }
- exit();
+ for (r = 30; r < 38; r++)
+ for (t = 0; t < 2; t++) {
+ printf(" %2d,%1d |", r, t);
+ for (c = 40; c < 48; c++) {
+ ansi_set_color3(r, c, t)
+ printf(" %s ", !t ? "Normal" : "Bold ")
+ ansi_reset_color()
+ }
+ ansi_new_line()
+ }
+ exit();
}
diff --git a/testsuite/systemtap.examples/general/ansi_colors2.meta b/testsuite/systemtap.examples/general/ansi_colors2.meta
new file mode 100644
index 00000000..4ccaf4e3
--- /dev/null
+++ b/testsuite/systemtap.examples/general/ansi_colors2.meta
@@ -0,0 +1,13 @@
+title: Show Attribues in Table for ansi_set_color3()
+name: ansi_colors2.stp
+version: 1.0
+author: Eugene Teo
+keywords: format
+subsystem: none
+status: production
+exit: fixed
+output: text
+scope: system-wide
+description: The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset.
+test_check: stap -p4 ansi_colors2.stp
+test_installcheck: stap ansi_colors2.stp
diff --git a/testsuite/systemtap.examples/general/ansi_colors2.stp b/testsuite/systemtap.examples/general/ansi_colors2.stp
new file mode 100755
index 00000000..fadcf011
--- /dev/null
+++ b/testsuite/systemtap.examples/general/ansi_colors2.stp
@@ -0,0 +1,31 @@
+#!/usr/bin/env stap
+# ansi_colors2.stp
+# Copyright (C) 2009 Red Hat, Inc., Eugene Teo <eteo@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+
+probe begin {
+ printf("fg,t \\ bg |");
+ for (c = 40; c < 48; c++)
+ printf(" %d ", c);
+ ansi_new_line()
+ for (l = 0; l < 75; l++)
+ printf("-");
+ ansi_new_line()
+
+ for (r = 30; r < 38; r++)
+ # this displays more attributes
+ for (t = 0; t < 8; !t ? ++t : t+=3) {
+ printf(" %2d,%1d |", r, t);
+ for (c = 40; c < 48; c++) {
+ ansi_set_color3(r, c, t)
+ printf(" Colors ")
+ ansi_reset_color()
+ }
+ ansi_new_line()
+ }
+ exit();
+}
diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html
index 0f4b2572..a03b8dcc 100644
--- a/testsuite/systemtap.examples/index.html
+++ b/testsuite/systemtap.examples/index.html
@@ -40,6 +40,12 @@
<h2>All Examples</h2>
<ul>
+<li><a href="general/ansi_colors.stp">general/ansi_colors.stp</a> - Color Table for ansi_set_color2() and ansi_set_color3()<br>
+keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br>
+<p>The script prints a table showing the available color combinations for the ansi_set_color2() and ans_set_color3() functions in the ansi.stp tapset.</p></li>
+<li><a href="general/ansi_colors2.stp">general/ansi_colors2.stp</a> - Show Attribues in Table for ansi_set_color3()<br>
+keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br>
+<p>The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset.</p></li>
<li><a href="general/graphs.stp">general/graphs.stp</a> - Graphing Disk and CPU Utilization<br>
keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html#CPU">CPU</a> <a href="keyword-index.html#USE">USE</a> <a href="keyword-index.html#GRAPH">GRAPH</a> <br>
<p>The script tracks the disk and CPU utilization. The resulting output of the script can be piped into gnuplot to generate a graph of disk and CPU USE.</p></li>
@@ -60,7 +66,7 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#BAC
<p>When a reschedule occurs during an AIO io_submit call, accumulate the traceback in a histogram. When the script exits prints out a sorted list from most common to least common backtrace.</p></li>
<li><a href="io/ioblktime.stp">io/ioblktime.stp</a> - Average Time Block IO Requests Spend in Queue <br>
keywords: <a href="keyword-index.html#IO">IO</a> <br>
-<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script compute the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li>
+<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li>
<li><a href="io/iostats.stp">io/iostats.stp</a> - List Executables Reading and Writing the Most Data<br>
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <br>
<p> The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.</p></li>
@@ -91,6 +97,12 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde
<li><a href="network/tcp_connections.stp">network/tcp_connections.stp</a> - Track Creation of Incoming TCP Connections<br>
keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TCP">TCP</a> <a href="keyword-index.html#SOCKET">SOCKET</a> <br>
<p>The tcp_connections.stp script prints information for each new incoming TCP connection accepted by the computer. The information includes the UID, the command accepting the connection, the PID of the command, the port the connection is on, and the IP address of the originator of the request.</p></li>
+<li><a href="network/tcpdumplike.stp">network/tcpdumplike.stp</a> - Dump of Received TCP Packets<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <br>
+<p>The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags.</p></li>
+<li><a href="process/errsnoop.stp">process/errsnoop.stp</a> - tabulate system call errors<br>
+keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br>
+<p>The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).</p></li>
<li><a href="process/futexes.stp">process/futexes.stp</a> - System-Wide Futex Contention<br>
keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#LOCKING">LOCKING</a> <a href="keyword-index.html#FUTEX">FUTEX</a> <br>
<p>The script watches the futex syscall on the system. On exit the futexes address, the number of contentions, and the average time for each contention on the futex are printed from lowest pid number to highest.</p></li>
diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt
index e31baf4f..d24232e7 100644
--- a/testsuite/systemtap.examples/index.txt
+++ b/testsuite/systemtap.examples/index.txt
@@ -1,6 +1,22 @@
SYSTEMTAP EXAMPLES INDEX
(see also keyword-index.txt)
+general/ansi_colors.stp - Color Table for ansi_set_color2() and ansi_set_color3()
+keywords: format
+
+ The script prints a table showing the available color combinations
+ for the ansi_set_color2() and ans_set_color3() functions in the
+ ansi.stp tapset.
+
+
+general/ansi_colors2.stp - Show Attribues in Table for ansi_set_color3()
+keywords: format
+
+ The script prints a table showing the available attributes (bold,
+ underline, and inverse) with color combinations for the
+ ans_set_color3() function in the ansi.stp tapset.
+
+
general/graphs.stp - Graphing Disk and CPU Utilization
keywords: disk cpu use graph
@@ -56,10 +72,10 @@ io/ioblktime.stp - Average Time Block IO Requests Spend in Queue
keywords: io
The ioblktime.stp script tracks the amount of time that each block IO
- requests spend waiting for completion. The script compute the average
- time waiting time for block IO per device and prints list every 10
- seconds. In some cases there can be too many oustanding block IO
- operations and the script may exceed the default number of
+ requests spend waiting for completion. The script computes the
+ average time waiting time for block IO per device and prints list
+ every 10 seconds. In some cases there can be too many oustanding
+ block IO operations and the script may exceed the default number of
MAXMAPENTRIES allowed. In this case the allowed number can be
increased with "-DMAXMAPENTRIES=10000" option on the stap command
line.
@@ -166,6 +182,24 @@ keywords: network tcp socket
originator of the request.
+network/tcpdumplike.stp - Dump of Received TCP Packets
+keywords: network traffic
+
+ The tcpdumplike.stp prints out a line for each TCP packet received.
+ Each line includes the source and destination IP addresses, the
+ source and destination ports, and flags.
+
+
+process/errsnoop.stp - tabulate system call errors
+keywords: process syscall
+
+ The script prints a periodic tabular report about failing system
+ calls, by process and by syscall failure. The first optional
+ argument specifies the reporting interval (in seconds, default 5);
+ the second optional argument gives a screen height (number of lines
+ in the report, default 20).
+
+
process/futexes.stp - System-Wide Futex Contention
keywords: syscall locking futex
diff --git a/testsuite/systemtap.examples/io/ioblktime.stp b/testsuite/systemtap.examples/io/ioblktime.stp
index 5ff59cf7..d6267b3e 100755
--- a/testsuite/systemtap.examples/io/ioblktime.stp
+++ b/testsuite/systemtap.examples/io/ioblktime.stp
@@ -18,7 +18,7 @@ probe ioblock.end
}
probe timer.s(10), end {
- printf("\033[2J\033[1;1H") /* clear screen */
+ ansi_clear_screen()
printf("%10s %3s %10s %10s %10s\n",
"device", "rw", "total (us)", "count", "avg (us)")
foreach ([dev,rw] in etimes - limit 20) {
diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html
index 75768709..e65ed19d 100644
--- a/testsuite/systemtap.examples/keyword-index.html
+++ b/testsuite/systemtap.examples/keyword-index.html
@@ -39,7 +39,7 @@
</ul>
<h2>Examples by Keyword</h2>
-<p><tt><a href="#BACKTRACE">BACKTRACE</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DISK">DISK</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#NETWORK">NETWORK</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
+<p><tt><a href="#BACKTRACE">BACKTRACE</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DISK">DISK</a> <a href="#FORMAT">FORMAT</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#NETWORK">NETWORK</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROCESS">PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
<h3><a name="BACKTRACE">BACKTRACE</a></h3>
<ul>
<li><a href="interrupt/scf.stp">interrupt/scf.stp</a> - Tally Backtraces for Inter-Processor Interrupt (IPI)<br>
@@ -73,6 +73,15 @@ keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html
keywords: <a href="keyword-index.html#DISK">DISK</a> <br>
<p>Get the status of reading/writing disk every 5 seconds, output top ten entries during that period.</p></li>
</ul>
+<h3><a name="FORMAT">FORMAT</a></h3>
+<ul>
+<li><a href="general/ansi_colors.stp">general/ansi_colors.stp</a> - Color Table for ansi_set_color2() and ansi_set_color3()<br>
+keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br>
+<p>The script prints a table showing the available color combinations for the ansi_set_color2() and ans_set_color3() functions in the ansi.stp tapset.</p></li>
+<li><a href="general/ansi_colors2.stp">general/ansi_colors2.stp</a> - Show Attribues in Table for ansi_set_color3()<br>
+keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br>
+<p>The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset.</p></li>
+</ul>
<h3><a name="FUNCTIONS">FUNCTIONS</a></h3>
<ul>
<li><a href="profiling/functioncallcount.stp">profiling/functioncallcount.stp</a> - Count Times Functions Called<br>
@@ -104,7 +113,7 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#BAC
<p>When a reschedule occurs during an AIO io_submit call, accumulate the traceback in a histogram. When the script exits prints out a sorted list from most common to least common backtrace.</p></li>
<li><a href="io/ioblktime.stp">io/ioblktime.stp</a> - Average Time Block IO Requests Spend in Queue <br>
keywords: <a href="keyword-index.html#IO">IO</a> <br>
-<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script compute the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li>
+<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li>
<li><a href="io/iostats.stp">io/iostats.stp</a> - List Executables Reading and Writing the Most Data<br>
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <br>
<p> The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.</p></li>
@@ -150,6 +159,9 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde
<li><a href="network/tcp_connections.stp">network/tcp_connections.stp</a> - Track Creation of Incoming TCP Connections<br>
keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TCP">TCP</a> <a href="keyword-index.html#SOCKET">SOCKET</a> <br>
<p>The tcp_connections.stp script prints information for each new incoming TCP connection accepted by the computer. The information includes the UID, the command accepting the connection, the PID of the command, the port the connection is on, and the IP address of the originator of the request.</p></li>
+<li><a href="network/tcpdumplike.stp">network/tcpdumplike.stp</a> - Dump of Received TCP Packets<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <br>
+<p>The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags.</p></li>
</ul>
<h3><a name="PER-PROCESS">PER-PROCESS</a></h3>
<ul>
@@ -157,6 +169,12 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde
keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <a href="keyword-index.html#PER-PROCESS">PER-PROCESS</a> <br>
<p>Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.</p></li>
</ul>
+<h3><a name="PROCESS">PROCESS</a></h3>
+<ul>
+<li><a href="process/errsnoop.stp">process/errsnoop.stp</a> - tabulate system call errors<br>
+keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br>
+<p>The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).</p></li>
+</ul>
<h3><a name="PROFILING">PROFILING</a></h3>
<ul>
<li><a href="io/iostats.stp">io/iostats.stp</a> - List Executables Reading and Writing the Most Data<br>
@@ -231,6 +249,9 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde
<li><a href="io/iotime.stp">io/iotime.stp</a> - Trace Time Spent in Read and Write for Files <br>
keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#READ">READ</a> <a href="keyword-index.html#WRITE">WRITE</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#IO">IO</a> <br>
<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li>
+<li><a href="process/errsnoop.stp">process/errsnoop.stp</a> - tabulate system call errors<br>
+keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br>
+<p>The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).</p></li>
<li><a href="process/futexes.stp">process/futexes.stp</a> - System-Wide Futex Contention<br>
keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#LOCKING">LOCKING</a> <a href="keyword-index.html#FUTEX">FUTEX</a> <br>
<p>The script watches the futex syscall on the system. On exit the futexes address, the number of contentions, and the average time for each contention on the futex are printed from lowest pid number to highest.</p></li>
@@ -270,6 +291,9 @@ keywords: <a href="keyword-index.html#TRACE">TRACE</a> <a href="keyword-index.ht
<li><a href="network/nettop.stp">network/nettop.stp</a> - Periodic Listing of Processes Using Network Interfaces<br>
keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <a href="keyword-index.html#PER-PROCESS">PER-PROCESS</a> <br>
<p>Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.</p></li>
+<li><a href="network/tcpdumplike.stp">network/tcpdumplike.stp</a> - Dump of Received TCP Packets<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <br>
+<p>The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags.</p></li>
</ul>
<h3><a name="USE">USE</a></h3>
<ul>
diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt
index d3a9617f..40b5276f 100644
--- a/testsuite/systemtap.examples/keyword-index.txt
+++ b/testsuite/systemtap.examples/keyword-index.txt
@@ -70,6 +70,24 @@ keywords: disk
ten entries during that period.
+= FORMAT =
+
+general/ansi_colors.stp - Color Table for ansi_set_color2() and ansi_set_color3()
+keywords: format
+
+ The script prints a table showing the available color combinations
+ for the ansi_set_color2() and ans_set_color3() functions in the
+ ansi.stp tapset.
+
+
+general/ansi_colors2.stp - Show Attribues in Table for ansi_set_color3()
+keywords: format
+
+ The script prints a table showing the available attributes (bold,
+ underline, and inverse) with color combinations for the
+ ans_set_color3() function in the ansi.stp tapset.
+
+
= FUNCTIONS =
profiling/functioncallcount.stp - Count Times Functions Called
@@ -129,10 +147,10 @@ io/ioblktime.stp - Average Time Block IO Requests Spend in Queue
keywords: io
The ioblktime.stp script tracks the amount of time that each block IO
- requests spend waiting for completion. The script compute the average
- time waiting time for block IO per device and prints list every 10
- seconds. In some cases there can be too many oustanding block IO
- operations and the script may exceed the default number of
+ requests spend waiting for completion. The script computes the
+ average time waiting time for block IO per device and prints list
+ every 10 seconds. In some cases there can be too many oustanding
+ block IO operations and the script may exceed the default number of
MAXMAPENTRIES allowed. In this case the allowed number can be
increased with "-DMAXMAPENTRIES=10000" option on the stap command
line.
@@ -263,6 +281,14 @@ keywords: network tcp socket
originator of the request.
+network/tcpdumplike.stp - Dump of Received TCP Packets
+keywords: network traffic
+
+ The tcpdumplike.stp prints out a line for each TCP packet received.
+ Each line includes the source and destination IP addresses, the
+ source and destination ports, and flags.
+
+
= PER-PROCESS =
network/nettop.stp - Periodic Listing of Processes Using Network Interfaces
@@ -274,6 +300,18 @@ keywords: network traffic per-process
interval.
+= PROCESS =
+
+process/errsnoop.stp - tabulate system call errors
+keywords: process syscall
+
+ The script prints a periodic tabular report about failing system
+ calls, by process and by syscall failure. The first optional
+ argument specifies the reporting interval (in seconds, default 5);
+ the second optional argument gives a screen height (number of lines
+ in the report, default 20).
+
+
= PROFILING =
io/iostats.stp - List Executables Reading and Writing the Most Data
@@ -458,6 +496,16 @@ keywords: syscall read write time io
syscalls.
+process/errsnoop.stp - tabulate system call errors
+keywords: process syscall
+
+ The script prints a periodic tabular report about failing system
+ calls, by process and by syscall failure. The first optional
+ argument specifies the reporting interval (in seconds, default 5);
+ the second optional argument gives a screen height (number of lines
+ in the report, default 20).
+
+
process/futexes.stp - System-Wide Futex Contention
keywords: syscall locking futex
@@ -557,6 +605,14 @@ keywords: network traffic per-process
interval.
+network/tcpdumplike.stp - Dump of Received TCP Packets
+keywords: network traffic
+
+ The tcpdumplike.stp prints out a line for each TCP packet received.
+ Each line includes the source and destination IP addresses, the
+ source and destination ports, and flags.
+
+
= USE =
general/graphs.stp - Graphing Disk and CPU Utilization
diff --git a/testsuite/systemtap.examples/network/nettop.stp b/testsuite/systemtap.examples/network/nettop.stp
index 15b4d62a..e96548f1 100755
--- a/testsuite/systemtap.examples/network/nettop.stp
+++ b/testsuite/systemtap.examples/network/nettop.stp
@@ -1,6 +1,7 @@
#! /usr/bin/env stap
global ifxmit, ifrecv
+global ifmerged
probe netdev.transmit
{
@@ -18,7 +19,13 @@ function print_activity()
"PID", "UID", "DEV", "XMIT_PK", "RECV_PK",
"XMIT_KB", "RECV_KB", "COMMAND")
- foreach ([pid, dev, exec, uid] in ifrecv-) {
+ foreach ([pid, dev, exec, uid] in ifrecv) {
+ ifmerged[pid, dev, exec, uid] += @count(ifrecv[pid,dev,exec,uid]);
+ }
+ foreach ([pid, dev, exec, uid] in ifxmit) {
+ ifmerged[pid, dev, exec, uid] += @count(ifxmit[pid,dev,exec,uid]);
+ }
+ foreach ([pid, dev, exec, uid] in ifmerged-) {
n_xmit = @count(ifxmit[pid, dev, exec, uid])
n_recv = @count(ifrecv[pid, dev, exec, uid])
printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n",
@@ -32,6 +39,7 @@ function print_activity()
delete ifxmit
delete ifrecv
+ delete ifmerged
}
probe timer.ms(5000), end, error
diff --git a/testsuite/systemtap.examples/network/tcp.stp b/testsuite/systemtap.examples/network/tcp.stp
index 01db9d2d..01db9d2d 100644..100755
--- a/testsuite/systemtap.examples/network/tcp.stp
+++ b/testsuite/systemtap.examples/network/tcp.stp
diff --git a/testsuite/systemtap.examples/network/tcpdumplike.meta b/testsuite/systemtap.examples/network/tcpdumplike.meta
new file mode 100644
index 00000000..8fb9fccb
--- /dev/null
+++ b/testsuite/systemtap.examples/network/tcpdumplike.meta
@@ -0,0 +1,12 @@
+title: Dump of Received TCP Packets
+name: tcpdumplike.stp
+version: 1.0
+author: anonymous
+keywords: network traffic
+subsystem: network
+status: production
+exit: user-controlled
+output: timed
+scope: system-wide
+description: The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags.
+test_installcheck: stap tcpdumplike.stp -c "sleep 1"
diff --git a/testsuite/systemtap.examples/network/tcpdumplike.stp b/testsuite/systemtap.examples/network/tcpdumplike.stp
new file mode 100755
index 00000000..de3899d6
--- /dev/null
+++ b/testsuite/systemtap.examples/network/tcpdumplike.stp
@@ -0,0 +1,14 @@
+#! /usr/bin/env stap
+
+// A TCP dump like example
+
+probe begin, timer.s(1) {
+ printf("-----------------------------------------------------------------\n")
+ printf(" Source IP Dest IP SPort DPort U A P R S F \n")
+ printf("-----------------------------------------------------------------\n")
+}
+
+probe tcp.receive {
+ printf(" %15s %15s %5d %5d %d %d %d %d %d %d\n",
+ saddr, daddr, sport, dport, urg, ack, psh, rst, syn, fin)
+}
diff --git a/testsuite/systemtap.examples/process/errsnoop.meta b/testsuite/systemtap.examples/process/errsnoop.meta
new file mode 100644
index 00000000..34b8cb7c
--- /dev/null
+++ b/testsuite/systemtap.examples/process/errsnoop.meta
@@ -0,0 +1,7 @@
+title: tabulate system call errors
+name: errsnoop.stp
+keywords: process syscall
+subsystem: general
+description: The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).
+test_check: stap -p4 errsnoop.stp
+test_installcheck: stap errsnoop.stp 1 10 -c "sleep 3"
diff --git a/testsuite/systemtap.examples/process/errsnoop.stp b/testsuite/systemtap.examples/process/errsnoop.stp
new file mode 100755
index 00000000..a3f17b77
--- /dev/null
+++ b/testsuite/systemtap.examples/process/errsnoop.stp
@@ -0,0 +1,44 @@
+#!/bin/sh
+//usr/bin/env stap -DMAXMAPENTRIES=20480 $0 $@; exit $?
+# errsnoop.stp
+# Copyright (C) 2009 Red Hat, Inc., Eugene Teo <eteo@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# attack "stupid userspace" apps
+#
+
+global error, trace
+
+probe syscall.* {
+ # assume syscall don't nest
+ trace[tid()] = argstr
+}
+
+probe syscall.*.return {
+ errno = errno_p(returnval())
+ if (errno != 0) {
+ t = tid()
+ argstr = trace[t]
+ delete trace[t]
+
+ error[name, execname(), pid(), errno, argstr] <<< 1
+ }
+}
+
+probe timer.s(%( $# > 0 %? $1 %: 5 %)) {
+ ansi_clear_screen()
+ printf("%17s %15s %5s %4s %-12s %s\n",
+ "SYSCALL", "PROCESS", "PID", "HITS", "ERRSTR", "ARGSTR")
+ foreach([fn, comm, pid, errno, argstr] in error- limit %( $# > 1 %? $2 %: 20 %)) {
+ errstr = sprintf("%3d (%s)", errno, errno_str(errno))
+ printf("%17s %15s %5d %4d %-12s %s\n", fn, comm, pid,
+ @count(error[fn, comm, pid, errno, argstr]),
+# errstr, substr(argstr,0,22)) # within cols#80
+ errstr, argstr)
+
+ }
+ delete error
+}
diff --git a/testsuite/systemtap.examples/process/proc_snoop.stp b/testsuite/systemtap.examples/process/proc_snoop.stp
index 06425d45..9a3768c2 100755
--- a/testsuite/systemtap.examples/process/proc_snoop.stp
+++ b/testsuite/systemtap.examples/process/proc_snoop.stp
@@ -18,30 +18,30 @@ function id:string(task:long) {
task_execname(task))
}
-probe process.create {
+probe kprocess.create {
report(sprintf("create %s", id(task)))
}
-probe process.start {
+probe kprocess.start {
report("start")
}
-probe process.exec {
+probe kprocess.exec {
report(sprintf("exec %s", filename))
}
-probe process.exec_complete {
+probe kprocess.exec_complete {
if (success)
report("exec success")
else
report(sprintf("exec failed %d (%s)", errno, errno_str(errno)))
}
-probe process.exit {
+probe kprocess.exit {
report(sprintf("exit %d", code))
}
-probe process.release {
+probe kprocess.release {
report(sprintf("remove %s", id(task)))
}
diff --git a/testsuite/systemtap.examples/profiling/timeout.stp b/testsuite/systemtap.examples/profiling/timeout.stp
index 48d6d21d..8054b364 100755
--- a/testsuite/systemtap.examples/profiling/timeout.stp
+++ b/testsuite/systemtap.examples/profiling/timeout.stp
@@ -90,8 +90,8 @@ probe syscall.exit {
}
probe timer.s(1) {
- printf("\033[2J\033[1;1H") /* clear screen */
- printf (" uid | poll select epoll itimer futex nanosle signal| process\n")
+ ansi_clear_screen()
+ printf (" pid | poll select epoll itimer futex nanosle signal| process\n")
foreach (p in timeout_count- limit 20) {
printf ("%5d |%7d %7d %7d %7d %7d %7d %7d| %-.38s\n", p,
poll_timeout[p], select_timeout[p],
diff --git a/testsuite/systemtap.pass1-4/buildok.exp b/testsuite/systemtap.pass1-4/buildok.exp
index 08d50fb5..12275c1d 100644
--- a/testsuite/systemtap.pass1-4/buildok.exp
+++ b/testsuite/systemtap.pass1-4/buildok.exp
@@ -6,12 +6,12 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] {
# some tests are known to fail.
switch $test {
buildok/perfmon01.stp {setup_kfail 909 *-*-*}
- buildok/twentysix.stp {setup_kfail 4105 *-*-*}
buildok/twentyseven.stp {setup_kfail 4166 *-*-*}
buildok/sched_test.stp {setup_kfail 1155 *-*-*}
buildok/process_test.stp {setup_kfail 1155 *-*-*}
buildok/rpc-all-probes.stp {setup_kfail 4413 *-*-*}
buildok/nfs-all-probes.stp {setup_kfail 4413 *-*-*}
+ buildok/per-process-syscall.stp {if {![utrace_p]} { setup_kfail 9999 *-*-*} }
}
if {$rc == 0} { pass $test } else { fail $test }
}
diff --git a/testsuite/systemtap.server/server.exp b/testsuite/systemtap.server/server.exp
index c2c60b97..d2dd0f16 100644
--- a/testsuite/systemtap.server/server.exp
+++ b/testsuite/systemtap.server/server.exp
@@ -16,7 +16,6 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] {
# some tests are known to fail.
switch $test {
"buildok/perfmon01.stp with server" {setup_kfail 909 *-*-*}
- "buildok/twentysix.stp with server" {setup_kfail 4105 *-*-*}
"buildok/twentyseven.stp with server" {setup_kfail 4166 *-*-*}
"buildok/sched_test.stp with server" {setup_kfail 1155 *-*-*}
"buildok/process_test.stp with server" {setup_kfail 1155 *-*-*}
diff --git a/testsuite/systemtap.stress/whitelist.exp b/testsuite/systemtap.stress/whitelist.exp
index 4a31c124..70973978 100644
--- a/testsuite/systemtap.stress/whitelist.exp
+++ b/testsuite/systemtap.stress/whitelist.exp
@@ -96,6 +96,7 @@ set init_probes_all_script {
udp.*.return,
tcp.*,
tcp.*.return,
+ kprocess.*,
process.*,
nfs.fop.*,
nfs.aop.*,
diff --git a/translate.cxx b/translate.cxx
index 47fffd1e..d81287ee 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -918,6 +918,7 @@ c_unparser::emit_common_header ()
ostringstream oss;
oss << "c->statp = & time_" << dp->basest()->name << ";" << endl; // -t anti-dupe
oss << "# needs_global_locks: " << dp->needs_global_locks () << endl;
+ dp->print_dupe_stamp (oss);
dp->body->print(oss);
// NB: dependent probe conditions *could* be listed here, but don't need to be.
// That's because they're only dependent on the probe body, which is already
@@ -1507,6 +1508,7 @@ c_unparser::emit_probe (derived_probe* v)
// be very different with or without -t.
oss << "c->statp = & time_" << v->basest()->name << ";" << endl;
+ v->print_dupe_stamp (oss);
v->body->print(oss);
// Since the generated C changes based on whether or not the probe
@@ -3488,7 +3490,10 @@ c_unparser_assignment::visit_symbol (symbol *e)
void
c_unparser::visit_target_symbol (target_symbol* e)
{
- throw semantic_error("cannot translate general target-symbol expression", e->tok);
+ if (!e->probe_context_var.empty())
+ o->line() << "l->" << e->probe_context_var;
+ else
+ throw semantic_error("cannot translate general cast expression", e->tok);
}
@@ -4481,7 +4486,7 @@ dump_unwindsyms (Dwfl_Module *m,
// In the future, we'll also care about data symbols.
int syments = dwfl_module_getsymtab(m);
- assert(syments);
+ dwfl_assert ("Getting symbol table for " + modname, syments >= 0);
//extract build-id from debuginfo file
int build_id_len = 0;
@@ -4527,6 +4532,15 @@ dump_unwindsyms (Dwfl_Module *m,
}
}
+ // Get the canonical path of the main file for comparison at runtime.
+ // When given directly by the user through -d or in case of the kernel
+ // name and path might differ. path should be used for matching.
+ // Use end as sanity check when resolving symbol addresses and to
+ // calculate size for .dynamic and .absolute sections.
+ const char *mainfile;
+ Dwarf_Addr start, end;
+ dwfl_module_info (m, NULL, &start, &end, NULL, NULL, &mainfile, NULL);
+
// Look up the relocation basis for symbols
int n = dwfl_module_relocations (m);
@@ -4536,15 +4550,17 @@ dump_unwindsyms (Dwfl_Module *m,
// XXX: unfortunate duplication with tapsets.cxx:emit_address()
typedef map<Dwarf_Addr,const char*> addrmap_t; // NB: plain map, sorted by address
- vector<string> seclist; // encountered relocation bases (section names)
+ vector<pair<string,unsigned> > seclist; // encountered relocation bases
+ // (section names and sizes)
map<unsigned, addrmap_t> addrmap; // per-relocation-base sorted addrmap
Dwarf_Addr extra_offset = 0;
- for (int i = 1 /* XXX: why not 0? */ ; i < syments; ++i)
+ for (int i = 0; i < syments; ++i)
{
GElf_Sym sym;
- const char *name = dwfl_module_getsym(m, i, &sym, NULL);
+ GElf_Word shndxp;
+ const char *name = dwfl_module_getsym(m, i, &sym, &shndxp);
if (name)
{
// NB: Yey, we found the kernel's _stext value.
@@ -4567,21 +4583,22 @@ dump_unwindsyms (Dwfl_Module *m,
clog << "Found kernel _stext extra offset 0x" << hex << extra_offset << dec << endl;
}
- // We only need the function symbols to identify kernel-mode
- // PC's, so we omit undefined or "fake" absolute addresses.
- // These fake absolute addresses occur in some older i386
- // kernels to indicate they are vDSO symbols, not real
- // functions in the kernel.
+ // We are only interested in "real" symbols.
+ // We omit symbols that have suspicious addresses (before base,
+ // or after end).
if ((GELF_ST_TYPE (sym.st_info) == STT_FUNC ||
GELF_ST_TYPE (sym.st_info) == STT_OBJECT) // PR10000: also need .data
- && !(sym.st_shndx == SHN_UNDEF || sym.st_shndx == SHN_ABS))
+ && !(sym.st_shndx == SHN_UNDEF // Value undefined,
+ || shndxp == (GElf_Word) -1 // in a non-allocated section,
+ || sym.st_value >= end // beyond current module,
+ || sym.st_value < base)) // before first section.
{
Dwarf_Addr sym_addr = sym.st_value;
+ Dwarf_Addr save_addr = sym_addr;
const char *secname = NULL;
if (n > 0) // only try to relocate if there exist relocation bases
{
- Dwarf_Addr save_addr = sym_addr;
int ki = dwfl_module_relocate_address (m, &sym_addr);
dwfl_assert ("dwfl_module_relocate_address", ki >= 0);
secname = dwfl_module_relocation_info (m, ki, NULL);
@@ -4599,6 +4616,16 @@ dump_unwindsyms (Dwfl_Module *m,
{
// This is a symbol within a (possibly relocatable)
// kernel image.
+
+ // We only need the function symbols to identify kernel-mode
+ // PC's, so we omit undefined or "fake" absolute addresses.
+ // These fake absolute addresses occur in some older i386
+ // kernels to indicate they are vDSO symbols, not real
+ // functions in the kernel. We also omit symbols that have
+ if (GELF_ST_TYPE (sym.st_info) == STT_FUNC
+ && sym.st_shndx == SHN_ABS)
+ continue;
+
secname = "_stext";
// NB: don't subtract session.sym_stext, which could be inconveniently NULL.
// Instead, sym_addr will get compensated later via extra_offset.
@@ -4624,10 +4651,31 @@ dump_unwindsyms (Dwfl_Module *m,
// Compute our section number
unsigned secidx;
for (secidx=0; secidx<seclist.size(); secidx++)
- if (seclist[secidx]==secname) break;
+ if (seclist[secidx].first==secname) break;
if (secidx == seclist.size()) // new section name
- seclist.push_back (secname);
+ {
+ // absolute, dynamic or kernel have just one relocation
+ // section, which covers the whole module address range.
+ unsigned size;
+ if (secidx == 0
+ && (n == 0
+ || (n == 1
+ && (strcmp(secname, ".dynamic") == 0
+ || strcmp(secname, "_stext") == 0))))
+ size = end - start;
+ else
+ {
+ Dwarf_Addr b;
+ Elf_Scn *scn;
+ GElf_Shdr *shdr, shdr_mem;
+ scn = dwfl_module_address_section (m, &save_addr, &b);
+ assert (scn != NULL);
+ shdr = gelf_getshdr(scn, &shdr_mem);
+ size = shdr->sh_size;
+ }
+ seclist.push_back (make_pair(secname,size));
+ }
(addrmap[secidx])[sym_addr] = name;
}
@@ -4658,10 +4706,10 @@ dump_unwindsyms (Dwfl_Module *m,
// There would be only a small benefit to warning. A user
// likely can't do anything about this; backtraces for the
// affected module would just get all icky heuristicy.
-#if 0
- c->session.print_warning ("No unwind data for " + modname
- + ", " + dwfl_errmsg (-1));
-#endif
+ // So only report in verbose mode.
+ if (c->session.verbose > 2)
+ c->session.print_warning ("No unwind data for " + modname
+ + ", " + dwfl_errmsg (-1));
}
for (unsigned secidx = 0; secidx < seclist.size(); secidx++)
@@ -4688,12 +4736,17 @@ dump_unwindsyms (Dwfl_Module *m,
}
c->output << "static struct _stp_section _stp_module_" << stpmod_idx<< "_sections[] = {\n";
+ // For the kernel, executables (ET_EXEC) or shared libraries (ET_DYN)
+ // there is just one section that covers the whole address space of
+ // the module. For kernel modules (ET_REL) there can be multiple
+ // sections that get relocated separately.
for (unsigned secidx = 0; secidx < seclist.size(); secidx++)
{
c->output << "{\n"
- << ".name = " << lex_cast_qstring(seclist[secidx]) << ",\n"
+ << ".name = " << lex_cast_qstring(seclist[secidx].first) << ",\n"
+ << ".size = 0x" << hex << seclist[secidx].second << dec << ",\n"
<< ".symbols = _stp_module_" << stpmod_idx << "_symbols_" << secidx << ",\n"
- << ".num_symbols = sizeof(_stp_module_" << stpmod_idx << "_symbols_" << secidx << ")/sizeof(struct _stp_symbol)\n"
+ << ".num_symbols = " << addrmap[secidx].size() << "\n"
<< "},\n";
}
c->output << "};\n";
@@ -4701,11 +4754,6 @@ dump_unwindsyms (Dwfl_Module *m,
c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n";
c->output << ".name = " << lex_cast_qstring (modname) << ", \n";
- // Get the canonical path of the main file for comparison at runtime.
- // When given directly by the user through -d or in case of the kernel
- // name and path might differ. path should be used for matching.
- const char *mainfile;
- dwfl_module_info (m, NULL, NULL, NULL, NULL, NULL, &mainfile, NULL);
mainfile = canonicalize_file_name(mainfile);
c->output << ".path = " << lex_cast_qstring (mainfile) << ",\n";
@@ -4840,7 +4888,8 @@ emit_symbol_data (systemtap_session& s)
{
NULL, /* dwfl_linux_kernel_find_elf, */
dwfl_standard_find_debuginfo,
- dwfl_offline_section_address,
+ NULL, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN.
+ dwfl_offline_section_address, */
(char **) & debuginfo_path
};
@@ -4955,6 +5004,8 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#define STP_OVERLOAD";
s.op->newline() << "#endif";
+ s.op->newline() << "#define STP_SKIP_BADVARS " << (s.skip_badvars ? 1 : 0);
+
if (s.bulk_mode)
s.op->newline() << "#define STP_BULKMODE";
@@ -4965,9 +5016,7 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#define STP_PERFMON";
s.op->newline() << "#include \"runtime.h\"";
- s.op->newline() << "#include \"regs.c\"";
s.op->newline() << "#include \"stack.c\"";
- s.op->newline() << "#include \"regs-ia64.c\"";
s.op->newline() << "#include \"stat.c\"";
s.op->newline() << "#include <linux/string.h>";
s.op->newline() << "#include <linux/timer.h>";
diff --git a/util.cxx b/util.cxx
index 68cc27f7..5fa7a5f2 100644
--- a/util.cxx
+++ b/util.cxx
@@ -20,13 +20,15 @@
#include <cerrno>
extern "C" {
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <fcntl.h>
#include <pwd.h>
-#include <unistd.h>
+#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
-#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
}
using namespace std;
@@ -275,4 +277,35 @@ git_revision(const string& path)
return revision;
}
+
+static pid_t spawned_pid = 0;
+
+// Runs a command with a saved PID, so we can kill it from the signal handler
+int
+stap_system(const char *command)
+{
+ const char * argv[] = { "sh", "-c", command, NULL };
+ int ret, status;
+
+ spawned_pid = 0;
+ ret = posix_spawn(&spawned_pid, "/bin/sh", NULL, NULL,
+ const_cast<char **>(argv), environ);
+ if (ret == 0)
+ {
+ if (waitpid(spawned_pid, &status, 0) == spawned_pid)
+ ret = WIFEXITED(status) ? WEXITSTATUS(status) : 128 + WTERMSIG(status);
+ else
+ ret = errno;
+ }
+ spawned_pid = 0;
+ return ret;
+}
+
+// Send a signal to our spawned command
+int
+kill_stap_spawn(int sig)
+{
+ return spawned_pid ? kill(spawned_pid, sig) : 0;
+}
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/util.h b/util.h
index d385be02..7c557049 100644
--- a/util.h
+++ b/util.h
@@ -13,6 +13,8 @@ void tokenize(const std::string& str, std::vector<std::string>& tokens,
std::string find_executable(const std::string& name);
const std::string cmdstr_quoted(const std::string& cmd);
std::string git_revision(const std::string& path);
+int stap_system(const char *command);
+int kill_stap_spawn(int sig);
// stringification generics