summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--HACKING12
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.in3
-rw-r--r--NEWS8
-rw-r--r--doc/.gitignore2
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.am4
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.in29
-rw-r--r--doc/langref.tex158
-rwxr-xr-xdtrace.in26
-rw-r--r--dwflpp.cxx275
-rw-r--r--dwflpp.h25
-rw-r--r--runtime/io.c9
-rw-r--r--runtime/regs.h20
-rw-r--r--runtime/staprun/relay_old.c6
-rw-r--r--runtime/sym.c58
-rw-r--r--runtime/sym.h2
-rw-r--r--runtime/syscall.h1
-rw-r--r--runtime/task_finder.c13
-rw-r--r--runtime/transport/control.c3
-rw-r--r--runtime/transport/ring_buffer.c10
-rw-r--r--runtime/transport/symbols.c2
-rw-r--r--runtime/transport/transport.c5
-rwxr-xr-xstap-server2
-rw-r--r--systemtap.spec17
-rw-r--r--tapset-itrace.cxx16
-rw-r--r--tapset-utrace.cxx4
-rw-r--r--tapset/nd_syscalls2.stp15
-rw-r--r--tapset/scheduler.stp6
-rw-r--r--tapset/syscalls2.stp12
-rw-r--r--tapsets.cxx698
-rwxr-xr-x[-rw-r--r--]testsuite/buildok/ipmib-all-probes.stp0
-rwxr-xr-x[-rw-r--r--]testsuite/buildok/linuxmib-all-probes.stp0
-rwxr-xr-x[-rw-r--r--]testsuite/buildok/tcpmib-all-probes.stp0
-rwxr-xr-xtestsuite/semko/nodwf07.stp2
-rwxr-xr-xtestsuite/semok/bz10475.stp7
-rw-r--r--testsuite/systemtap.base/sdt_misc.exp58
-rw-r--r--testsuite/systemtap.base/tracepoints.exp26
-rw-r--r--testsuite/systemtap.base/utrace_syscall_args.exp6
-rw-r--r--testsuite/systemtap.examples/check.exp40
-rw-r--r--testsuite/systemtap.examples/general/graphs.meta2
-rw-r--r--testsuite/systemtap.examples/index.html3
-rw-r--r--testsuite/systemtap.examples/index.txt8
-rw-r--r--testsuite/systemtap.examples/interrupt/scf.meta2
-rw-r--r--testsuite/systemtap.examples/io/disktop.meta2
-rw-r--r--testsuite/systemtap.examples/io/io_submit.meta2
-rw-r--r--testsuite/systemtap.examples/io/ioblktime.meta2
-rw-r--r--testsuite/systemtap.examples/io/iostat-scsi.meta14
-rwxr-xr-xtestsuite/systemtap.examples/io/iostat-scsi.stp19
-rw-r--r--testsuite/systemtap.examples/io/iostats.meta2
-rw-r--r--testsuite/systemtap.examples/io/iotime.meta2
-rw-r--r--testsuite/systemtap.examples/io/iotop.meta2
-rw-r--r--testsuite/systemtap.examples/io/traceio.meta2
-rw-r--r--testsuite/systemtap.examples/io/traceio2.meta2
-rw-r--r--testsuite/systemtap.examples/io/ttyspy.meta2
-rw-r--r--testsuite/systemtap.examples/keyword-index.html14
-rw-r--r--testsuite/systemtap.examples/keyword-index.txt26
-rw-r--r--testsuite/systemtap.examples/locks/bkl.meta2
-rw-r--r--testsuite/systemtap.examples/locks/bkl_stats.meta2
-rw-r--r--testsuite/systemtap.examples/memory/kmalloc-top.meta2
-rw-r--r--testsuite/systemtap.examples/memory/mmanonpage.meta3
-rw-r--r--testsuite/systemtap.examples/memory/mmfilepage.meta3
-rw-r--r--testsuite/systemtap.examples/memory/mmreclaim.meta3
-rw-r--r--testsuite/systemtap.examples/memory/mmwriteback.meta3
-rw-r--r--testsuite/systemtap.examples/memory/numa_faults.meta2
-rw-r--r--testsuite/systemtap.examples/memory/pfaults.meta2
-rw-r--r--testsuite/systemtap.examples/network/autofs4.meta3
-rw-r--r--testsuite/systemtap.examples/network/dropwatch.meta3
-rw-r--r--testsuite/systemtap.examples/network/nettop.meta2
-rw-r--r--testsuite/systemtap.examples/network/sk_stream_wait_memory.meta2
-rw-r--r--testsuite/systemtap.examples/network/socket-trace.meta2
-rw-r--r--testsuite/systemtap.examples/network/tcp_connections.meta2
-rw-r--r--testsuite/systemtap.examples/network/tcpdumplike.meta2
-rw-r--r--testsuite/systemtap.examples/process/chng_cpu.meta2
-rw-r--r--testsuite/systemtap.examples/process/errsnoop.meta2
-rw-r--r--testsuite/systemtap.examples/process/forktracker.meta2
-rw-r--r--testsuite/systemtap.examples/process/futexes.meta2
-rw-r--r--testsuite/systemtap.examples/process/migrate.meta2
-rw-r--r--testsuite/systemtap.examples/process/pf2.meta2
-rw-r--r--testsuite/systemtap.examples/process/schedtimes.meta3
-rw-r--r--testsuite/systemtap.examples/process/sig_by_pid.meta2
-rw-r--r--testsuite/systemtap.examples/process/sig_by_proc.meta2
-rw-r--r--testsuite/systemtap.examples/process/sigkill.meta2
-rw-r--r--testsuite/systemtap.examples/process/sigmon.meta2
-rw-r--r--testsuite/systemtap.examples/process/sleepingBeauties.meta2
-rw-r--r--testsuite/systemtap.examples/process/sleeptime.meta2
-rw-r--r--testsuite/systemtap.examples/process/syscalls_by_pid.meta2
-rw-r--r--testsuite/systemtap.examples/process/syscalls_by_proc.meta2
-rw-r--r--testsuite/systemtap.examples/process/wait4time.meta2
-rw-r--r--testsuite/systemtap.examples/profiling/functioncallcount.meta2
-rw-r--r--testsuite/systemtap.examples/profiling/thread-times.meta2
-rw-r--r--testsuite/systemtap.examples/profiling/timeout.meta2
-rw-r--r--testsuite/systemtap.examples/profiling/topsys.meta2
-rw-r--r--testsuite/systemtap.exelib/exelib.exp12
-rw-r--r--testsuite/systemtap.exelib/libmarkunamestack.stp72
-rw-r--r--testsuite/systemtap.exelib/libmarkunamestack.tcl104
-rw-r--r--testsuite/systemtap.syscall/syscall.exp24
-rwxr-xr-xtestsuite/systemtap.syscall/test.tcl21
-rw-r--r--translate.cxx41
-rw-r--r--translate.h2
-rw-r--r--util.h12
100 files changed, 1363 insertions, 693 deletions
diff --git a/HACKING b/HACKING
index 5a1b86bf..24986a9e 100644
--- a/HACKING
+++ b/HACKING
@@ -118,3 +118,15 @@ the <systemtap@sources.redhat.com> mailing list.
Proposed changes to these guidelines should be discussed on the
mailing list.
+
+- git basics
+
+ git clone ssh://sources.redhat.com/git/systemtap.git
+ # build ; hack hack hack; test
+ git commit # to your local repository, add nice commit message
+ git pull # to make sure your copy is up to date & merged
+ # last minute rebuild; retest
+ git rebase origin/master # clean git commit of merge history
+ git diff origin/master # final visual check
+ git push # to the central one
+
diff --git a/Makefile.am b/Makefile.am
index a4a828a6..a838e01a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -272,7 +272,6 @@ distclean-local:
uninstall-local:
rm -rf $(DESTDIR)$(pkgdatadir)
- rm -rf $(DESTDIR)$(libexecdir)/$(PACKAGE)
rm -rf $(DESTDIR)$(libdir)/$(PACKAGE)
-rm -rf $(DESTDIR)$(localstatedir)/cache/$(PACKAGE)
@list='$(EXAMPLE_SRC)'; for f in $$list; do p=`basename $$f`; \
@@ -288,7 +287,7 @@ uninstall-local:
rm -f "$(SAMPLE_INSTALL_DIR)/$$p"; \
done
rm -rf $(DESTDIR)$(sysconfdir)/systemtap
-# XXX: leaves behind man pages
+ rm -rf $(DESTDIR)$(docdir)/examples
SUBDIRS = doc grapher
DIST_SUBDIRS = testsuite $(SUBDIRS)
diff --git a/Makefile.in b/Makefile.in
index 6891948b..91eaf4dc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -427,7 +427,6 @@ LDADD =
EXAMPLE_SOURCE_DIR = $(srcdir)/testsuite/systemtap.examples
EXAMPLE_META_FILES = $(EXAMPLE_SOURCE_DIR)/*/*.meta
TEST_COV_DIR = coverage
-# XXX: leaves behind man pages
SUBDIRS = doc grapher
DIST_SUBDIRS = testsuite $(SUBDIRS)
@@ -1816,7 +1815,6 @@ distclean-local:
uninstall-local:
rm -rf $(DESTDIR)$(pkgdatadir)
- rm -rf $(DESTDIR)$(libexecdir)/$(PACKAGE)
rm -rf $(DESTDIR)$(libdir)/$(PACKAGE)
-rm -rf $(DESTDIR)$(localstatedir)/cache/$(PACKAGE)
@list='$(EXAMPLE_SRC)'; for f in $$list; do p=`basename $$f`; \
@@ -1832,6 +1830,7 @@ uninstall-local:
rm -f "$(SAMPLE_INSTALL_DIR)/$$p"; \
done
rm -rf $(DESTDIR)$(sysconfdir)/systemtap
+ rm -rf $(DESTDIR)$(docdir)/examples
check-local:
SRCDIR=`cd $(srcdir); pwd`; \
diff --git a/NEWS b/NEWS
index 0b170732..e0c888f2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
* What's new
+- Memory consumption for scripts involving many uprobes has been
+ dramatically reduced.
+
- The preprocessor now supports || and && in the conditions.
%( arch == "x86_64" || arch == "ia64" %: ... %)
@@ -68,6 +71,11 @@
SYSTEMTAP_RUNTIME, SYSTEMTAP_TAPSET, SYSTEMTAP_DEBUGINFO_PATH
- nss and nss-tools are required to use this feature.
+- A new experimental transport mechanism, using ftrace's ring_buffer,
+ has been added. This may become the default transport mechanism in
+ future versions of systemtap. To test this new transport mechanism,
+ define 'STP_USE_RING_BUFFER'.
+
* What's new in version 0.9.9
- Systemwide kernel .function.return (kretprobe) maxactive defaults may
diff --git a/doc/.gitignore b/doc/.gitignore
index d8a93302..23d43673 100644
--- a/doc/.gitignore
+++ b/doc/.gitignore
@@ -6,3 +6,5 @@
*.out
*.pdf
*.toc
+*.dvi
+_region_.*
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.am b/doc/SystemTap_Tapset_Reference/Makefile.am
index 30c4ffef..4adba34e 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.am
+++ b/doc/SystemTap_Tapset_Reference/Makefile.am
@@ -57,3 +57,7 @@ endif
$(MKDIR_P) $(HTML_INSTALL_DIR)
$(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR)
endif
+
+CLEANFILES=tapsets.xml stamp-* $(PDFDOCS)
+clean-local:
+ rm -rf man3 tapsets
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in
index a7424ad7..86a112c2 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.in
+++ b/doc/SystemTap_Tapset_Reference/Makefile.in
@@ -181,6 +181,7 @@ HTML_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap/tapsets
SRCTREE = $(abs_top_srcdir)/
DOCPROC = $(abs_builddir)/docproc
@BUILD_PDFREFDOCS_TRUE@PDFDOCS = tapsets.pdf
+CLEANFILES = tapsets.xml stamp-* $(PDFDOCS)
all: all-am
.SUFFIXES:
@@ -338,6 +339,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -348,7 +350,8 @@ maintainer-clean-generic:
@BUILD_REFDOCS_FALSE@install-data-hook:
clean: clean-am
-clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+clean-am: clean-generic clean-local clean-noinstPROGRAMS \
+ mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
@@ -408,17 +411,17 @@ uninstall-am:
.MAKE: install-am install-data-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-noinstPROGRAMS ctags distclean distclean-compile \
- distclean-generic distclean-tags distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-data-hook install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-man install-pdf \
- install-pdf-am install-ps install-ps-am install-strip \
- installcheck installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
- uninstall-am
+ clean-local clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-data-hook install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am
@BUILD_REFDOCS_TRUE@all: $(PDFDOCS) stamp-htmldocs stamp-mandocs
@@ -452,6 +455,8 @@ uninstall-am:
@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man3/* $(MAN_INSTALL_DIR)
@BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(HTML_INSTALL_DIR)
@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR)
+clean-local:
+ rm -rf man3 tapsets
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/doc/langref.tex b/doc/langref.tex
index 3d08234d..aa583c2e 100644
--- a/doc/langref.tex
+++ b/doc/langref.tex
@@ -911,26 +911,46 @@ function, use \textbf{.statement} probes. Do not use wildcards in
to not register. Also, run statement probes in guru mode only.
-\begin{comment}
\subsection{Marker probes}
+\index{marker probes}
+This family of probe points connects to static probe markers inserted
+into the kernel or a module. These markers are special macro calls in
+the kernel that make probing faster and more reliable than with
+DWARF-based probes. DWARF debugging information is not required to
+use probe markers.
+
+Marker probe points begin with a \texttt{kernel} prefix which
+identifies the source of the symbol table used for finding
+markers. The suffix names the marker itself:
+\texttt{mark.("MARK")}. The marker name string, which can contain
+wildcard characters, is matched against the names given to the marker
+macros when the kernel or module is compiled. Optionally, you can
+specify \texttt{format("FORMAT")}. Specifying the marker format
+string allows differentiation between two markers with the same name
+but different marker format strings.
+
+The handler associated with a marker probe reads any optional
+parameters specified at the macro call site named \texttt{\$arg1}
+through \texttt{\$argNN}, where \texttt{NN} is the number of
+parameters supplied by the macro. Number and string parameters are
+passed in a type-safe manner.
+
+The marker format string associated with a marker is available in
+\texttt{\$format}. The marker name string is available in
+\texttt{\$name}.
+
+Here are the marker probe constructs:
+\begin{vindent}
+\begin{verbatim}
+kernel.mark("MARK")
+kernel.mark("MARK").format("FORMAT")
+\end{verbatim}
+\end{vindent}
+
+For more information about marker probes, see
+\url{http://sourceware.org/systemtap/wiki/UsingMarkers}.
+
-This family of probe points connects to static probe markers inserted into
-the kernel or a module. These markers are special macro calls in the kernel
-that make probing faster and more reliable than with DWARF-based probes.
-DWARF debugging information is not required to use probe markers.
-
-Marker probe points begin with a kernel or module(\char`\"{}\emph{name}\char`\"{})
-prefix, the same as DWARF probes. This prefix identifies the source of the
-symbol table used for finding markers. The suffix names the marker itself:
-mark(\char`\"{}\emph{name}\char`\"{}). The marker name string, which may
-contain wildcard characters, is matched against the names given to the marker
-macros when the kernel or module was compiled.
-
-The handler associated with a marker probe reads any optional parameters
-specified at the macro call site named \$arg1 through \$argNN, where NN is
-the number of parameters supplied by the macro. Number and string parameters
-are passed in a type-safe manner.
-\end{comment}
\subsection{Timer probes}
\index{timer probes}
@@ -1031,14 +1051,33 @@ of an \texttt{exit} function call, or an interruption from the user. In the
case of an shutdown triggered by error, \texttt{end} probes are not run.
-\subsubsection{begin and end probe sequence}
-\index{sequence}
-\texttt{begin} and \texttt{end} probes are specified with an optional sequence
-number that controls the order in which they are run. If no sequence number
-is provided, the sequence number defaults to zero and probes are run in the
-order that they occur in the script file. Sequence numbers may be either
-positive or negative, and are especially useful for tapset writers who want
-to do initialization in a \texttt{begin} probe. The following are examples.
+\subsubsection{error}
+\index{error}
+The \emph{error} probe point is similar to the end
+probe, except the probe handler runs when the session ends if an error
+occurred. In this case, an \texttt{end} probe is skipped, but each
+\texttt{error} probe is still attempted. You can use an
+\texttt{error} probe to clean up or perform a final action on script
+termination.
+
+Here is a simple example:
+\begin{vindent}
+\begin{verbatim}
+probe error { println ("Oops, errors occurred. Here's a report anyway.")
+ foreach (coin in mint) { println (coin) } }
+\end{verbatim}
+\end{vindent}
+
+
+\subsubsection{begin, end, and error probe sequence}
+\index{probe sequence}
+\texttt{begin}, \texttt{end}, and \texttt{error} probes can be
+specified with an optional sequence number that controls the order in
+which they are run. If no sequence number is provided, the sequence
+number defaults to zero and probes are run in the order that they
+occur in the script file. Sequence numbers may be either positive or
+negative, and are especially useful for tapset writers who want to do
+initialization in a \texttt{begin} probe. The following are examples.
\begin{vindent}
\begin{verbatim}
@@ -1088,9 +1127,74 @@ read\_counter is a function passed to the handle for a perfmon probe. It
returns the current count for the event.
\end{comment}
-\section{Language elements\label{sec:Language-Elements}}
+\subsection{Pointer typecasting}
+\index{Pointer typecasting}
+
+\emph{Typecasting} is supported using the \texttt{@cast()} operator. A
+script can define a pointer type for a \emph{long} value, then access
+type members using the same syntax as with \texttt{\$target}
+variables. After a pointer is saved into a script integer variable,
+the translator loses the necessary type information to access members
+from that pointer. The \texttt{@cast()} operator tells the translator
+how to read a pointer.
+
+The following statement interprets \texttt{p} as a pointer to a struct
+or union named \texttt{type\_name} and dereferences the
+\texttt{member} value:
+\begin{vindent}
+\begin{verbatim}
+@cast(p, "type_name"[, "module"])->member
+\end{verbatim}
+\end{vindent}
+
+The optional \texttt{module} parameter tells the translator where to
+look for information about that type. You can specify multiple modules
+as a list with colon (\texttt{:}) separators. If you do not specify
+the module parameter, the translator defaults to either the probe
+module for dwarf probes or to \textit{kernel} for functions and all
+other probe types.
+The following statement retrieves the parent PID from a kernel
+task\_struct:
+\begin{vindent}
+\begin{verbatim}
+@cast(pointer, "task_struct", "kernel")->parent->tgid
+\end{verbatim}
+\end{vindent}
+The translator can create its own module with type information from a
+header surrounded by angle brackets (\texttt{< >}) if normal debugging
+information is not available. For kernel headers, prefix it with
+\texttt{kernel} to use the appropriate build system. All other
+headers are built with default GCC parameters into a user module. The
+following statements are examples.
+\begin{vindent}
+\begin{verbatim}
+@cast(tv, "timeval", "<sys/time.h>")->tv_sec
+@cast(task, "task_struct", "kernel<linux/sched.h>")->tgid
+\end{verbatim}
+\end{vindent}
+
+In guru mode, the translator allows scripts to assign new values to
+members of typecasted pointers.
+
+Typecasting is also useful in the case of \texttt{void*} members whose
+type might be determinable at run time.
+\begin{vindent}
+\begin{verbatim}
+probe foo {
+ if ($var->type == 1) {
+ value = @cast($var->data, "type1")->bar
+ } else {
+ value = @cast($var->data, "type2")->baz
+ }
+ print(value)
+}
+\end{verbatim}
+\end{vindent}
+
+
+\section{Language elements\label{sec:Language-Elements}}
\subsection{Identifiers}
\index{identifiers}
\emph{Identifiers} are used to name variables and functions. They are an
diff --git a/dtrace.in b/dtrace.in
index 96a10b3a..98783604 100755
--- a/dtrace.in
+++ b/dtrace.in
@@ -17,9 +17,17 @@ from subprocess import call
from tempfile import mkstemp
class provider:
+ semaphores_def = "\n"
+ # is the type a basic scalar type?
+ def basic_type(self, arg):
+ basic_types = [ "int","int*","long","long*","short","short int","unsigned long","char","char*","float","double" ]
+ split_arg = arg.rsplit(None,1)
+ return (split_arg[0].strip() in basic_types) & (arg.find("[") == -1)
def typedef_append(self, typedefs,this_probe,arg,c):
if (add_typedefs):
split_arg = arg.rsplit(None,1)
+ if (self.basic_type(arg)):
+ return typedefs
type_name = " %s_arg%d" % (this_probe.replace("__","_"),c)
if (len(split_arg) > 1):
typedefs += ("typedef " + arg.replace(" " + split_arg[1].split("[")[0].lstrip("*"),type_name).strip() + "; ")
@@ -28,11 +36,16 @@ class provider:
typedefs += ("typedef " + arg.strip() + type_name + "; ")
typedefs += (type_name + type_name + "_v;\n")
return typedefs
+ def semaphore_def_append(self, this_probe):
+ self.semaphores_def += "__extension__ long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe)
+ def semaphore_def_write(self, file):
+ file.write(self.semaphores_def)
def generate(self, provider, header, add_typedefs):
have_provider = False
self.f = open(provider)
self.h = open(header,mode='w')
self.h.write("/* Generated by the Systemtap dtrace wrapper */\n")
+ self.h.write("\n#define STAP_HAS_SEMAPHORES 1\n\n")
self.h.write("\n#include <sys/sdt.h>\n\n")
in_comment = False
typedefs = ""
@@ -64,6 +77,7 @@ class provider:
arg = ""
i = 0
c = 0
+ self.semaphore_def_append (this_probe)
while (i < len(args)):
if (args[i:i+1] == ","):
args_string = ('%s %s,' % (args_string, arg.strip()))
@@ -91,7 +105,8 @@ class provider:
stap_str = stap_str + ",arg%s" % (i);
i += 1
self.h.write ('/* %s (%s) */\n' % (this_probe_canon,args_string))
- self.h.write ('#define %s_ENABLED() 1\n' % this_probe_canon)
+ self.h.write ('#define %s_ENABLED() %s_semaphore\n' % (this_probe_canon,this_probe))
+ self.h.write ("__extension__ extern long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe))
self.h.write (define_str + ") \\\n")
self.h.write (stap_str + ")\n\n")
elif (line.find("}") != -1 and have_provider):
@@ -187,12 +202,19 @@ if (build_header):
providers.generate(s_filename, filename + h_ext, add_typedefs)
elif (build_source):
(basename,ext) = os.path.splitext(s_filename)
+
+ # create for semaphore_def_write
+ providers = provider()
+ (d,fn) = mkstemp(suffix=".h")
+ providers.generate(s_filename, fn, add_typedefs)
+ os.remove(fn)
+
(d,fn) = mkstemp(suffix=".c")
f = open(fn,mode='w')
f.write("static __dtrace () {}\n")
+ providers.semaphore_def_write(f)
f.close()
call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"], shell=False)
os.remove(fn)
if (use_cpp):
os.remove(s_filename)
-
diff --git a/dwflpp.cxx b/dwflpp.cxx
index 2437630e..dcf4182d 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -56,6 +56,10 @@ extern "C" {
}
+// debug flag to compare to the uncached version from libdw
+// #define DEBUG_DWFLPP_GETSCOPES 1
+
+
using namespace std;
using namespace __gnu_cxx;
@@ -66,8 +70,7 @@ static string TOK_KERNEL("kernel");
dwflpp::dwflpp(systemtap_session & session, const string& name, bool kernel_p):
sess(session), module(NULL), module_bias(0), mod_info(NULL),
module_start(0), module_end(0), cu(NULL), dwfl(NULL),
- module_dwarf(NULL), function(NULL), blacklist_enabled(false),
- pc_cached_scopes(0), num_cached_scopes(0), cached_scopes(NULL)
+ module_dwarf(NULL), function(NULL), blacklist_enabled(false)
{
if (kernel_p)
setup_kernel(name);
@@ -83,8 +86,7 @@ dwflpp::dwflpp(systemtap_session & session, const string& name, bool kernel_p):
dwflpp::dwflpp(systemtap_session & session, const vector<string>& names):
sess(session), module(NULL), module_bias(0), mod_info(NULL),
module_start(0), module_end(0), cu(NULL), dwfl(NULL),
- module_dwarf(NULL), function(NULL), blacklist_enabled(false),
- pc_cached_scopes(0), num_cached_scopes(0), cached_scopes(NULL)
+ module_dwarf(NULL), function(NULL), blacklist_enabled(false)
{
setup_user(names);
}
@@ -92,23 +94,11 @@ dwflpp::dwflpp(systemtap_session & session, const vector<string>& names):
dwflpp::~dwflpp()
{
- free(cached_scopes);
-
- for (module_cu_cache_t::iterator it = module_cu_cache.begin();
- it != module_cu_cache.end(); ++it)
- delete it->second;
-
- for (mod_cu_function_cache_t::iterator it = cu_function_cache.begin();
- it != cu_function_cache.end(); ++it)
- delete it->second;
-
- for (cu_inl_function_cache_t::iterator it = cu_inl_function_cache.begin();
- it != cu_inl_function_cache.end(); ++it)
- delete it->second;
-
- for (mod_cu_type_cache_t::iterator it = global_alias_cache.begin();
- it != global_alias_cache.end(); ++it)
- delete it->second;
+ delete_map(module_cu_cache);
+ delete_map(cu_function_cache);
+ delete_map(cu_inl_function_cache);
+ delete_map(global_alias_cache);
+ delete_map(cu_die_parent_cache);
if (dwfl)
dwfl_end(dwfl);
@@ -185,9 +175,6 @@ dwflpp::focus_on_cu(Dwarf_Die * c)
// Reset existing pointers and names
function_name.clear();
function = NULL;
-
- free(cached_scopes);
- cached_scopes = NULL;
}
@@ -591,6 +578,178 @@ dwflpp::iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void *
}
+void
+dwflpp::cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die)
+{
+ // Record and recurse through DIEs we care about
+ Dwarf_Die child, import;
+ if (dwarf_child(die, &child) == 0)
+ do
+ {
+ switch (dwarf_tag (&child))
+ {
+ // normal tags to recurse
+ case DW_TAG_compile_unit:
+ case DW_TAG_module:
+ case DW_TAG_lexical_block:
+ case DW_TAG_with_stmt:
+ case DW_TAG_catch_block:
+ case DW_TAG_try_block:
+ case DW_TAG_entry_point:
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ parents->insert(make_pair(child.addr, *die));
+ cache_die_parents(parents, &child);
+ break;
+
+ // record only, nothing to recurse
+ case DW_TAG_label:
+ parents->insert(make_pair(child.addr, *die));
+ break;
+
+ // imported dies should be followed
+ case DW_TAG_imported_unit:
+ if (dwarf_attr_die(&child, DW_AT_import, &import))
+ {
+ parents->insert(make_pair(import.addr, *die));
+ cache_die_parents(parents, &import);
+ }
+ break;
+
+ // nothing to do for other tags
+ default:
+ break;
+ }
+ }
+ while (dwarf_siblingof(&child, &child) == 0);
+}
+
+
+cu_die_parent_cache_t*
+dwflpp::get_die_parents()
+{
+ assert (cu);
+
+ cu_die_parent_cache_t *& parents = cu_die_parent_cache[cu->addr];
+ if (!parents)
+ {
+ parents = new cu_die_parent_cache_t;
+ cache_die_parents(parents, cu);
+ if (sess.verbose > 4)
+ clog << "die parent cache " << module_name << ":" << cu_name()
+ << " size " << parents->size() << endl;
+ }
+ return parents;
+}
+
+
+vector<Dwarf_Die>
+dwflpp::getscopes_die(Dwarf_Die* die)
+{
+ cu_die_parent_cache_t *parents = get_die_parents();
+
+ vector<Dwarf_Die> scopes;
+ Dwarf_Die *scope = die;
+ cu_die_parent_cache_t::iterator it;
+ do
+ {
+ scopes.push_back(*scope);
+ it = parents->find(scope->addr);
+ scope = &it->second;
+ }
+ while (it != parents->end());
+
+#ifdef DEBUG_DWFLPP_GETSCOPES
+ Dwarf_Die *dscopes = NULL;
+ int nscopes = dwarf_getscopes_die(die, &dscopes);
+
+ assert(nscopes == (int)scopes.size());
+ for (unsigned i = 0; i < scopes.size(); ++i)
+ assert(scopes[i].addr == dscopes[i].addr);
+ free(dscopes);
+#endif
+
+ return scopes;
+}
+
+
+std::vector<Dwarf_Die>
+dwflpp::getscopes(Dwarf_Die* die)
+{
+ cu_die_parent_cache_t *parents = get_die_parents();
+
+ vector<Dwarf_Die> scopes;
+
+ Dwarf_Die origin;
+ Dwarf_Die *scope = die;
+ cu_die_parent_cache_t::iterator it;
+ do
+ {
+ scopes.push_back(*scope);
+ if (dwarf_tag(scope) == DW_TAG_inlined_subroutine &&
+ dwarf_attr_die(scope, DW_AT_abstract_origin, &origin))
+ scope = &origin;
+
+ it = parents->find(scope->addr);
+ scope = &it->second;
+ }
+ while (it != parents->end());
+
+#ifdef DEBUG_DWFLPP_GETSCOPES
+ // there isn't an exact libdw equivalent, but if dwarf_getscopes on the
+ // entrypc returns the same first die, then all the scopes should match
+ Dwarf_Addr pc;
+ if (die_entrypc(die, &pc))
+ {
+ Dwarf_Die *dscopes = NULL;
+ int nscopes = dwarf_getscopes(cu, pc, &dscopes);
+ if (nscopes > 0 && dscopes[0].addr == die->addr)
+ {
+ assert(nscopes == (int)scopes.size());
+ for (unsigned i = 0; i < scopes.size(); ++i)
+ assert(scopes[i].addr == dscopes[i].addr);
+ }
+ free(dscopes);
+ }
+#endif
+
+ return scopes;
+}
+
+
+std::vector<Dwarf_Die>
+dwflpp::getscopes(Dwarf_Addr pc)
+{
+ // The die_parent_cache doesn't help us without knowing where the pc is
+ // contained, so we have to do this one the old fashioned way.
+
+ assert (cu);
+
+ vector<Dwarf_Die> scopes;
+
+ Dwarf_Die* dwarf_scopes;
+ int nscopes = dwarf_getscopes(cu, pc, &dwarf_scopes);
+ if (nscopes > 0)
+ {
+ scopes.assign(dwarf_scopes, dwarf_scopes + nscopes);
+ free(dwarf_scopes);
+ }
+
+#ifdef DEBUG_DWFLPP_GETSCOPES
+ // check that getscopes on the starting die gets the same result
+ if (!scopes.empty())
+ {
+ vector<Dwarf_Die> other = getscopes(&scopes[0]);
+ assert(scopes.size() == other.size());
+ for (unsigned i = 0; i < scopes.size(); ++i)
+ assert(scopes[i].addr == other[i].addr);
+ }
+#endif
+
+ return scopes;
+}
+
+
int
dwflpp::global_alias_caching_callback(Dwarf_Die *die, void *arg)
{
@@ -1025,9 +1184,8 @@ dwflpp::iterate_over_labels (Dwarf_Die *begin_die,
Dwarf_Addr stmt_addr;
if (dwarf_lowpc (&die, &stmt_addr) == 0)
{
- Dwarf_Die *scopes;
- int nscopes = dwarf_getscopes_die (&die, &scopes);
- if (nscopes > 1)
+ vector<Dwarf_Die> scopes = getscopes_die(&die);
+ if (scopes.size() > 1)
callback(current_function, name, file, dline,
&scopes[1], stmt_addr, q);
}
@@ -1412,11 +1570,13 @@ dwflpp::loc2c_emit_address (void *arg, struct obstack *pool,
void
-dwflpp::print_locals(Dwarf_Die *die, ostream &o)
+dwflpp::print_locals(vector<Dwarf_Die>& scopes, ostream &o)
{
+ // XXX Shouldn't this be walking up to outer scopes too?
+
// Try to get the first child of die.
Dwarf_Die child;
- if (dwarf_child (die, &child) == 0)
+ if (dwarf_child (&scopes[0], &child) == 0)
{
do
{
@@ -1441,34 +1601,19 @@ dwflpp::print_locals(Dwarf_Die *die, ostream &o)
Dwarf_Attribute *
-dwflpp::find_variable_and_frame_base (Dwarf_Die *scope_die,
+dwflpp::find_variable_and_frame_base (vector<Dwarf_Die>& scopes,
Dwarf_Addr pc,
string const & local,
const target_symbol *e,
Dwarf_Die *vardie,
Dwarf_Attribute *fb_attr_mem)
{
- Dwarf_Die *scopes;
- int nscopes = 0;
+ Dwarf_Die *scope_die = &scopes[0];
Dwarf_Attribute *fb_attr = NULL;
assert (cu);
- nscopes = dwarf_getscopes_cached (pc, &scopes);
- if (nscopes <= 0)
- {
- throw semantic_error ("unable to find any scopes containing "
- + lex_cast_hex(pc)
- + ((scope_die == NULL) ? ""
- : (string (" in ")
- + (dwarf_diename(scope_die) ?: "<unknown>")
- + "(" + (dwarf_diename(cu) ?: "<unknown>")
- + ")"))
- + " while searching for local '" + local + "'",
- e->tok);
- }
-
- int declaring_scope = dwarf_getscopevar (scopes, nscopes,
+ int declaring_scope = dwarf_getscopevar (&scopes[0], scopes.size(),
local.c_str(),
0, NULL, 0, 0,
vardie);
@@ -1491,17 +1636,19 @@ dwflpp::find_variable_and_frame_base (Dwarf_Die *scope_die,
* as returned by dwarf_getscopes for the address, starting with the
* declaring_scope that the variable was found in.
*/
- for (int inner = declaring_scope;
- inner < nscopes && fb_attr == NULL;
+ vector<Dwarf_Die> physcopes, *fbscopes = &scopes;
+ for (size_t inner = declaring_scope;
+ inner < fbscopes->size() && fb_attr == NULL;
++inner)
{
- switch (dwarf_tag (&scopes[inner]))
+ Dwarf_Die& scope = (*fbscopes)[inner];
+ switch (dwarf_tag (&scope))
{
default:
continue;
case DW_TAG_subprogram:
case DW_TAG_entry_point:
- fb_attr = dwarf_attr_integrate (&scopes[inner],
+ fb_attr = dwarf_attr_integrate (&scope,
DW_AT_frame_base,
fb_attr_mem);
break;
@@ -1511,11 +1658,12 @@ dwflpp::find_variable_and_frame_base (Dwarf_Die *scope_die,
* subroutine is inlined to find the appropriate frame base. */
if (declaring_scope != -1)
{
- nscopes = dwarf_getscopes_die (&scopes[inner], &scopes);
- if (nscopes == -1)
+ physcopes = getscopes_die(&scope);
+ if (physcopes.empty())
throw semantic_error ("unable to get die scopes for '" +
local + "' in an inlined subroutines",
e->tok);
+ fbscopes = &physcopes;
inner = 0; // zero is current scope, for look will increase.
declaring_scope = -1;
}
@@ -1569,7 +1717,8 @@ dwflpp::translate_location(struct obstack *pool,
/* Fall through. */
case 0: /* Shouldn't happen. */
- throw semantic_error ("not accessible at this address", e->tok);
+ throw semantic_error ("not accessible at this address ("
+ + lex_cast_hex(pc) + ")", e->tok);
default: /* Shouldn't happen. */
case -1:
@@ -2093,7 +2242,7 @@ dwflpp::express_as_string (string prelude,
string
-dwflpp::literal_stmt_for_local (Dwarf_Die *scope_die,
+dwflpp::literal_stmt_for_local (vector<Dwarf_Die>& scopes,
Dwarf_Addr pc,
string const & local,
const target_symbol *e,
@@ -2103,7 +2252,7 @@ dwflpp::literal_stmt_for_local (Dwarf_Die *scope_die,
Dwarf_Die vardie;
Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
- fb_attr = find_variable_and_frame_base (scope_die, pc, local, e,
+ fb_attr = find_variable_and_frame_base (scopes, pc, local, e,
&vardie, &fb_attr_mem);
if (sess.verbose>2)
@@ -2606,20 +2755,6 @@ dwflpp::literal_addr_to_sym_addr(Dwarf_Addr lit_addr)
return lit_addr;
}
-int
-dwflpp::dwarf_getscopes_cached (Dwarf_Addr pc, Dwarf_Die **scopes)
-{
- if (!cached_scopes || pc != pc_cached_scopes)
- {
- free(cached_scopes);
- cached_scopes = NULL;
- pc_cached_scopes = pc;
- num_cached_scopes = dwarf_getscopes(cu, pc, &cached_scopes);
- }
- *scopes = cached_scopes;
- return num_cached_scopes;
-}
-
/* Returns the call frame address operations for the given program counter
* in the libdw address space.
*/
diff --git a/dwflpp.h b/dwflpp.h
index 74a3ae00..d379b265 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -65,6 +65,12 @@ typedef unordered_map<void*, cu_function_cache_t*> mod_cu_function_cache_t;
// inline function die -> instance die[]
typedef unordered_map<void*, std::vector<Dwarf_Die>*> cu_inl_function_cache_t;
+// die -> parent die
+typedef unordered_map<void*, Dwarf_Die> cu_die_parent_cache_t;
+
+// cu die -> (die -> parent die)
+typedef unordered_map<void*, cu_die_parent_cache_t*> mod_cu_die_parent_cache_t;
+
typedef std::vector<func_info> func_info_map_t;
typedef std::vector<inline_instance_info> inline_instance_map_t;
@@ -201,6 +207,10 @@ struct dwflpp
void iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * arg),
void * data);
+ std::vector<Dwarf_Die> getscopes_die(Dwarf_Die* die);
+ std::vector<Dwarf_Die> getscopes(Dwarf_Die* die);
+ std::vector<Dwarf_Die> getscopes(Dwarf_Addr pc);
+
Dwarf_Die *declaration_resolve(const char *name);
mod_cu_function_cache_t cu_function_cache;
@@ -245,7 +255,7 @@ struct dwflpp
bool die_has_pc (Dwarf_Die & die, Dwarf_Addr pc);
- std::string literal_stmt_for_local (Dwarf_Die *scope_die,
+ std::string literal_stmt_for_local (std::vector<Dwarf_Die>& scopes,
Dwarf_Addr pc,
std::string const & local,
const target_symbol *e,
@@ -292,6 +302,10 @@ private:
cu_inl_function_cache_t cu_inl_function_cache;
void cache_inline_instances (Dwarf_Die* die);
+ mod_cu_die_parent_cache_t cu_die_parent_cache;
+ void cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die);
+ cu_die_parent_cache_t *get_die_parents();
+
/* The global alias cache is used to resolve any DIE found in a
* module that is stubbed out with DW_AT_declaration with a defining
* DIE found in a different module. The current assumption is that
@@ -317,10 +331,10 @@ private:
static void loc2c_emit_address (void *arg, struct obstack *pool,
Dwarf_Addr address);
- void print_locals(Dwarf_Die *die, std::ostream &o);
+ void print_locals(std::vector<Dwarf_Die>& scopes, std::ostream &o);
void print_members(Dwarf_Die *vardie, std::ostream &o);
- Dwarf_Attribute *find_variable_and_frame_base (Dwarf_Die *scope_die,
+ Dwarf_Attribute *find_variable_and_frame_base (std::vector<Dwarf_Die>& scopes,
Dwarf_Addr pc,
std::string const & local,
const target_symbol *e,
@@ -374,11 +388,6 @@ private:
void build_blacklist();
std::string get_blacklist_section(Dwarf_Addr addr);
- Dwarf_Addr pc_cached_scopes;
- int num_cached_scopes;
- Dwarf_Die *cached_scopes;
- int dwarf_getscopes_cached (Dwarf_Addr pc, Dwarf_Die **scopes);
-
// Returns the call frame address operations for the given program counter.
Dwarf_Op *get_cfa_ops (Dwarf_Addr pc);
diff --git a/runtime/io.c b/runtime/io.c
index 687926fd..0136aae5 100644
--- a/runtime/io.c
+++ b/runtime/io.c
@@ -32,7 +32,7 @@ static void _stp_vlog (enum code type, const char *func, int line, const char *f
int start = 0;
if (type == DBUG) {
- start = _stp_snprintf(buf, STP_LOG_BUF_LEN, "\033[36m%s:%d:\033[0m ", func, line);
+ start = _stp_snprintf(buf, STP_LOG_BUF_LEN, "%s:%d: ", func, line);
} else if (type == WARN) {
strcpy (buf, WARN_STRING);
start = sizeof(WARN_STRING) - 1;
@@ -49,12 +49,19 @@ static void _stp_vlog (enum code type, const char *func, int line, const char *f
buf[num + start] = '\0';
}
+#ifdef STAP_DEBUG_PRINTK
+ if (type == DBUG) printk (KERN_DEBUG "%s", buf);
+ else if (type == WARN) printk (KERN_WARNING "%s", buf);
+ else if (type == ERROR) printk (KERN_ERR "%s", buf);
+ else printk (KERN_INFO "%s", buf);
+#else
if (type != DBUG)
_stp_ctl_write(STP_OOB_DATA, buf, start + num + 1);
else {
_stp_print(buf);
_stp_print_flush();
}
+#endif
}
put_cpu();
}
diff --git a/runtime/regs.h b/runtime/regs.h
index d80cdf0a..dc6b50af 100644
--- a/runtime/regs.h
+++ b/runtime/regs.h
@@ -12,53 +12,61 @@
#define _REGS_H_
#if defined (STAPCONF_X86_UNIREGS) && (defined (__x86_64__) || defined (__i386__))
+
#define REG_IP(regs) regs->ip
-#define REG_IP_LVALUE 1
#define REG_SP(regs) regs->sp
#define REG_FP(regs) regs->bp
#elif defined (__x86_64__)
#define REG_IP(regs) regs->rip
-#define REG_IP_LVALUE 1
#define REG_SP(regs) regs->rsp
#elif defined (__i386__)
#define REG_IP(regs) regs->eip
-#define REG_IP_LVALUE 1
#define REG_SP(regs) regs->esp
#define REG_FP(regs) regs->ebp
#elif defined (__ia64__)
+
#define REG_IP(regs) ((regs)->cr_iip +ia64_psr(regs)->ri)
#define REG_SP(regs) ((regs)->r12)
+#define SET_REG_IP(regs, x) \
+ (((regs)->cr_iip = (x) & ~3UL), (ia64_psr(regs)->ri = (x) & 3UL))
+
#elif defined (__powerpc64__)
#define REG_IP(regs) regs->nip
-#define REG_IP_LVALUE 1
#define REG_SP(regs) regs->gpr[1]
#define REG_LINK(regs) regs->link
#elif defined (__arm__)
#define REG_IP(regs) regs->ARM_pc
-#define REG_IP_LVALUE 1
#define REG_SP(regs) regs->ARM_sp
#define REG_LINK(regs) regs->ARM_lr
#elif defined (__s390__) || defined (__s390x__)
+
#ifndef __s390x__
#define PSW_ADDR_AMODE 0x80000000UL
+#define PSW_ADDR_INSN 0x7FFFFFFFUL
#else /* __s390x__ */
#define PSW_ADDR_AMODE 0x0000000000000000UL
+#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
#endif /* __s390x__ */
-#define REG_IP(regs) (((regs)->psw.addr) | PSW_ADDR_AMODE)
+#define REG_IP(regs) (((regs)->psw.addr) & PSW_ADDR_INSN)
#define REG_SP(regs) (regs)->gprs[15]
+#define SET_REG_IP(regs,x) (regs)->psw.addr = (x) | PSW_ADDR_AMODE
#else
#error "Unimplemented architecture"
#endif
+#ifndef SET_REG_IP
+#define SET_REG_IP(regs, x) REG_IP(regs) = x
+#endif
+
#endif /* _REGS_H_ */
diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c
index 71d8acee..0254173f 100644
--- a/runtime/staprun/relay_old.c
+++ b/runtime/staprun/relay_old.c
@@ -110,7 +110,8 @@ static int open_oldoutfile(int fnum, int cpu, int remove_file)
perr("Couldn't open output file %s", buf);
return -1;
}
- if (set_clexec(fileno(percpu_tmpfile[cpu])) < 0) {
+ out_fd[cpu] = fileno(percpu_tmpfile[cpu]);
+ if (set_clexec(out_fd[cpu]) < 0) {
perr("Couldn't clear exec bit of open output file %s", buf);
return -1;
}
@@ -181,7 +182,8 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p
perr("Couldn't open output file %s", tmp);
goto err2;
}
- if (set_clexec(fileno(percpu_tmpfile[cpu])) < 0) {
+ out_fd[cpu] = fileno(percpu_tmpfile[cpu]);
+ if (set_clexec(out_fd[cpu]) < 0) {
perr("Couldn't open output file %s", tmp);
goto err2;
}
diff --git a/runtime/sym.c b/runtime/sym.c
index dd2235cc..0baa1a5e 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -16,21 +16,6 @@
#include "string.c"
#include "task_finder_vma.c"
-/** @file sym.c
- * @addtogroup sym Symbolic Functions
- * Symbolic Lookup Functions
- * @{
- */
-
-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
session.unwindsyms_modules) for every user task path for which we
might need symbols or unwind info. */
@@ -259,7 +244,8 @@ static int _stp_module_check(void)
/* notes end address */
if (!strcmp(m->name, "kernel")) {
- notes_addr = m->build_id_offset;
+ notes_addr = _stp_module_relocate("kernel",
+ "_stext", m->build_id_offset);
base_addr = _stp_module_relocate("kernel",
"_stext", 0);
} else {
@@ -408,4 +394,44 @@ static void _stp_symbol_snprint(char *str, size_t len, unsigned long address,
}
/** @} */
+
+
+/** @file sym.c
+ * @addtogroup sym Symbolic Functions
+ * Symbolic Lookup Functions
+ * @{
+ */
+static void _stp_sym_init(void)
+{
+ // NB: it's too "early" to make this conditional on STP_NEED_VMA_TRACKER,
+ // since we're #included at the top of the generated module, before any
+ // tapset-induced #define's.
+#if defined(CONFIG_UTRACE)
+ static int initialized = 0;
+ static struct stap_task_finder_target vmcb = {
+ // NB: no .pid, no .procname filters here.
+ // This means that we get a system-wide mmap monitoring
+ // widget while the script is running. (The system-wideness may
+ // be restricted by stap -c or -x.) But this seems to
+ // be necessary if we want to to stack tracebacks through arbitrary
+ // shared libraries. XXX: There may be an optimization opportunity
+ // for executables (for which the main task-finder callback should be
+ // sufficient).
+ .mmap_callback = &_stp_tf_mmap_cb,
+ .munmap_callback = &_stp_tf_munmap_cb,
+ };
+ if (! initialized) {
+ int rc;
+ __stp_tf_vma_initialize();
+ rc = stap_register_task_finder_target (& vmcb);
+#ifdef DEBUG_TASK_FINDER_VMA
+ _stp_dbug(__FUNCTION__, __LINE__, "registered vmcb");
+#endif
+ (void) rc; // XXX
+ initialized = 1;
+ }
+#endif
+}
+
+
#endif /* _STP_SYM_C_ */
diff --git a/runtime/sym.h b/runtime/sym.h
index 262b1776..ca69345f 100644
--- a/runtime/sym.h
+++ b/runtime/sym.h
@@ -30,8 +30,6 @@ struct _stp_module {
struct _stp_section *sections;
unsigned num_sections;
- struct stap_task_finder_target *vmcb; /* PR10228 */
-
/* A pointer to the struct module. Note that we cannot */
/* trust this because as of 2.6.19, there are not yet */
/* any notifier hooks that will tell us when a module */
diff --git a/runtime/syscall.h b/runtime/syscall.h
index 38b523e1..786965f4 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -52,6 +52,7 @@
: __MREMAP_SYSCALL_NO_X86_64)
# else
#define MMAP_SYSCALL_NO(tsk) __MMAP_SYSCALL_NO_X86_64
+#define MMAP2_SYSCALL_NO(tsk) __MMAP2_SYSCALL_NO_X86_64
#define MPROTECT_SYSCALL_NO(tsk) __MPROTECT_SYSCALL_NO_X86_64
#define MUNMAP_SYSCALL_NO(tsk) __MUNMAP_SYSCALL_NO_X86_64
#define MREMAP_SYSCALL_NO(tsk) __MREMAP_SYSCALL_NO_X86_64
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 1a9a738a..6b50f1b9 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -45,18 +45,10 @@ static atomic_t __stp_attach_count = ATOMIC_INIT (0);
#define debug_task_finder_attach() (atomic_inc(&__stp_attach_count))
#define debug_task_finder_detach() (atomic_dec(&__stp_attach_count))
-#ifdef DEBUG_TASK_FINDER_PRINTK
-#define debug_task_finder_report() (printk(KERN_ERR \
- "%s:%d attach count: %d, inuse count: %d\n", \
- __FUNCTION__, __LINE__, \
- atomic_read(&__stp_attach_count), \
- atomic_read(&__stp_inuse_count)))
-#else
#define debug_task_finder_report() (_stp_dbug(__FUNCTION__, __LINE__, \
"attach count: %d, inuse count: %d\n", \
atomic_read(&__stp_attach_count), \
atomic_read(&__stp_inuse_count)))
-#endif /* !DEBUG_TASK_FINDER_PRINTK */
#else
#define debug_task_finder_attach() /* empty */
#define debug_task_finder_detach() /* empty */
@@ -1357,7 +1349,6 @@ stap_start_task_finder(void)
char *mmpath_buf;
uid_t tsk_euid;
- debug_task_finder_report();
mmpath_buf = _stp_kmalloc(PATH_MAX);
if (mmpath_buf == NULL) {
_stp_error("Unable to allocate space for path");
@@ -1443,7 +1434,7 @@ stap_start_task_finder(void)
#ifndef STP_PRIVILEGED
/* Make sure unprivileged users only probe their own threads. */
if (_stp_uid != tsk_euid) {
- if (tgt->pid != 0) {
+ if (tgt->pid != 0 || _stp_target) {
_stp_warn("Process %d does not belong to unprivileged user %d",
tsk->pid, _stp_uid);
}
@@ -1462,8 +1453,8 @@ stap_start_task_finder(void)
} while_each_thread(grp, tsk);
stf_err:
rcu_read_unlock();
-
_stp_kfree(mmpath_buf);
+ debug_task_finder_report(); // report at end for utrace engine counting
return rc;
}
diff --git a/runtime/transport/control.c b/runtime/transport/control.c
index 925a6768..0e18bb8b 100644
--- a/runtime/transport/control.c
+++ b/runtime/transport/control.c
@@ -173,6 +173,9 @@ static int _stp_ctl_send(int type, void *data, int len)
msleep(5);
if (err > 0)
wake_up_interruptible(&_stp_ctl_wq);
+ else
+ // printk instead of _stp_error since an error here means our transport is suspect
+ printk(KERN_ERR "ctl_send (type=%d len=%d) failed: %d\n", type, len, err);
dbug_trans(1, "returning %d\n", err);
return err;
}
diff --git a/runtime/transport/ring_buffer.c b/runtime/transport/ring_buffer.c
index 43448076..251d6ed9 100644
--- a/runtime/transport/ring_buffer.c
+++ b/runtime/transport/ring_buffer.c
@@ -162,7 +162,7 @@ _stp_event_to_user(struct ring_buffer_event *event, char __user *ubuf,
return -EFAULT;
}
- entry = (struct _stp_data_entry *)ring_buffer_event_data(event);
+ entry = ring_buffer_event_data(event);
if (entry == NULL) {
dbug_trans(1, "returning -EFAULT(2)\n");
return -EFAULT;
@@ -578,7 +578,7 @@ _stp_data_write_reserve(size_t size_request, void **entry)
if (event) {
ssize_t len;
- sde = (struct _stp_data_entry *)ring_buffer_event_data(event);
+ sde = ring_buffer_event_data(event);
if (sde->len < size_request)
size_request = sde->len;
_stp_ring_buffer_consume(iter);
@@ -605,7 +605,7 @@ _stp_data_write_reserve(size_t size_request, void **entry)
}
}
- sde = (struct _stp_data_entry *)ring_buffer_event_data(event);
+ sde = ring_buffer_event_data(event);
sde->len = size_request;
*entry = event;
@@ -620,7 +620,7 @@ static unsigned char *_stp_data_entry_data(void *entry)
if (event == NULL)
return NULL;
- sde = (struct _stp_data_entry *)ring_buffer_event_data(event);
+ sde = ring_buffer_event_data(event);
return sde->buf;
}
@@ -635,7 +635,7 @@ static int _stp_data_write_commit(void *entry)
#if defined(DEBUG_TRANS) && (DEBUG_TRANS >= 2)
{
- struct _stp_data_entry *sde = (struct _stp_data_entry *)ring_buffer_event_data(event);
+ struct _stp_data_entry *sde = ring_buffer_event_data(event);
char *last = sde->buf + (sde->len - 5);
dbug_trans2("commiting %.5s...%.5s\n", sde->buf, last);
}
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index 3e6a2fb1..a214d1f2 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -15,7 +15,7 @@
static void _stp_do_relocation(const char __user *buf, size_t count)
{
- struct _stp_msg_relocation msg;
+ static struct _stp_msg_relocation msg; /* by protocol, never concurrently used */
unsigned mi, si;
if (sizeof(msg) != count)
diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c
index 1d029e53..f5efce9f 100644
--- a/runtime/transport/transport.c
+++ b/runtime/transport/transport.c
@@ -31,8 +31,9 @@ static int _stp_ctl_attached = 0;
static pid_t _stp_target = 0;
static int _stp_probes_started = 0;
-// For now, disable transport version 3
-#if STP_TRANSPORT_VERSION == 3
+// For now, disable transport version 3 (unless STP_USE_RING_BUFFER is
+// defined).
+#if STP_TRANSPORT_VERSION == 3 && !defined(STP_USE_RING_BUFFER)
#undef STP_TRANSPORT_VERSION
#define STP_TRANSPORT_VERSION 2
#endif
diff --git a/stap-server b/stap-server
index a6539d44..3358bcf1 100755
--- a/stap-server
+++ b/stap-server
@@ -395,7 +395,7 @@ function package_response {
# Compress the server's temporary directory into a .zip archive.
(rm $zip_server && zip -r $zip_server `basename $tmpdir_server` > /dev/null) || \
- fatal "zip of request tree, $tmpdir_server, failed"
+ fatal "zip of server response tree, $tmpdir_server, failed"
}
# function: fatal [ MESSAGE ]
diff --git a/systemtap.spec b/systemtap.spec
index f4957200..ca355083 100644
--- a/systemtap.spec
+++ b/systemtap.spec
@@ -84,7 +84,7 @@ Summary: Instrumentation System Testsuite
Group: Development/System
License: GPLv2+
URL: http://sourceware.org/systemtap/
-Requires: systemtap systemtap-sdt-devel dejagnu
+Requires: systemtap systemtap-sdt-devel dejagnu which
%description testsuite
The testsuite allows testing of the entire SystemTap toolchain
@@ -97,11 +97,13 @@ License: GPLv2+
URL: http://sourceware.org/systemtap/
Requires: systemtap-runtime = %{version}-%{release}
Requires: avahi avahi-tools nss nss-tools mktemp
+Requires: zip unzip
%description client
-SystemTap client is the client component of an instrumentation
-system for systems running Linux 2.6. Developers can write
-instrumentation to collect data on the operation of the system.
+This is the remote script compilation client component of systemtap.
+It relies on a nearby compilation server to translate systemtap
+scripts to kernel objects, so a client workstation only needs the
+runtime, and not the compiler/etc toolchain.
%package server
Summary: Instrumentation System Server
@@ -110,11 +112,12 @@ License: GPLv2+
URL: http://sourceware.org/systemtap/
Requires: systemtap
Requires: avahi avahi-tools nss nss-tools mktemp
+Requires: zip unzip
%description server
-SystemTap server is the server component of an instrumentation
-system for systems running Linux 2.6. Developers can write
-instrumentation to collect data on the operation of the system.
+This is the remote script compilation server component of systemtap.
+It announces itself to local clients with avahi, and compiles systemtap
+scripts to kernel objects on their demand.
%package sdt-devel
Summary: Static probe support tools
diff --git a/tapset-itrace.cxx b/tapset-itrace.cxx
index dee2fe64..9fc59d42 100644
--- a/tapset-itrace.cxx
+++ b/tapset-itrace.cxx
@@ -299,10 +299,18 @@ register_tapset_itrace(systemtap_session& s)
match_node* root = s.pattern_root;
derived_probe_builder *builder = new itrace_builder();
- root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(builder);
- root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(builder);
- root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)->bind(builder);
- root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)->bind(builder);
+ root->bind_str(TOK_PROCESS)->bind(TOK_INSN)
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num(TOK_PROCESS)->bind(TOK_INSN)
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
+ ->allow_unprivileged()
+ ->bind(builder);
+ root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK)
+ ->allow_unprivileged()
+ ->bind(builder);
}
diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx
index 490af20f..22682776 100644
--- a/tapset-utrace.cxx
+++ b/tapset-utrace.cxx
@@ -1040,12 +1040,16 @@ register_tapset_utrace(systemtap_session& s)
->allow_unprivileged()
->bind(builder);
roots[i]->bind(TOK_THREAD)->bind(TOK_BEGIN)
+ ->allow_unprivileged()
->bind(builder);
roots[i]->bind(TOK_THREAD)->bind(TOK_END)
+ ->allow_unprivileged()
->bind(builder);
roots[i]->bind(TOK_SYSCALL)
+ ->allow_unprivileged()
->bind(builder);
roots[i]->bind(TOK_SYSCALL)->bind(TOK_RETURN)
+ ->allow_unprivileged()
->bind(builder);
}
}
diff --git a/tapset/nd_syscalls2.stp b/tapset/nd_syscalls2.stp
index 6e50d256..8b604f94 100644
--- a/tapset/nd_syscalls2.stp
+++ b/tapset/nd_syscalls2.stp
@@ -4134,10 +4134,23 @@ probe nd_syscall.ustat32 = kprobe.function("sys32_ustat") ?
dev = uint_arg(1)
argstr = sprintf("%d, %p", dev, pointer_arg(2))
}
+# Since 2.6.30 sys32_ustat is called compat_sys_ustat and is now asmlinkage.
+#asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u)
+probe nd_syscall.ustat32 = kprobe.function("compat_sys_ustat") ?
+{
+ name = "ustat"
+ // dev = $dev
+ // argstr = sprintf("%d, %p", $dev, $u)
+ // asmlinkage
+ asmlinkage()
+ dev = uint_arg(1)
+ argstr = sprintf("%d, %p", dev, pointer_arg(2))
+}
probe nd_syscall.ustat.return = kprobe.function("SyS_ustat").return ?,
kprobe.function("sys_ustat").return ?,
- kprobe.function("sys32_ustat").return ?
+ kprobe.function("sys32_ustat").return ?,
+ kprobe.function("compat_sys_ustat").return ?
{
name = "ustat"
retstr = returnstr(1)
diff --git a/tapset/scheduler.stp b/tapset/scheduler.stp
index d67e0310..3c3d504e 100644
--- a/tapset/scheduler.stp
+++ b/tapset/scheduler.stp
@@ -33,7 +33,7 @@ function __is_idle:long()
* idle - boolean indicating whether current is the idle process
*/
probe scheduler.cpu_off
- = kernel.function("context_switch")
+ = kernel.trace("sched_switch") !, kernel.function("context_switch")
{
task_prev = $prev
task_next = $next
@@ -122,9 +122,9 @@ probe scheduler.balance = kernel.function("idle_balance")? {}
*/
probe scheduler.ctxswitch =
%( arch != "x86_64" && arch != "ia64" %?
- kernel.function("__switch_to")
+ kernel.trace("sched_switch") !, kernel.function("__switch_to")
%:
- kernel.function("context_switch")
+ kernel.trace("sched_switch") !, kernel.function("context_switch")
%)
{
%( arch == "powerpc" %?
diff --git a/tapset/syscalls2.stp b/tapset/syscalls2.stp
index defc50a0..e2be10fc 100644
--- a/tapset/syscalls2.stp
+++ b/tapset/syscalls2.stp
@@ -3414,10 +3414,20 @@ probe syscall.ustat32 = kernel.function("sys32_ustat") ?
dev = $dev
argstr = sprintf("%d, %p", $dev, $u32p)
}
+# Since 2.6.30 sys32_ustat is compat_sys_ustat
+# Note that last argument changed name.
+#long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u)
+probe syscall.ustat32 = kernel.function("compat_sys_ustat") ?
+{
+ name = "ustat"
+ dev = $dev
+ argstr = sprintf("%d, %p", $dev, $u)
+}
probe syscall.ustat.return = kernel.function("SyS_ustat").return ?,
kernel.function("sys_ustat").return ?,
- kernel.function("sys32_ustat").return ?
+ kernel.function("sys32_ustat").return ?,
+ kernel.function("compat_sys_ustat").return ?
{
name = "ustat"
retstr = returnstr(1)
diff --git a/tapsets.cxx b/tapsets.cxx
index 053344cf..bd314345 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -351,11 +351,8 @@ struct dwarf_derived_probe: public derived_probe
bool access_vars;
void printsig (std::ostream &o) const;
- void join_group (systemtap_session& s);
+ virtual void join_group (systemtap_session& s);
void emit_probe_local_init(translator_output * o);
-
- string args;
- void saveargs(Dwarf_Die* scope_die);
void printargs(std::ostream &o) const;
// Pattern registration helpers.
@@ -369,42 +366,48 @@ struct dwarf_derived_probe: public derived_probe
dwarf_builder * dw,
bool unprivileged_ok_p = false);
static void register_patterns(systemtap_session& s);
+
+protected:
+ dwarf_derived_probe(probe *base,
+ probe_point *location,
+ Dwarf_Addr addr,
+ bool has_return):
+ derived_probe(base, location), addr(addr), has_return(has_return),
+ has_maxactive(0), maxactive_val(0), access_vars(false)
+ {}
+
+private:
+ string args;
+ void saveargs(dwarf_query& q, Dwarf_Die* scope_die);
};
-struct uprobe_derived_probe: public derived_probe
+struct uprobe_derived_probe: public dwarf_derived_probe
{
- bool return_p;
- string module; // * => unrestricted
int pid; // 0 => unrestricted
- string section; // empty => absolute address
- Dwarf_Addr address;
- // bool has_maxactive;
- // long maxactive_val;
uprobe_derived_probe (const string& function,
const string& filename,
int line,
const string& module,
- int pid,
const string& section,
Dwarf_Addr dwfl_addr,
Dwarf_Addr addr,
dwarf_query & q,
- Dwarf_Die* scope_die);
+ Dwarf_Die* scope_die):
+ dwarf_derived_probe(function, filename, line, module, section,
+ dwfl_addr, addr, q, scope_die), pid(0)
+ {}
// alternate constructor for process(PID).statement(ADDR).absolute
uprobe_derived_probe (probe *base,
probe_point *location,
int pid,
Dwarf_Addr addr,
- bool return_p);
+ bool has_return):
+ dwarf_derived_probe(base, location, addr, has_return), pid(pid)
+ {}
- string args;
- void saveargs(Dwarf_Die* scope_die);
- void printargs(std::ostream &o) const;
-
- void printsig (std::ostream &o) const;
void join_group (systemtap_session& s);
};
@@ -1003,7 +1006,7 @@ dwarf_query::add_probe_point(const string& funcname,
if (has_process)
{
results.push_back (new uprobe_derived_probe(funcname, filename, line,
- module, 0, reloc_section, addr, reloc_addr,
+ module, reloc_section, addr, reloc_addr,
*this, scope_die));
}
else
@@ -1604,11 +1607,8 @@ validate_module_elf (Dwfl_Module *mod, const char *name, base_query *q)
expect_machine2 = "x86_64";
break;
case EM_PPC:
- expect_machine = "ppc";
- if (! q->has_process) break; // 32-bit kernel/module
- /* FALLSTHROUGH */
case EM_PPC64:
- expect_machine2 = "ppc64";
+ expect_machine = "powerpc";
break;
case EM_S390: expect_machine = "s390"; break;
case EM_IA_64: expect_machine = "ia64"; break;
@@ -1764,7 +1764,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor
Dwarf_Addr addr;
block *add_block;
probe *add_probe;
- std::map<std::string, symbol *> return_ts_map;
+ map<std::string, symbol *> return_ts_map;
+ vector<Dwarf_Die> scopes;
bool visited;
dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a):
@@ -1773,6 +1774,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor
void visit_target_symbol_context (target_symbol* e);
void visit_target_symbol (target_symbol* e);
void visit_cast_op (cast_op* e);
+private:
+ vector<Dwarf_Die>& getscopes(target_symbol *e);
};
@@ -2113,10 +2116,8 @@ dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e)
void
dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
{
- Dwarf_Die *scopes;
- if (dwarf_getscopes_die (scope_die, &scopes) == 0)
+ if (null_die(scope_die))
return;
- auto_free free_scopes(scopes);
target_symbol *tsym = new target_symbol;
print_format* pf = new print_format;
@@ -2164,6 +2165,7 @@ dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
// non-.return probe: support $$parms, $$vars, $$locals
bool first = true;
Dwarf_Die result;
+ vector<Dwarf_Die> scopes = q.dw.getscopes_die(scope_die);
if (dwarf_child (&scopes[0], &result) == 0)
do
{
@@ -2285,7 +2287,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
}
else
{
- ec->code = q.dw.literal_stmt_for_local (scope_die,
+ ec->code = q.dw.literal_stmt_for_local (getscopes(e),
addr,
e->base_name.substr(1),
e,
@@ -2395,6 +2397,35 @@ dwarf_var_expanding_visitor::visit_cast_op (cast_op *e)
}
+vector<Dwarf_Die>&
+dwarf_var_expanding_visitor::getscopes(target_symbol *e)
+{
+ if (scopes.empty())
+ {
+ // If the address is at the beginning of the scope_die, we can do a fast
+ // getscopes from there. Otherwise we need to look it up by address.
+ Dwarf_Addr entrypc;
+ if (q.dw.die_entrypc(scope_die, &entrypc) && entrypc == addr)
+ scopes = q.dw.getscopes(scope_die);
+ else
+ scopes = q.dw.getscopes(addr);
+
+ if (scopes.empty())
+ throw semantic_error ("unable to find any scopes containing "
+ + lex_cast_hex(addr)
+ + ((scope_die == NULL) ? ""
+ : (string (" in ")
+ + (dwarf_diename(scope_die) ?: "<unknown>")
+ + "(" + (dwarf_diename(q.dw.cu) ?: "<unknown>")
+ + ")"))
+ + " while searching for local '"
+ + e->base_name.substr(1) + "'",
+ e->tok);
+ }
+ return scopes;
+}
+
+
struct dwarf_cast_query : public base_query
{
cast_op& e;
@@ -2702,16 +2733,25 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
module (module), section (section), addr (addr),
has_return (q.has_return),
has_maxactive (q.has_maxactive),
- maxactive_val (q.maxactive_val)
+ maxactive_val (q.maxactive_val),
+ access_vars(false)
{
- // Assert relocation invariants
- if (section == "" && dwfl_addr != addr) // addr should be absolute
- throw semantic_error ("missing relocation base against", q.base_loc->tok);
- if (section != "" && dwfl_addr == addr) // addr should be an offset
- throw semantic_error ("inconsistent relocation address", q.base_loc->tok);
-
- this->tok = q.base_probe->tok;
- this->access_vars = false;
+ if (q.has_process)
+ {
+ // We may receive probes on two types of ELF objects: ET_EXEC or ET_DYN.
+ // ET_EXEC ones need no further relocation on the addr(==dwfl_addr), whereas
+ // ET_DYN ones do (addr += run-time mmap base address). We tell these apart
+ // by the incoming section value (".absolute" vs. ".dynamic").
+ // XXX Assert invariants here too?
+ }
+ else
+ {
+ // Assert kernel relocation invariants
+ if (section == "" && dwfl_addr != addr) // addr should be absolute
+ throw semantic_error ("missing relocation base against", tok);
+ if (section != "" && dwfl_addr == addr) // addr should be an offset
+ throw semantic_error ("inconsistent relocation address", tok);
+ }
// XXX: hack for strange g++/gcc's
#ifndef USHRT_MAX
@@ -2719,7 +2759,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
#endif
// Range limit maxactive() value
- if (q.has_maxactive && (q.maxactive_val < 0 || q.maxactive_val > USHRT_MAX))
+ if (has_maxactive && (maxactive_val < 0 || maxactive_val > USHRT_MAX))
throw semantic_error ("maxactive value out of range [0,"
+ lex_cast(USHRT_MAX) + "]",
q.base_loc->tok);
@@ -2727,9 +2767,11 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
// Expand target variables in the probe body
if (!null_die(scope_die))
{
+ // XXX: user-space deref's for q.has_process!
dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr);
v.replace (this->body);
- this->access_vars = v.visited;
+ if (!q.has_process)
+ access_vars = v.visited;
// If during target-variable-expanding the probe, we added a new block
// of code, add it to the start of the probe.
@@ -2748,7 +2790,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
// Save the local variables for listing mode
if (q.sess.listing_mode_vars)
- saveargs(scope_die);
+ saveargs(q, scope_die);
// Reset the sole element of the "locations" vector as a
// "reverse-engineered" form of the incoming (q.base_loc) probe
@@ -2815,12 +2857,10 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
void
-dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
+dwarf_derived_probe::saveargs(dwarf_query& q, Dwarf_Die* scope_die)
{
- Dwarf_Die *scopes;
- if (!null_die(scope_die) && dwarf_getscopes_die (scope_die, &scopes) == 0)
+ if (null_die(scope_die))
return;
- auto_free free_scopes(scopes);
stringstream argstream;
string type_name;
@@ -2832,6 +2872,7 @@ dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
argstream << " $return:" << type_name;
Dwarf_Die arg;
+ vector<Dwarf_Die> scopes = q.dw.getscopes_die(scope_die);
if (dwarf_child (&scopes[0], &arg) == 0)
do
{
@@ -2918,12 +2959,21 @@ dwarf_derived_probe::register_patterns(systemtap_session& s)
register_function_and_statement_variants(root->bind(TOK_KERNEL), dw);
register_function_and_statement_variants(root->bind_str(TOK_MODULE), dw);
- root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(dw);
- root->bind(TOK_KERNEL)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw);
- root->bind_str(TOK_PROCESS)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw);
- register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw, false/*!unprivileged_ok_p*/);
- root->bind_str(TOK_PROCESS)->bind_str(TOK_MARK)->bind(dw);
- root->bind_str(TOK_PROCESS)->bind_num(TOK_MARK)->bind(dw);
+ root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)
+ ->bind(dw);
+ root->bind(TOK_KERNEL)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)
+ ->bind(dw);
+
+ register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw, true/*unprivileged_ok_p*/);
+ root->bind_str(TOK_PROCESS)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)
+ ->allow_unprivileged()
+ ->bind(dw);
+ root->bind_str(TOK_PROCESS)->bind_str(TOK_MARK)
+ ->allow_unprivileged()
+ ->bind(dw);
+ root->bind_str(TOK_PROCESS)->bind_num(TOK_MARK)
+ ->allow_unprivileged()
+ ->bind(dw);
}
void
@@ -3083,18 +3133,13 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
// Make it look like the IP is set as it wouldn't have been replaced
// by a breakpoint instruction when calling real probe handler. Reset
// IP regs on return, so we don't confuse kprobes. PR10458
- // But only for architectures where REG_IP is a proper lvalue. PR10491
- s.op->newline() << "#ifdef REG_IP_LVALUE";
s.op->newline() << "{";
s.op->indent(1);
s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
- s.op->newline() << "REG_IP(regs) = (unsigned long) inst->addr;";
+ s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->addr);";
s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
s.op->newline(-1) << "}";
- s.op->newline() << "#else";
- s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "#endif";
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
@@ -3122,18 +3167,13 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
// Make it look like the IP is set as it wouldn't have been replaced
// by a breakpoint instruction when calling real probe handler. Reset
// IP regs on return, so we don't confuse kprobes. PR10458
- // But only for architectures where REG_IP is a proper lvalue. PR10491
- s.op->newline() << "#ifdef REG_IP_LVALUE";
s.op->newline() << "{";
s.op->indent(1);
s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
- s.op->newline() << "REG_IP(regs) = (unsigned long) inst->rp->kp.addr;";
+ s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);";
s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
s.op->newline(-1) << "}";
- s.op->newline() << "#else";
- s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "#endif";
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
@@ -3835,8 +3875,7 @@ dwarf_builder::build(systemtap_session & sess,
symbol_table::~symbol_table()
{
- for (iterator_t i = map_by_addr.begin(); i != map_by_addr.end(); ++i)
- delete i->second;
+ delete_map(map_by_addr);
}
void
@@ -4189,6 +4228,11 @@ module_info::~module_info()
struct uprobe_derived_probe_group: public generic_dpg<uprobe_derived_probe>
{
+private:
+ string make_pbm_key (uprobe_derived_probe* p) {
+ return p->module + "|" + p->section + "|" + lex_cast(p->pid);
+ }
+
public:
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
@@ -4196,193 +4240,6 @@ public:
};
-uprobe_derived_probe::uprobe_derived_probe (const string& function,
- const string& filename,
- int line,
- const string& module,
- int pid,
- const string& section,
- Dwarf_Addr dwfl_addr,
- Dwarf_Addr addr,
- dwarf_query & q,
- Dwarf_Die* scope_die /* may be null */):
- derived_probe (q.base_probe, new probe_point (*q.base_loc) /* .components soon rewritten */ ),
- return_p (q.has_return), module (module), pid (pid), section (section), address (addr)
-{
- // We may receive probes on two types of ELF objects: ET_EXEC or ET_DYN.
- // ET_EXEC ones need no further relocation on the addr(==dwfl_addr), whereas
- // ET_DYN ones do (addr += run-time mmap base address). We tell these apart
- // by the incoming section value (".absolute" vs. ".dynamic").
-
- this->tok = q.base_probe->tok;
-
- // Expand target variables in the probe body
- if (!null_die(scope_die))
- {
- dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's!
- v.replace (this->body);
-
- // If during target-variable-expanding the probe, we added a new block
- // of code, add it to the start of the probe.
- if (v.add_block)
- this->body = new block(v.add_block, this->body);
-
- // If when target-variable-expanding the probe, we added a new
- // probe, add it in a new file to the list of files to be processed.
- if (v.add_probe)
- {
- stapfile *f = new stapfile;
- f->probes.push_back(v.add_probe);
- q.sess.files.push_back(f);
- }
- }
- // else - null scope_die - $target variables will produce an error during translate phase
-
- // Save the local variables for listing mode
- if (q.sess.listing_mode_vars)
- saveargs(scope_die);
-
- // Reset the sole element of the "locations" vector as a
- // "reverse-engineered" form of the incoming (q.base_loc) probe
- // point. This allows a user to see what function / file / line
- // number any particular match of the wildcards.
-
- vector<probe_point::component*> comps;
- if(q.has_process)
- comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(module)));
- else
- assert (0);
-
- string fn_or_stmt;
- if (q.has_function_str || q.has_function_num)
- fn_or_stmt = "function";
- else
- fn_or_stmt = "statement";
-
- if (q.has_function_str || q.has_statement_str)
- {
- string retro_name = function;
- if (filename != "")
- {
- retro_name += ("@" + string (filename));
- if (line > 0)
- retro_name += (":" + lex_cast (line));
- }
- comps.push_back
- (new probe_point::component
- (fn_or_stmt, new literal_string (retro_name)));
- }
- else if (q.has_function_num || q.has_statement_num)
- {
- Dwarf_Addr retro_addr;
- if (q.has_function_num)
- retro_addr = q.function_num_val;
- else
- retro_addr = q.statement_num_val;
- comps.push_back (new probe_point::component
- (fn_or_stmt,
- new literal_number(retro_addr))); // XXX: should be hex if possible
-
- if (q.has_absolute)
- comps.push_back (new probe_point::component (TOK_ABSOLUTE));
- }
-
- if (q.has_call)
- comps.push_back (new probe_point::component(TOK_CALL));
- if (q.has_inline)
- comps.push_back (new probe_point::component(TOK_INLINE));
- if (return_p)
- comps.push_back (new probe_point::component(TOK_RETURN));
- /*
- if (has_maxactive)
- comps.push_back (new probe_point::component
- (TOK_MAXACTIVE, new literal_number(maxactive_val)));
- */
-
- // Overwrite it.
- this->sole_location()->components = comps;
-}
-
-
-uprobe_derived_probe::uprobe_derived_probe (probe *base,
- probe_point *location,
- int pid,
- Dwarf_Addr addr,
- bool has_return):
- derived_probe (base, location), // location is not rewritten here
- return_p (has_return), pid (pid), address (addr)
-{
-}
-
-
-void
-uprobe_derived_probe::saveargs(Dwarf_Die* scope_die)
-{
- // same as dwarf_derived_probe::saveargs
-
- Dwarf_Die *scopes;
- if (!null_die(scope_die) && dwarf_getscopes_die (scope_die, &scopes) == 0)
- return;
- auto_free free_scopes(scopes);
-
- stringstream argstream;
- string type_name;
- Dwarf_Die type_die;
-
- if (return_p &&
- dwarf_attr_die (scope_die, DW_AT_type, &type_die) &&
- dwarf_type_name(&type_die, type_name))
- argstream << " $return:" << type_name;
-
- Dwarf_Die arg;
- if (dwarf_child (&scopes[0], &arg) == 0)
- do
- {
- switch (dwarf_tag (&arg))
- {
- case DW_TAG_variable:
- case DW_TAG_formal_parameter:
- break;
-
- default:
- continue;
- }
-
- const char *arg_name = dwarf_diename (&arg);
- if (!arg_name)
- continue;
-
- type_name.clear();
- if (!dwarf_attr_die (&arg, DW_AT_type, &type_die) ||
- !dwarf_type_name(&type_die, type_name))
- continue;
-
- argstream << " $" << arg_name << ":" << type_name;
- }
- while (dwarf_siblingof (&arg, &arg) == 0);
-
- args = argstream.str();
-}
-
-
-void
-uprobe_derived_probe::printargs(std::ostream &o) const
-{
- // same as dwarf_derived_probe::printargs
- o << args;
-}
-
-
-void
-uprobe_derived_probe::printsig (ostream& o) const
-{
- // Same as dwarf_derived_probe.
- sole_location()->print (o);
- o << " /* pc=" << section << "+0x" << hex << address << dec << " */";
- printsig_nested (o);
-}
-
-
void
uprobe_derived_probe::join_group (systemtap_session& s)
{
@@ -4459,13 +4316,65 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "static struct stap_uprobe {";
s.op->newline(1) << "union { struct uprobe up; struct uretprobe urp; };";
s.op->newline() << "int spec_index;"; // index into stap_uprobe_specs; <0 == free && unregistered
- s.op->newline(-1) << "} stap_uprobes [MAXUPROBES];";
+ s.op->newline(-1) << "} stap_uprobes [MAXUPROBES];"; // XXX: consider a slab cache or somesuch
s.op->newline() << "DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration
- s.op->newline() << "static struct stap_uprobe_spec {";
+ s.op->assert_0_indent();
+
+ // Forward decls
+ s.op->newline() << "static int stap_uprobe_process_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p);";
+ 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() << "static int stap_uprobe_munmap_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, unsigned long addr, unsigned long length);";
+
+ // Assign task-finder numbers as we build up the stap_uprobe_tf table.
+ // This means we process probes[] in two passes.
+ map <string,unsigned> module_index;
+ unsigned module_index_ctr = 0;
+
+ s.op->newline() << "static struct stap_uprobe_tf {"; // not const since embedded task_finder_target struct changes
s.op->newline(1) << "struct stap_task_finder_target finder;";
+ s.op->newline(0) << "const char *pathname;";
+ s.op->newline(-1) << "} stap_uprobe_finders[] = {";
+ s.op->indent(1);
+ for (unsigned i=0; i<probes.size(); i++)
+ {
+ uprobe_derived_probe *p = probes[i];
+ string pbmkey = make_pbm_key (p);
+ if (module_index.find (pbmkey) == module_index.end())
+ {
+ module_index[pbmkey] = module_index_ctr++;
+
+ s.op->newline() << "{";
+ // NB: it's essential that make_pbm_key() use all of and
+ // only the same fields as we're about to emit.
+ s.op->line() << " .finder={";
+ if (p->pid != 0)
+ s.op->line() << " .pid=" << p->pid;
+ else if (p->section == ".absolute") // proxy for ET_EXEC -> exec()'d program
+ {
+ s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ",";
+ s.op->line() << " .callback=&stap_uprobe_process_found,";
+ }
+ if (p->section != ".absolute") // ET_DYN
+ {
+ s.op->line() << " .mmap_callback=&stap_uprobe_mmap_found, ";
+ s.op->line() << " .munmap_callback=&stap_uprobe_munmap_found, ";
+ }
+
+ s.op->line() << " },";
+ s.op->line() << " .pathname=" << lex_cast_qstring(p->module) << ", ";
+ s.op->line() << " },";
+ }
+ else
+ ; // skip it in this pass, already have a suitable stap_uprobe_tf slot for it.
+ }
+ s.op->newline(-1) << "};";
+
+ s.op->assert_0_indent();
+
+ s.op->newline() << "static const struct stap_uprobe_spec {";
+ s.op->newline(1) << "unsigned tfi;"; // index into stap_uprobe_finders[]
s.op->newline() << "unsigned long address;";
- s.op->newline() << "const char *pathname;";
s.op->newline() << "const char *pp;";
s.op->newline() << "void (*ph) (struct context*);";
s.op->newline() << "unsigned return_p:1;";
@@ -4475,26 +4384,22 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
{
uprobe_derived_probe* p = probes[i];
s.op->newline() << "{";
- s.op->line() << " .finder = {";
- if (p->pid != 0)
- s.op->line() << " .pid=" << p->pid;
- else if (p->section == ".absolute") // proxy for ET_EXEC -> exec()'d program
- s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ", ";
- // else ".dynamic" gets procname=0, pid=0, activating task_finder "global tracing"
- s.op->line() << "},";
- if (p->section != ".absolute")
- s.op->line() << " .pathname=" << lex_cast_qstring(p->module) << ", ";
- s.op->line() << " .address=(unsigned long)0x" << hex << p->address << dec << "ULL,";
+ string key = make_pbm_key (p);
+ unsigned value = module_index[key];
+ s.op->line() << " .tfi=" << value << ",";
+ s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
s.op->line() << " .ph=&" << p->name << ",";
- if (p->return_p) s.op->line() << " .return_p=1,";
+ if (p->has_return) s.op->line() << " .return_p=1,";
s.op->line() << " },";
}
s.op->newline(-1) << "};";
+ s.op->assert_0_indent();
+
s.op->newline() << "static void enter_uprobe_probe (struct uprobe *inst, struct pt_regs *regs) {";
s.op->newline(1) << "struct stap_uprobe *sup = container_of(inst, struct stap_uprobe, up);";
- s.op->newline() << "struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
+ s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sups->pp");
s.op->newline() << "if (sup->spec_index < 0 ||"
<< "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen
@@ -4503,25 +4408,20 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// Make it look like the IP is set as it would in the actual user
// task when calling real probe handler. Reset IP regs on return, so
// we don't confuse uprobes. PR10458
- // But only for architectures where REG_IP is a proper lvalue. PR10491
- s.op->newline() << "#ifdef REG_IP_LVALUE";
s.op->newline() << "{";
s.op->indent(1);
s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->regs);";
- s.op->newline() << "REG_IP(regs) = inst->vaddr;";
+ s.op->newline() << "SET_REG_IP(regs, inst->vaddr);";
s.op->newline() << "(*sups->ph) (c);";
- s.op->newline() << "REG_IP(regs) = uprobes_ip;";
+ s.op->newline() << "SET_REG_IP(regs, uprobes_ip);";
s.op->newline(-1) << "}";
- s.op->newline() << "#else";
- s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "#endif";
common_probe_entryfn_epilogue (s.op);
s.op->newline(-1) << "}";
s.op->newline() << "static void enter_uretprobe_probe (struct uretprobe_instance *inst, struct pt_regs *regs) {";
s.op->newline(1) << "struct stap_uprobe *sup = container_of(inst->rp, struct stap_uprobe, urp);";
- s.op->newline() << "struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
+ s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sups->pp");
s.op->newline() << "if (sup->spec_index < 0 ||"
<< "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen
@@ -4531,18 +4431,13 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// Make it look like the IP is set as it would in the actual user
// task when calling real probe handler. Reset IP regs on return, so
// we don't confuse uprobes. PR10458
- // But only for architectures where REG_IP is a proper lvalue. PR10491
- s.op->newline() << "#ifdef REG_IP_LVALUE";
s.op->newline() << "{";
s.op->indent(1);
s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->regs);";
- s.op->newline() << "REG_IP(regs) = inst->rp->u.vaddr;";
+ s.op->newline() << "SET_REG_IP(regs, inst->rp->u.vaddr);";
s.op->newline() << "(*sups->ph) (c);";
- s.op->newline() << "REG_IP(regs) = uprobes_ip;";
+ s.op->newline() << "SET_REG_IP(regs, uprobes_ip);";
s.op->newline(-1) << "}";
- s.op->newline() << "#else";
- s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "#endif";
common_probe_entryfn_epilogue (s.op);
s.op->newline(-1) << "}";
@@ -4560,19 +4455,33 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// unregistration.
s.op->newline();
- s.op->newline() << "static int stap_uprobe_change (struct task_struct *tsk, int register_p, unsigned long relocation, struct stap_uprobe_spec *sups) {";
- s.op->newline(1) << "int spec_index = (sups - stap_uprobe_specs);";
- s.op->newline() << "int handled_p = 0;";
+ s.op->newline() << "static int stap_uprobe_change_plus (struct task_struct *tsk, unsigned long relocation, unsigned long length, const struct stap_uprobe_tf *stf) {";
+ s.op->newline(1) << "int tfi = (stf - stap_uprobe_finders);";
+ s.op->newline() << "int spec_index;";
+
+ // iterate over stap_uprobe_spec[] that use this same stap_uprobe_tf
+ s.op->newline() << "for (spec_index=0; spec_index<sizeof(stap_uprobe_specs)/sizeof(stap_uprobe_specs[0]); spec_index++) {";
+ s.op->newline(1) << "int handled_p = 0;";
s.op->newline() << "int slotted_p = 0;";
+ s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [spec_index];";
s.op->newline() << "int rc = 0;";
s.op->newline() << "int i;";
+ s.op->newline() << "if (likely(sups->tfi != tfi)) continue;";
+ // skip probes with an address beyond this map event; should not
+ // happen unless a shlib/exec got mmapped in weirdly piecemeal
+ s.op->newline() << "if (likely(sups->address >= length)) continue;";
+
+ // Found a uprobe_spec for this stap_uprobe_tf. Need to lock the
+ // stap_uprobes[] array to allocate a free spot, but then we can
+ // unlock and do the register_*probe subsequently.
+
s.op->newline() << "mutex_lock (& stap_uprobes_lock);";
s.op->newline() << "for (i=0; i<MAXUPROBES; i++) {"; // XXX: slow linear search
s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[i];";
// register new uprobe
- s.op->newline() << "if (register_p && sup->spec_index < 0) {";
+ s.op->newline() << "if (sup->spec_index < 0) {";
s.op->newline(1) << "#if (UPROBES_API_VERSION < 2)";
// See PR6829 comment.
s.op->newline() << "if (sup->spec_index == -1 && sup->up.kdata != NULL) continue;";
@@ -4581,20 +4490,14 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "sup->spec_index = spec_index;";
s.op->newline() << "slotted_p = 1;";
s.op->newline() << "break;";
- s.op->newline(-1) << "} else if (!register_p && "
- << "sup->spec_index == spec_index && " // a u[ret]probe set up for this probe point
- << "((sups->return_p && sup->urp.u.pid == tsk->tgid && sup->urp.u.vaddr == relocation + sups->address) ||" // dying uretprobe
- << "(!sups->return_p && sup->up.pid == tsk->tgid && sup->up.vaddr == relocation + sups->address))) {"; // dying uprobe
- s.op->newline(1) << "slotted_p = 1;";
- s.op->newline() << "break;"; // exit to-free slot search
s.op->newline(-1) << "}";
-
s.op->newline(-1) << "}";
s.op->newline() << "mutex_unlock (& stap_uprobes_lock);";
s.op->newline() << "#ifdef DEBUG_UPROBES";
- s.op->newline() << "printk (KERN_INFO \"%cuprobe spec %d idx %d process %s[%d] reloc %p pp '%s'\\n\", ";
- s.op->line() << "(register_p ? '+' : '-'), spec_index, (slotted_p ? i : -1), tsk->comm, tsk->tgid, (void*) relocation, sups->pp);";
+ s.op->newline() << "_stp_dbug(__FUNCTION__,__LINE__, \"+uprobe spec %d idx %d process %s[%d] addr %p pp %s\\n\", ";
+ s.op->line() << "spec_index, (slotted_p ? i : -1), tsk->comm, tsk->tgid, "
+ << "(void*)(relocation+sups->address), sups->pp);";
s.op->newline() << "#endif";
// Here, slotted_p implies that `i' points to the single
@@ -4603,7 +4506,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// was full (registration; MAXUPROBES) or that no matching entry was
// found (unregistration; should not happen).
- s.op->newline() << "if (register_p && slotted_p) {";
+ s.op->newline() << "if (slotted_p) {";
s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[i];";
s.op->newline() << "if (sups->return_p) {";
s.op->newline(1) << "sup->urp.u.pid = tsk->tgid;";
@@ -4617,7 +4520,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "rc = register_uprobe (& sup->up);";
s.op->newline(-1) << "}";
s.op->newline() << "if (rc) {"; // failed to register
- s.op->newline(1) << "printk (KERN_WARNING \"uprobe failed %s[%d] '%s' addr %p rc %d\\n\", tsk->comm, tsk->tgid, sups->pp, (void*)(relocation + sups->address), rc);";
+ s.op->newline(1) << "_stp_warn (\"u*probe failed %s[%d] '%s' addr %p rc %d\\n\", tsk->comm, tsk->tgid, sups->pp, (void*)(relocation + sups->address), rc);";
// NB: we need to release this slot, so we need to borrow the mutex temporarily.
s.op->newline() << "mutex_lock (& stap_uprobes_lock);";
s.op->newline() << "sup->spec_index = -1;";
@@ -4625,10 +4528,49 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline(-1) << "} else {";
s.op->newline(1) << "handled_p = 1;"; // success
s.op->newline(-1) << "}";
+ s.op->newline(-1) << "}";
- s.op->newline(-1) << "} else if (!register_p && slotted_p) {";
+ // NB: handled_p implies slotted_p
+
+ s.op->newline() << "if (unlikely (! handled_p)) {";
+ s.op->newline(1) << "#ifdef STP_TIMING";
+ s.op->newline() << "atomic_inc (& skipped_count_uprobe_reg);";
+ s.op->newline() << "#endif";
+ // NB: duplicates common_entryfn_epilogue, but then this is not a probe entry fn epilogue.
+ s.op->newline() << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
+ s.op->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+ s.op->newline() << "_stp_exit ();";
+ s.op->newline(-1) << "}";
+ s.op->newline(-1) << "}";
+
+ // close iteration over stap_uprobe_spec[]
+ s.op->newline(-1) << "}";
+
+ s.op->newline() << "return 0;"; // XXX: or rc?
+ s.op->newline(-1) << "}";
+
+ s.op->assert_0_indent();
+
+
+ // Removing/unmapping a uprobe is simpler than adding one (in the _plus function above).
+ // We need not care about stap_uprobe_finders or anything, we just scan through stap_uprobes[]
+ // for a live probe within the given address range, and kill it.
+ s.op->newline();
+ s.op->newline() << "static int stap_uprobe_change_minus (struct task_struct *tsk, unsigned long relocation, unsigned long length, const struct stap_uprobe_tf *stf) {";
+ s.op->newline(1) << "int i;";
+
+ // NB: it's not an error for us not to find a live uprobe within the
+ // given range. We might have received a callback for a part of a
+ // shlib that was unmapped and unprobed.
+
+ s.op->newline() << "for (i=0; i<MAXUPROBES; i++) {"; // XXX: slow linear search
s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[i];";
- s.op->newline() << "int unregistered_flag;";
+ s.op->newline() << "const struct stap_uprobe_spec *sups;";
+ s.op->newline() << "if (sup->spec_index < 0) continue;"; // skip free uprobes slot
+ s.op->newline() << "sups = & stap_uprobe_specs[sup->spec_index];";
+
+ s.op->newline() << "mutex_lock (& stap_uprobes_lock);";
+
// PR6829, PR9940:
// Here we're unregistering for one of two reasons:
// 1. the process image is going away (or gone) due to exit or exec; or
@@ -4640,73 +4582,116 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// In both cases, we must use unmap_u[ret]probe instead of
// unregister_u[ret]probe, so uprobes knows not to try to restore the
// original opcode.
+
+ // URETPROBE
+ s.op->newline() << "if (sups->return_p && sup->urp.u.pid == tsk->tgid && " // my uretprobe
+ << "sup->urp.u.vaddr >= relocation && sup->urp.u.vaddr < relocation+length) {"; // in range
+ s.op->newline(1) << "";
+
+ s.op->newline() << "#ifdef DEBUG_UPROBES";
+ s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uretprobe spec %d idx %d process %s[%d] addr %p pp %s\\n\", ";
+ s.op->line() << "sup->spec_index, i, tsk->comm, tsk->tgid, (void*) sup->urp.u.vaddr, sups->pp);";
+ s.op->newline() << "#endif";
+
s.op->newline() << "#if (UPROBES_API_VERSION >= 2)";
- s.op->newline() << "if (sups->return_p)";
- s.op->newline(1) << "unmap_uretprobe (& sup->urp);";
- s.op->newline(-1) << "else";
- s.op->newline(1) << "unmap_uprobe (& sup->up);";
- s.op->newline(-1) << "unregistered_flag = -1;";
+ s.op->newline() << "unmap_uretprobe (& sup->urp);";
+ s.op->newline() << "sup->spec_index = -1;";
s.op->newline() << "#else";
- // Uprobes lacks unmap_u[ret]probe. Before reusing sup, we must wait
- // until uprobes turns loose of the u[ret]probe on its own, as indicated
- // by uprobe.kdata = NULL.
- s.op->newline() << "unregistered_flag = (sups->return_p ? -2 : -1);";
+ // Uprobes lacks unmap_uretprobe. Before reusing sup, we must wait
+ // until uprobes turns loose of the uretprobe on its own, as indicated
+ // by uretprobe.kdata = NULL.
+ s.op->newline() << "sup->spec_index = -2;";
s.op->newline() << "#endif";
- s.op->newline() << "mutex_lock (& stap_uprobes_lock);";
- s.op->newline() << "sup->spec_index = unregistered_flag;";
- s.op->newline() << "mutex_unlock (& stap_uprobes_lock);";
- s.op->newline() << "handled_p = 1;";
- s.op->newline(-1) << "}"; // if slotted_p
- // NB: handled_p implies slotted_p
+ // UPROBE
+ s.op->newline(-1) << "} else if (!sups->return_p && sup->up.pid == tsk->tgid && " // my uprobe
+ << "sup->up.vaddr >= relocation && sup->up.vaddr < relocation+length) {"; //in range
+ s.op->newline(1) << "";
- s.op->newline() << "if (! handled_p) {";
- s.op->newline(1) << "#ifdef STP_TIMING";
- s.op->newline() << "atomic_inc (register_p ? & skipped_count_uprobe_reg : & skipped_count_uprobe_unreg);";
+ s.op->newline() << "#ifdef DEBUG_UPROBES";
+ s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uprobe spec %d idx %d process %s[%d] reloc %p pp %s\\n\", ";
+ s.op->line() << "sup->spec_index, i, tsk->comm, tsk->tgid, (void*) sup->up.vaddr, sups->pp);";
s.op->newline() << "#endif";
- // NB: duplicates common_entryfn_epilogue, but then this is not a probe entry fn epilogue.
- s.op->newline() << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
- s.op->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
- s.op->newline() << "_stp_exit ();";
+
+ s.op->newline() << "#if (UPROBES_API_VERSION >= 2)";
+ s.op->newline() << "unmap_uprobe (& sup->up);";
+ s.op->newline() << "sup->spec_index = -1;";
+ s.op->newline() << "#else";
+ // Uprobes lacks unmap_uprobe. Before reusing sup, we must wait
+ // until uprobes turns loose of the uprobe on its own, as indicated
+ // by uprobe.kdata = NULL.
+ s.op->newline() << "sup->spec_index = -1;";
+ s.op->newline() << "#endif";
+
s.op->newline(-1) << "}";
+
+ s.op->newline() << "mutex_unlock (& stap_uprobes_lock);";
+
+ // close iteration over stap_uprobes[]
s.op->newline(-1) << "}";
- s.op->newline() << "return 0;"; // XXX: or rc?
+ s.op->newline() << "return 0;"; // XXX: or !handled_p
s.op->newline(-1) << "}";
- s.op->assert_0_indent();
+ s.op->assert_0_indent();
- // The task_finder_callback we use for ET_EXEC targets.
+ // The task_finder_callback we use for ET_EXEC targets. We used to perform uprobe
+ // insertion/removal here, but not any more. (PR10524)
s.op->newline();
s.op->newline() << "static int stap_uprobe_process_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {";
- s.op->newline(1) << "struct stap_uprobe_spec *sups = container_of(tgt, struct stap_uprobe_spec, finder);";
- s.op->newline() << "if (! process_p) return 0;";
- s.op->newline(0) << "return stap_uprobe_change (tsk, register_p, 0, sups);";
+ s.op->newline(1) << "const struct stap_uprobe_tf *stf = container_of(tgt, struct stap_uprobe_tf, finder);";
+ s.op->newline() << "if (! process_p) return 0;"; // ignore threads
+
+ s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA";
+ s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"%cproc pid %d stf %p %p path %s\\n\", register_p?'+':'-', tsk->tgid, tgt, stf, stf->pathname);";
+ s.op->newline() << "#endif";
+
+ // ET_EXEC events are modeled as if shlib events, but with 0 relocation bases
+ s.op->newline() << "if (register_p)";
+ s.op->newline(1) << "return stap_uprobe_change_plus (tsk, 0, TASK_SIZE, stf);";
+ s.op->newline(-1) << "else";
+ s.op->newline(1) << "return stap_uprobe_change_minus (tsk, 0, TASK_SIZE, stf);";
+ s.op->indent(-1);
s.op->newline(-1) << "}";
- // The task_finder_mmap_callback we use for ET_DYN targets.
+ s.op->assert_0_indent();
+
+ // The task_finder_mmap_callback
s.op->newline();
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);";
+ s.op->newline(1) << "const struct stap_uprobe_tf *stf = container_of(tgt, struct stap_uprobe_tf, finder);";
// 1 - shared libraries' executable segments load from offset 0 - ld.so convention
s.op->newline() << "if (offset != 0) return 0;";
// 2 - the shared library we're interested in
- 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 (sups->address >= addr && sups->address < (addr + length)) return 0;";
- // 4 - mapping should be executable
+ s.op->newline() << "if (path == NULL || strcmp (path, stf->pathname)) return 0;";
+ // 3 - 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 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() << "_stp_dbug (__FUNCTION__,__LINE__, \"+mmap pid %d path %s addr %p length %u offset %p stf %p %p path %s\\n\", "
+ << "tsk->tgid, path, (void *) addr, (unsigned)length, (void*) offset, tgt, stf, stf->pathname);";
s.op->newline() << "#endif";
- s.op->newline(0) << "return stap_uprobe_change (tsk, 1, addr, sups);";
+ s.op->newline() << "return stap_uprobe_change_plus (tsk, addr, length, stf);";
s.op->newline(-1) << "}";
+
s.op->assert_0_indent();
+ // The task_finder_munmap_callback
+ s.op->newline();
+ s.op->newline() << "static int stap_uprobe_munmap_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, unsigned long addr, unsigned long length) {";
+ s.op->newline(1) << "const struct stap_uprobe_tf *stf = container_of(tgt, struct stap_uprobe_tf, finder);";
+
+ s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA";
+ s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-mmap pid %d addr %p length %lu stf %p %p path %s\\n\", "
+ << "tsk->tgid, (void *) addr, length, tgt, stf, stf->pathname);";
+ s.op->newline() << "#endif";
+
+ s.op->newline() << "return stap_uprobe_change_minus (tsk, addr, length, stf);";
+ s.op->newline(-1) << "}";
+
+ s.op->assert_0_indent();
s.op->newline();
}
@@ -4728,12 +4713,11 @@ uprobe_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline(-1) << "}";
s.op->newline() << "mutex_init (& stap_uprobes_lock);";
- s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
- 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.procname) sups->finder.callback = & stap_uprobe_process_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);";
+ // Set up the task_finders
+ s.op->newline() << "for (i=0; i<sizeof(stap_uprobe_finders)/sizeof(stap_uprobe_finders[0]); i++) {";
+ s.op->newline(1) << "struct stap_uprobe_tf *stf = & stap_uprobe_finders[i];";
+ s.op->newline() << "probe_point = stf->pathname;"; // for error messages; XXX: would prefer pp() or something better
+ s.op->newline() << "rc = stap_register_task_finder_target (& stf->finder);";
// NB: if (rc), there is no need (XXX: nor any way) to clean up any
// finders already registered, since mere registration does not
@@ -4763,19 +4747,19 @@ uprobe_derived_probe_group::emit_module_exit (systemtap_session& s)
s.op->newline() << "for (j=0; j<MAXUPROBES; j++) {";
s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[j];";
- s.op->newline() << "struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
+ s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
s.op->newline() << "if (sup->spec_index < 0) continue;"; // free slot
s.op->newline() << "if (sups->return_p) {";
s.op->newline(1) << "#ifdef DEBUG_UPROBES";
- s.op->newline() << "printk (KERN_INFO \"-uretprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);";
+ s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uretprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);";
s.op->newline() << "#endif";
// NB: PR6829 does not change that we still need to unregister at
// *this* time -- when the script as a whole exits.
s.op->newline() << "unregister_uretprobe (& sup->urp);";
s.op->newline(-1) << "} else {";
s.op->newline(1) << "#ifdef DEBUG_UPROBES";
- s.op->newline() << "printk (KERN_INFO \"-uprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->urp.u.pid, (void*) sup->urp.u.vaddr);";
+ s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->urp.u.pid, (void*) sup->urp.u.vaddr);";
s.op->newline() << "#endif";
s.op->newline() << "unregister_uprobe (& sup->up);";
s.op->newline(-1) << "}";
@@ -5027,18 +5011,13 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// Make it look like the IP is set as it wouldn't have been replaced
// by a breakpoint instruction when calling real probe handler. Reset
// IP regs on return, so we don't confuse kprobes. PR10458
- // But only for architectures where REG_IP is a proper lvalue. PR10491
- s.op->newline() << "#ifdef REG_IP_LVALUE";
s.op->newline() << "{";
s.op->indent(1);
s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
- s.op->newline() << "REG_IP(regs) = (unsigned long) inst->addr;";
+ s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->addr);";
s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
s.op->newline(-1) << "}";
- s.op->newline() << "#else";
- s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "#endif";
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
@@ -5066,18 +5045,13 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// Make it look like the IP is set as it wouldn't have been replaced
// by a breakpoint instruction when calling real probe handler. Reset
// IP regs on return, so we don't confuse kprobes. PR10458
- // But only for architectures where REG_IP is a proper lvalue. PR10491
- s.op->newline() << "#ifdef REG_IP_LVALUE";
s.op->newline() << "{";
s.op->indent(1);
s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->regs);";
- s.op->newline() << "REG_IP(regs) = (unsigned long) inst->rp->kp.addr;";
+ s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);";
s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
s.op->newline(-1) << "}";
- s.op->newline() << "#else";
- s.op->newline() << "(*sdp->ph) (c);";
- s.op->newline() << "#endif";
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
@@ -6110,9 +6084,11 @@ register_standard_tapsets(systemtap_session & s)
// XXX: user-space starter set
s.pattern_root->bind_num(TOK_PROCESS)
->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)
+ ->allow_unprivileged()
->bind(new uprobe_builder ());
s.pattern_root->bind_num(TOK_PROCESS)
->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(TOK_RETURN)
+ ->allow_unprivileged()
->bind(new uprobe_builder ());
// kernel tracepoint probes
diff --git a/testsuite/buildok/ipmib-all-probes.stp b/testsuite/buildok/ipmib-all-probes.stp
index b6bedcf7..b6bedcf7 100644..100755
--- a/testsuite/buildok/ipmib-all-probes.stp
+++ b/testsuite/buildok/ipmib-all-probes.stp
diff --git a/testsuite/buildok/linuxmib-all-probes.stp b/testsuite/buildok/linuxmib-all-probes.stp
index c79fc7d3..c79fc7d3 100644..100755
--- a/testsuite/buildok/linuxmib-all-probes.stp
+++ b/testsuite/buildok/linuxmib-all-probes.stp
diff --git a/testsuite/buildok/tcpmib-all-probes.stp b/testsuite/buildok/tcpmib-all-probes.stp
index f20ba8bb..f20ba8bb 100644..100755
--- a/testsuite/buildok/tcpmib-all-probes.stp
+++ b/testsuite/buildok/tcpmib-all-probes.stp
diff --git a/testsuite/semko/nodwf07.stp b/testsuite/semko/nodwf07.stp
index 4a2cf4a5..b48562f9 100755
--- a/testsuite/semko/nodwf07.stp
+++ b/testsuite/semko/nodwf07.stp
@@ -12,4 +12,4 @@ probe kernel.function("*") {
probe timer.sec(15) {
exit()
}
-'
+' >/dev/null
diff --git a/testsuite/semok/bz10475.stp b/testsuite/semok/bz10475.stp
index ee79b07d..160263a5 100755
--- a/testsuite/semok/bz10475.stp
+++ b/testsuite/semok/bz10475.stp
@@ -1,10 +1,9 @@
#! stap -p2
// bz10475: pointer-array confused about array element size
-// struct file *do_filp_open(int dfd, const char *pathname,
-// int open_flag, int mode, int acc_mode)
-probe kernel.function("do_filp_open")
+// struct file *filp_open(int dfd, const char *filename, int flags, int mode)
+probe kernel.function("filp_open")
{
// check array access on a "complex" pointer type
- println($pathname[0])
+ println($filename[0])
}
diff --git a/testsuite/systemtap.base/sdt_misc.exp b/testsuite/systemtap.base/sdt_misc.exp
index 27f148d0..096ea126 100644
--- a/testsuite/systemtap.base/sdt_misc.exp
+++ b/testsuite/systemtap.base/sdt_misc.exp
@@ -1,10 +1,11 @@
-set test "static_user_markers"
+set test "sdt_misc"
# Test miscellaneous features of .mark probes
# Compile a C program to use as the user-space probing target
set sup_srcpath "[pwd]/static_user_markers.c"
set sup_exepath "[pwd]/static_user_markers.x"
+set sup_sopath "[pwd]/libsdt.so"
set supcplus_exepath "[pwd]/static_user_markers_cplus.x"
set fp [open $sup_srcpath "w"]
puts $fp "
@@ -44,6 +45,7 @@ buz (int parm)
DTRACE_PROBE1(static_user_markers,test_probe_4,&bstruct);
}
+#ifndef NO_MAIN
int
main ()
{
@@ -51,6 +53,7 @@ main ()
baz(3,(char*)\"abc\");
buz(4);
}
+#endif
"
close $fp
@@ -217,6 +220,56 @@ if { $ok != 0} {
pass "$test types $pbtype_mssg"
}
+# Test probe in shared object
+
+set sup_srcmainpath "[pwd]/static_user_markers_.c"
+set fp [open $sup_srcmainpath "w"]
+puts $fp "
+int
+main ()
+{
+ bar(2);
+ baz(3,(char*)\"abc\");
+ buz(4);
+}
+"
+close $fp
+
+set sup_flags "$sup_flags additional_flags=-shared"
+set sup_flags "$sup_flags additional_flags=-fPIC"
+set sup_flags "$sup_flags additional_flags=-DNO_MAIN"
+set res0 [target_compile $sup_srcpath $sup_sopath executable $sup_flags ]
+set sup0_flags "additional_flags=-g additional_flags=-Wl,-rpath,[pwd]"
+set sup0_flags "$sup0_flags additional_flags=-L[pwd] additional_flags=-lsdt"
+set res [target_compile $sup_srcmainpath $sup_exepath executable $sup0_flags ]
+if { $res0 != "" || $res != "" } {
+ verbose "target_compile failed: $res0 $res" 2
+ fail "$test compiling -g -shared $pbtype_mssg"
+ if { $verbose == 0 } {
+ catch {exec rm -f $sup_srcpath $sup_srcmainpath}
+ }
+ return
+} else {
+ pass "$test compiling -g -shared $pbtype_mssg"
+}
+
+verbose -log "stap -c $sup_exepath -e probe process(\"$sup_sopath\").mark(\"test_probe_2\") {printf(\"In %s probe %#x\\n\", \$\$name, \$arg1)}"
+spawn stap -c $sup_exepath -e "probe process(\"$sup_sopath\").mark(\"test_probe_2\") {printf(\"In %s probe %#x\\n\", \$\$name, \$arg1)}"
+expect {
+ -timeout 180
+ -re {In test_probe_2 probe 0x2} { incr ok; exp_continue }
+ timeout { fail "$test (timeout)" }
+ eof { }
+}
+
+wait
+
+if {$ok == 2} {
+ pass "$test shared $pbtype_mssg"
+} else {
+ fail "$test shared ($ok) $pbtype_mssg"
+}
+
# Test .mark probe wildcard matching
set ok 0
@@ -238,6 +291,5 @@ if { $ok == 45 } {
}
if { $verbose == 0 } {
-catch {exec rm -f $sup_srcpath $sup_exepath $supcplus_exepath $sup_dpath $sup_hpath $sup_stppath sdt_types.x}
+catch {exec rm -f $sup_srcpath $sup_exepath $sup_sopath $supcplus_exepath $sup_dpath $sup_hpath $sup_opath $sup_stppath $sdt_types.x $sup_srcmainpath}
}
-
diff --git a/testsuite/systemtap.base/tracepoints.exp b/testsuite/systemtap.base/tracepoints.exp
index a4e38c05..b9014208 100644
--- a/testsuite/systemtap.base/tracepoints.exp
+++ b/testsuite/systemtap.base/tracepoints.exp
@@ -2,6 +2,7 @@
set tracepoints {}
spawn stap -l {kernel.trace("*")}
expect {
+ -timeout 60
-re {^kernel.trace[^\r\n]*\r\n} {
append tracepoints $expect_out(0,string)
exp_continue
@@ -11,13 +12,26 @@ expect {
}
catch {close}; catch { wait }
+# Use this to test each tracepoint individually.
+#foreach tp $tracepoints {
+# set test "tracepoint $tp -p4"
+# if {[catch {exec stap -w -p4 -e "probe $tp { println($\$name, $\$vars) }"} res]} {
+# fail "$test $res"
+# } else {
+# pass "$test"
+# }
+#}
+
+# This tests all tracepoints all at once (much faster than the above)
+set script "probe begin {}"
foreach tp $tracepoints {
- set test "tracepoint $tp -p4"
- if {[catch {exec stap -w -p4 -e "probe $tp { println($\$name, $\$vars) }"} res]} {
- fail "$test $res"
- } else {
- pass "$test"
- }
+ set script "$script probe $tp { println($\$name, $\$vars) }"
+}
+send_log "Trying stap -w -p4 -e $script\n"
+if {[catch {exec stap -w -p4 -e "$script"} res]} {
+ fail "tracepoints $res"
+} else {
+ pass "tracepoints"
}
set test "tracepoints"
diff --git a/testsuite/systemtap.base/utrace_syscall_args.exp b/testsuite/systemtap.base/utrace_syscall_args.exp
index 98bc457e..e3c90191 100644
--- a/testsuite/systemtap.base/utrace_syscall_args.exp
+++ b/testsuite/systemtap.base/utrace_syscall_args.exp
@@ -37,7 +37,8 @@ if {$do_64_bit_pass} {
set res [target_compile $srcpath $exepath executable $flags]
if { $res != "" } {
verbose "target_compile for $exepath failed: $res" 2
- fail "$testname: unable to compile $srcpath"
+ send_log "$testname: unable to compile $srcpath\n"
+ untested $testname
return
}
@@ -72,7 +73,8 @@ if {$do_32_bit_pass} {
set res [target_compile $srcpath $exepath executable $flags]
if { $res != "" } {
verbose "target_compile for $exepath failed: $res" 2
- fail "$testname: unable to compile $srcpath"
+ send_log "$testname: unable to compile $srcpath\n"
+ untested $testname
return
}
diff --git a/testsuite/systemtap.examples/check.exp b/testsuite/systemtap.examples/check.exp
index 482738cc..0fad597d 100644
--- a/testsuite/systemtap.examples/check.exp
+++ b/testsuite/systemtap.examples/check.exp
@@ -32,7 +32,7 @@ proc extract_tag { META_DATA TAG } {
return $value
}
-proc run_command { test command } {
+proc run_command { test action command } {
#FIXME tcl says that single quotes not dealt with
if { $command != "" } then {
verbose -log "attempting command $command"
@@ -42,13 +42,16 @@ proc run_command { test command } {
set res [catch {eval exec "$command |& cat"} value]
verbose -log "OUT $value"
verbose -log "RC $res"
- if {$res != 0 } {
- fail $test
+ if { $res != 0 } { # allow failure for support
+ if { $action != "support" } { fail "$test $action" }
+ return $res
} else {
- pass $test
+ pass "$test $action"
+ return $res
}
} else {
- untested $test
+ untested "$test $action"
+ return 0
}
}
@@ -64,16 +67,33 @@ foreach file $meta_files {
cd $dir
set meta_data [get_meta_data $file]
- set test_check [extract_tag "$meta_data" "test_check"]
- set command $test_check
- run_command "$test build" $command
+ set test_support [extract_tag "$meta_data" "test_support"]
+ set command $test_support
+ set supported_p 1
+ if { $command != "" } { # need to test support
+ set res [run_command "$test" "support" $command]
+ if { $res != 0 } { set supported_p 0 }
+ }
+
+ if { $supported_p == 1 } {
+ set test_check [extract_tag "$meta_data" "test_check"]
+ set command $test_check
+ run_command "$test" "build" $command
+ } else {
+ untested "$test build"
+ }
+
set test_installcheck [extract_tag "$meta_data" "test_installcheck"]
# The pass/fail logic too simple and fails for some examples
# FIXME would like to be able to run more complicated test code
if {[info procs installtest_p] != "" && [installtest_p]
&& $test_installcheck != "" } then {
- set command $test_installcheck
- run_command "$test run" $command
+ if { $supported_p == 1 } {
+ set command $test_installcheck
+ run_command "$test" "run" $command
+ } else {
+ untested "$test run"
+ }
}
}
diff --git a/testsuite/systemtap.examples/general/graphs.meta b/testsuite/systemtap.examples/general/graphs.meta
index 60a522b3..273162e8 100644
--- a/testsuite/systemtap.examples/general/graphs.meta
+++ b/testsuite/systemtap.examples/general/graphs.meta
@@ -10,4 +10,4 @@ output: plot data
scope: system-wide
description: 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.
test_check: stap -p4 graphs.stp
-test_installcheck: stap graphs.stp -c "sleep 1"
+test_installcheck: stap graphs.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html
index 664bf420..b079f5b8 100644
--- a/testsuite/systemtap.examples/index.html
+++ b/testsuite/systemtap.examples/index.html
@@ -67,6 +67,9 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#BAC
<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 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/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br>
+keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br>
+<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</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>
diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt
index ce481d3b..376c545e 100644
--- a/testsuite/systemtap.examples/index.txt
+++ b/testsuite/systemtap.examples/index.txt
@@ -81,6 +81,14 @@ keywords: io
line.
+io/iostat-scsi.stp - iostat for SCSI Devices
+keywords: io profiling scsi
+
+ The iostat-scsi.stp script provides a breakdown of the number of blks
+ read and written on the various machines's SCSI devices. The script
+ takes one argument which is the number of seconds between reports.
+
+
io/iostats.stp - List Executables Reading and Writing the Most Data
keywords: io profiling
diff --git a/testsuite/systemtap.examples/interrupt/scf.meta b/testsuite/systemtap.examples/interrupt/scf.meta
index 1d6ec3d8..9ea5aafe 100644
--- a/testsuite/systemtap.examples/interrupt/scf.meta
+++ b/testsuite/systemtap.examples/interrupt/scf.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The Linux kernel function smp_call_function causes expensive inter-processor interrupts (IPIs). The scf.stp script tallies the processes and backtraces causing the interprocessor interrupts to identify the cause of the expensive IPI. On exit the script prints the tallies in descending frequency.
test_check: stap -p4 scf.stp
-test_installcheck: stap scf.stp -c "sleep 1"
+test_installcheck: stap scf.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/disktop.meta b/testsuite/systemtap.examples/io/disktop.meta
index b063075b..1d0ce04b 100644
--- a/testsuite/systemtap.examples/io/disktop.meta
+++ b/testsuite/systemtap.examples/io/disktop.meta
@@ -10,4 +10,4 @@ output: timed
scope: system-wide
description: Get the status of reading/writing disk every 5 seconds, output top ten entries during that period.
test_check: stap -p4 disktop.stp
-test_installcheck: stap disktop.stp -c "sleep 1"
+test_installcheck: stap disktop.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/io_submit.meta b/testsuite/systemtap.examples/io/io_submit.meta
index 911cb837..7bbc33a1 100644
--- a/testsuite/systemtap.examples/io/io_submit.meta
+++ b/testsuite/systemtap.examples/io/io_submit.meta
@@ -10,4 +10,4 @@ output: sorted on-exit
scope: system-wide
description: 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.
test_check: stap -p4 io_submit.stp
-test_installcheck: stap io_submit.stp -c "sleep 1"
+test_installcheck: stap io_submit.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/ioblktime.meta b/testsuite/systemtap.examples/io/ioblktime.meta
index 18a8b168..09425b29 100644
--- a/testsuite/systemtap.examples/io/ioblktime.meta
+++ b/testsuite/systemtap.examples/io/ioblktime.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: 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.
test_check: stap -p4 ioblktime.stp
-test_installcheck: stap ioblktime.stp -c "sleep 1"
+test_installcheck: stap ioblktime.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/iostat-scsi.meta b/testsuite/systemtap.examples/io/iostat-scsi.meta
new file mode 100644
index 00000000..a992bd51
--- /dev/null
+++ b/testsuite/systemtap.examples/io/iostat-scsi.meta
@@ -0,0 +1,14 @@
+title: iostat for SCSI Devices
+name: iostat-scsi.stp
+version: 1.0
+author: anonymous
+keywords: io profiling scsi
+subsystem: io
+status: production
+exit: user-controlled
+output: timed
+scope: system-wide
+description: The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.
+test_support: stap -l module("st").function("st_do_scsi")!,kernel.function("st_do_scsi")
+test_check: stap -g -p4 iostat-scsi.stp 1
+test_installcheck: stap -g iostat-scsi.stp 1 -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/iostat-scsi.stp b/testsuite/systemtap.examples/io/iostat-scsi.stp
index 15833af8..f6715a42 100755
--- a/testsuite/systemtap.examples/io/iostat-scsi.stp
+++ b/testsuite/systemtap.examples/io/iostat-scsi.stp
@@ -19,20 +19,29 @@ probe module("sd_mod").function("sd_init_command") !, kernel.function("sd_init_c
reads[device] <<< nr_sectors * sector_size
}
%:
+
+function get_sector_size:long (data:long) {
+ return @cast(data, "scsi_device", "kernel<scsi/scsi_device.h>")->sector_size
+}
+
+%(kernel_v>="2.6.31" %?
%{
-#include <scsi/scsi_device.h>
+#include <linux/blkdev.h>
%}
-function get_sector_size:long (data:long) %{ /* pure */
- struct scsi_device *sdp = (struct scsi_device *)((long)THIS->data);
- THIS->__retvalue = kread(&(sdp->sector_size));
- CATCH_DEREF_FAULT();
+function get_nr_sectors:long(rq:long) %{ /* pure */
+ THIS->__retvalue = blk_rq_sectors((const struct request *)(long)THIS->rq);
%}
+%)
probe module("sd_mod").function("sd_prep_fn") !, kernel.function("sd_prep_fn") {
device=kernel_string($rq->rq_disk->disk_name)
sector_size=get_sector_size($q->queuedata)
+%(kernel_v>="2.6.31" %?
+ nr_sectors=get_nr_sectors($rq)
+%:
nr_sectors=$rq->nr_sectors
+%)
devices[device] = 1
if ($rq->cmd_flags & 1)
writes[device] <<< nr_sectors * sector_size
diff --git a/testsuite/systemtap.examples/io/iostats.meta b/testsuite/systemtap.examples/io/iostats.meta
index a74c9fe4..2f0a2c50 100644
--- a/testsuite/systemtap.examples/io/iostats.meta
+++ b/testsuite/systemtap.examples/io/iostats.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: 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.
test_check: stap -p4 iostats.stp
-test_installcheck: stap iostats.stp -c "sleep 1"
+test_installcheck: stap iostats.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/iotime.meta b/testsuite/systemtap.examples/io/iotime.meta
index f656ff85..cde49974 100644
--- a/testsuite/systemtap.examples/io/iotime.meta
+++ b/testsuite/systemtap.examples/io/iotime.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: 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.
test_check: stap -p4 iotime.stp
-test_installcheck: stap iotime.stp -c "sleep 1"
+test_installcheck: stap iotime.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/iotop.meta b/testsuite/systemtap.examples/io/iotop.meta
index d5331eda..52a8e2f3 100644
--- a/testsuite/systemtap.examples/io/iotop.meta
+++ b/testsuite/systemtap.examples/io/iotop.meta
@@ -10,4 +10,4 @@ output: timed
scope: system-wide
description: Every five seconds print out the top ten executables generating I/O traffic during that interval sorted in descending order.
test_check: stap -p4 iotop.stp
-test_installcheck: stap iotop.stp -c "sleep 1"
+test_installcheck: stap iotop.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/traceio.meta b/testsuite/systemtap.examples/io/traceio.meta
index da0b99f3..77e7f5df 100644
--- a/testsuite/systemtap.examples/io/traceio.meta
+++ b/testsuite/systemtap.examples/io/traceio.meta
@@ -10,4 +10,4 @@ output: timed
scope: system-wide
description: Every second print out the top ten executables sorted in descending order based on cumulative I/O traffic observed.
test_check: stap -p4 traceio.stp
-test_installcheck: stap traceio.stp -c "sleep 1"
+test_installcheck: stap traceio.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/traceio2.meta b/testsuite/systemtap.examples/io/traceio2.meta
index 4b63108c..432978ca 100644
--- a/testsuite/systemtap.examples/io/traceio2.meta
+++ b/testsuite/systemtap.examples/io/traceio2.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: Print out the executable name and process number as reads and writes to the specified device occur.
test_check: stap -p4 traceio2.stp 0x0801
-test_installcheck: stap traceio2.stp 0x0801 -c "sleep 1"
+test_installcheck: stap traceio2.stp 0x0801 -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/io/ttyspy.meta b/testsuite/systemtap.examples/io/ttyspy.meta
index e29add1b..b190eafd 100644
--- a/testsuite/systemtap.examples/io/ttyspy.meta
+++ b/testsuite/systemtap.examples/io/ttyspy.meta
@@ -3,4 +3,4 @@ name: ttyspy.stp
keywords: io tty per-process monitor
description: The ttyspy.stp script uses tty_audit hooks to monitor recent typing activity on the system, printing a scrolling record of recent keystrokes, on a per-tty basis.
test_check: stap -gp4 ttyspy.stp
-test_installcheck: stap --skip-badvars -g ttyspy.stp -c "sleep 7"
+test_installcheck: stap --skip-badvars -g ttyspy.stp -c "sleep 1"
diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html
index 7523c302..a57b967e 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="#AUTOFS">AUTOFS</a> <a href="#BACKTRACE">BACKTRACE</a> <a href="#BUFFER">BUFFER</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DISK">DISK</a> <a href="#FORMAT">FORMAT</a> <a href="#FREE">FREE</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="#MONITOR">MONITOR</a> <a href="#NETWORK">NETWORK</a> <a href="#NFS">NFS</a> <a href="#NUMA">NUMA</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="#STATISTICS">STATISTICS</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRACEPOINT">TRACEPOINT</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#TTY">TTY</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
+<p><tt><a href="#AUTOFS">AUTOFS</a> <a href="#BACKTRACE">BACKTRACE</a> <a href="#BUFFER">BUFFER</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DISK">DISK</a> <a href="#FORMAT">FORMAT</a> <a href="#FREE">FREE</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="#MONITOR">MONITOR</a> <a href="#NETWORK">NETWORK</a> <a href="#NFS">NFS</a> <a href="#NUMA">NUMA</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="#SCSI">SCSI</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#STATISTICS">STATISTICS</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRACEPOINT">TRACEPOINT</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#TTY">TTY</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
<h3><a name="AUTOFS">AUTOFS</a></h3>
<ul>
<li><a href="network/autofs4.stp">network/autofs4.stp</a> - Watch autofs4 operations<br>
@@ -135,6 +135,9 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#BAC
<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 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/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br>
+keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br>
+<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</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>
@@ -264,6 +267,9 @@ keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-inde
</ul>
<h3><a name="PROFILING">PROFILING</a></h3>
<ul>
+<li><a href="io/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br>
+keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br>
+<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</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>
@@ -307,6 +313,12 @@ keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-inde
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#SCHEDULER">SCHEDULER</a> <a href="keyword-index.html#BACKTRACE">BACKTRACE</a> <br>
<p>The script monitors the time that threads spend waiting for IO operations (in "D" state) in the wait_for_completion function. If a thread spends over 10ms, its name and backtrace is printed, and later so is the total delay.</p></li>
</ul>
+<h3><a name="SCSI">SCSI</a></h3>
+<ul>
+<li><a href="io/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br>
+keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br>
+<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li>
+</ul>
<h3><a name="SIGNALS">SIGNALS</a></h3>
<ul>
<li><a href="process/sig_by_pid.stp">process/sig_by_pid.stp</a> - Signal Counts by Process ID<br>
diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt
index f9c27e3a..4f1ce8f2 100644
--- a/testsuite/systemtap.examples/keyword-index.txt
+++ b/testsuite/systemtap.examples/keyword-index.txt
@@ -192,6 +192,14 @@ keywords: io
line.
+io/iostat-scsi.stp - iostat for SCSI Devices
+keywords: io profiling scsi
+
+ The iostat-scsi.stp script provides a breakdown of the number of blks
+ read and written on the various machines's SCSI devices. The script
+ takes one argument which is the number of seconds between reports.
+
+
io/iostats.stp - List Executables Reading and Writing the Most Data
keywords: io profiling
@@ -539,6 +547,14 @@ keywords: process scheduler time tracepoint
= PROFILING =
+io/iostat-scsi.stp - iostat for SCSI Devices
+keywords: io profiling scsi
+
+ The iostat-scsi.stp script provides a breakdown of the number of blks
+ read and written on the various machines's SCSI devices. The script
+ takes one argument which is the number of seconds between reports.
+
+
io/iostats.stp - List Executables Reading and Writing the Most Data
keywords: io profiling
@@ -667,6 +683,16 @@ keywords: io scheduler backtrace
so is the total delay.
+= SCSI =
+
+io/iostat-scsi.stp - iostat for SCSI Devices
+keywords: io profiling scsi
+
+ The iostat-scsi.stp script provides a breakdown of the number of blks
+ read and written on the various machines's SCSI devices. The script
+ takes one argument which is the number of seconds between reports.
+
+
= SIGNALS =
process/sig_by_pid.stp - Signal Counts by Process ID
diff --git a/testsuite/systemtap.examples/locks/bkl.meta b/testsuite/systemtap.examples/locks/bkl.meta
index e4afabde..61bd4eb7 100644
--- a/testsuite/systemtap.examples/locks/bkl.meta
+++ b/testsuite/systemtap.examples/locks/bkl.meta
@@ -7,4 +7,4 @@ status: production
exit: user-controlled
description: The bkl.stp script can help determine whether the Big Kernel Lock (BKL) is causing serialization on a multiprocessor system due to excessive contention of the BKL. The bkl.stp script takes one argument which is the number of processes waiting for the Big Kernel Lock (BKL). When the number of processes waiting for the BKL is reached or exceeded, the script will print a time stamp, the number of processes waiting for the BKL, the holder of the BKL, and the amount of time the BKL was held.
test_check: stap -p4 bkl.stp 1
-test_installcheck: stap bkl.stp -c "sleep 1" 1
+test_installcheck: stap bkl.stp -c "sleep 0.2" 1
diff --git a/testsuite/systemtap.examples/locks/bkl_stats.meta b/testsuite/systemtap.examples/locks/bkl_stats.meta
index 00d55c68..6db6c72f 100644
--- a/testsuite/systemtap.examples/locks/bkl_stats.meta
+++ b/testsuite/systemtap.examples/locks/bkl_stats.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The bkl_stats.stp script can indicate which processes have excessive waits for the Big Kernel Lock (BKL) and which processes are taking the BKL for long periods of time. The bkl_stats.stp script prints lists of all the processes that require the BKL. Every five seconds two tables are printed out. The first table lists the processes that waited for the BKL followed by the number of times that the process waited, the minimum time of the wait, the average and the maximum time waited. The second table lists has similar information for the time spent holding the lock for each of the processes.
test_check: stap -p4 bkl_stats.stp
-test_installcheck: stap bkl_stats.stp -c "sleep 1"
+test_installcheck: stap bkl_stats.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/memory/kmalloc-top.meta b/testsuite/systemtap.examples/memory/kmalloc-top.meta
index 93308909..f4c2a9d1 100644
--- a/testsuite/systemtap.examples/memory/kmalloc-top.meta
+++ b/testsuite/systemtap.examples/memory/kmalloc-top.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The kmalloc-top perl program runs a small systemtap script to collect stack traces for each call to the kmalloc function and counts the time that each stack trace is observed. When kmalloc-top exits it prints out sorted list. The output can be be filtered to print only only the first stack traces (-t) stack traces with more a minimum counts (-m), or exclude certain stack traces (-e).
test_check: ./kmalloc-top -o "-p4" -c "sleep 0"
-test_installcheck: ./kmalloc-top -c "sleep 1"
+test_installcheck: ./kmalloc-top -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/memory/mmanonpage.meta b/testsuite/systemtap.examples/memory/mmanonpage.meta
index 496d10d8..eb2e9f57 100644
--- a/testsuite/systemtap.examples/memory/mmanonpage.meta
+++ b/testsuite/systemtap.examples/memory/mmanonpage.meta
@@ -9,5 +9,6 @@ exit: user-controlled
output: sorted-list
scope: system-wide
description: The mmanonpage.stp script uses the virtual memory tracepoints available in some kernels to track the number of faults, user space frees, page ins, copy on writes and unmaps for anonymous pages. When the script is terminated the counts are printed for each process that allocated pages while the script was running. This script displays the anonymous page statistics for each process that ran while the script is active. Its useful in debugging leaks in the anonymous regions of a process.
+test_support: stap -l kernel.trace("mm_page_allocation"),kernel.trace("mm_page_free"),kernel.trace("mm_anon_fault"),kernel.trace("mm_anon_pgin"),kernel.trace("mm_anon_cow"),kernel.trace("mm_anon_unmap"),kernel.trace("mm_anon_userfree")
test_check: stap -p4 mmanonpage.stp
-test_installcheck: stap mmanonpage.stp -c "sleep 1"
+test_installcheck: stap mmanonpage.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/memory/mmfilepage.meta b/testsuite/systemtap.examples/memory/mmfilepage.meta
index 3fb6ba55..c26f0601 100644
--- a/testsuite/systemtap.examples/memory/mmfilepage.meta
+++ b/testsuite/systemtap.examples/memory/mmfilepage.meta
@@ -9,5 +9,6 @@ exit: user-controlled
output: sorted-list
scope: system-wide
description: The mmfilepage.stp script uses the virtual memory tracepoints available in some kernels to track the number of faults, copy on writes mapping, and unmapping operations for file backed pages. When the script is terminated the counts are printed for each process that allocated pages while the script was running. The mmfilepage.stp script is useful in debugging leaks in the mapped file regions of a process.
+test_support: stap -l kernel.trace("mm_page_allocation"),kernel.trace("mm_page_free"),kernel.trace("mm_filemap_fault"),kernel.trace("mm_filemap_cow"),kernel.trace("mm_filemap_unmap"),kernel.trace("mm_filemap_userunmap")
test_check: stap -p4 mmfilepage.stp
-test_installcheck: stap mmfilepage.stp -c "sleep 1"
+test_installcheck: stap mmfilepage.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/memory/mmreclaim.meta b/testsuite/systemtap.examples/memory/mmreclaim.meta
index f9c9b523..c3b9cfc6 100644
--- a/testsuite/systemtap.examples/memory/mmreclaim.meta
+++ b/testsuite/systemtap.examples/memory/mmreclaim.meta
@@ -9,5 +9,6 @@ exit: user-controlled
output: sorted-list
scope: system-wide
description: The mmreclaim.stp script uses the virtual memory tracepoints available in some kernels to track page reclaim activity that occured while the script was running. Its useful is debugging performance problems that occur due to page reclamation.
+test_support: stap -l kernel.trace("mm_directreclaim_reclaimall"),kernel.trace("mm_pagereclaim_shrinkinactive"),kernel.trace("mm_pagereclaim_free"),kernel.trace("mm_pagereclaim_pgout"),kernel.trace("mm_pagereclaim_shrinkactive_a2a"),kernel.trace("mm_pagereclaim_shrinkinactive_i2a"),kernel.trace("mm_pagereclaim_shrinkactive_a2i"),kernel.trace("mm_pagereclaim_shrinkinactive_i2i")
test_check: stap -p4 mmreclaim.stp
-test_installcheck: stap mmreclaim.stp -c "sleep 1"
+test_installcheck: stap mmreclaim.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/memory/mmwriteback.meta b/testsuite/systemtap.examples/memory/mmwriteback.meta
index aab0f910..1ad4947c 100644
--- a/testsuite/systemtap.examples/memory/mmwriteback.meta
+++ b/testsuite/systemtap.examples/memory/mmwriteback.meta
@@ -9,5 +9,6 @@ exit: user-controlled
output: sorted-list
scope: system-wide
description: The mmwriteback.stp script uses the virtual memory tracepoints available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a supposedly idle system that is experiencing upexpected IO.
+test_support: stap -l kernel.trace("mm_pdflush_bgwriteout"),kernel.trace("mm_pdflush_kupdate"),kernel.trace("mm_pagereclaim_pgout")
test_check: stap -p4 mmwriteback.stp
-test_installcheck: stap mmwriteback.stp -c "sleep 1"
+test_installcheck: stap mmwriteback.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/memory/numa_faults.meta b/testsuite/systemtap.examples/memory/numa_faults.meta
index 34034bef..51da3fc7 100644
--- a/testsuite/systemtap.examples/memory/numa_faults.meta
+++ b/testsuite/systemtap.examples/memory/numa_faults.meta
@@ -10,4 +10,4 @@ output: list
scope: system-wide
description: The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also providea a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer.
test_check: stap -p4 numa_faults.stp
-test_installcheck: stap numa_faults.stp -c "sleep 1"
+test_installcheck: stap numa_faults.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/memory/pfaults.meta b/testsuite/systemtap.examples/memory/pfaults.meta
index 149d83fa..480e3b24 100644
--- a/testsuite/systemtap.examples/memory/pfaults.meta
+++ b/testsuite/systemtap.examples/memory/pfaults.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occuring.
test_check: stap -p4 pfaults.stp
-test_installcheck: stap pfaults.stp -c "sleep 1"
+test_installcheck: stap pfaults.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/network/autofs4.meta b/testsuite/systemtap.examples/network/autofs4.meta
index 16ae7297..e0036481 100644
--- a/testsuite/systemtap.examples/network/autofs4.meta
+++ b/testsuite/systemtap.examples/network/autofs4.meta
@@ -4,5 +4,6 @@ name: autofs4.stp
author: Jeff Moyer
keywords: network autofs nfs
subsystem: network
+test_support: stap -l module("autofs4").function("autofs4_lookup"),module("autofs4").function("autofs4_follow_link"),module("autofs4").function("autofs4_expire_indirect").return,module("autofs4").function("autofs4_wait").return
test_check: stap -p4 autofs4.stp
-test_installcheck: stap autofs4.stp -c "sleep 10"
+test_installcheck: stap autofs4.stp -c "sleep 1"
diff --git a/testsuite/systemtap.examples/network/dropwatch.meta b/testsuite/systemtap.examples/network/dropwatch.meta
index 176ba236..06d338c5 100644
--- a/testsuite/systemtap.examples/network/dropwatch.meta
+++ b/testsuite/systemtap.examples/network/dropwatch.meta
@@ -9,5 +9,6 @@ exit: user-controlled
output: timed
scope: system-wide
description: Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.
+test_support: stap -l kernel.trace("kfree_skb")
test_check: stap -p4 dropwatch.stp
-test_installcheck: stap dropwatch.stp -c "sleep 1"
+test_installcheck: stap dropwatch.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/network/nettop.meta b/testsuite/systemtap.examples/network/nettop.meta
index 61d1c153..1c3923c7 100644
--- a/testsuite/systemtap.examples/network/nettop.meta
+++ b/testsuite/systemtap.examples/network/nettop.meta
@@ -10,4 +10,4 @@ output: timed
scope: system-wide
description: 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.
test_check: stap -p4 nettop.stp
-test_installcheck: stap nettop.stp -c "sleep 1"
+test_installcheck: stap nettop.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/network/sk_stream_wait_memory.meta b/testsuite/systemtap.examples/network/sk_stream_wait_memory.meta
index bc798f72..186203a1 100644
--- a/testsuite/systemtap.examples/network/sk_stream_wait_memory.meta
+++ b/testsuite/systemtap.examples/network/sk_stream_wait_memory.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: The sk_stream-wait_memory.stp prints a time stamp, executable, and pid each time a process blocks due to the send buffer being full. A similar entry is printed each time a process continues because there is room in the buffer.
test_check: stap -p4 sk_stream_wait_memory.stp
-test_installcheck: stap sk_stream_wait_memory.stp -c "sleep 1"
+test_installcheck: stap sk_stream_wait_memory.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/network/socket-trace.meta b/testsuite/systemtap.examples/network/socket-trace.meta
index 0b26f2fe..f73731b5 100644
--- a/testsuite/systemtap.examples/network/socket-trace.meta
+++ b/testsuite/systemtap.examples/network/socket-trace.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: The script instrument each of the functions inn the Linux kernel's net/socket.c file. The script prints out trace. The first element of a line is time delta in microseconds from the previous entry. This is followed by the command name and the PID. The "->" and "<-" indicates function entry and function exit, respectively. The last element of the line is the function name.
test_check: stap -p4 socket-trace.stp
-test_installcheck: stap socket-trace.stp -c "sleep 1"
+test_installcheck: stap socket-trace.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/network/tcp_connections.meta b/testsuite/systemtap.examples/network/tcp_connections.meta
index 0bc9bcb1..df24850d 100644
--- a/testsuite/systemtap.examples/network/tcp_connections.meta
+++ b/testsuite/systemtap.examples/network/tcp_connections.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: 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.
test_check: stap -p4 tcp_connections.stp
-test_installcheck: stap tcp_connections.stp -c "sleep 1"
+test_installcheck: stap tcp_connections.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/network/tcpdumplike.meta b/testsuite/systemtap.examples/network/tcpdumplike.meta
index 0de45d5e..f5975aa6 100644
--- a/testsuite/systemtap.examples/network/tcpdumplike.meta
+++ b/testsuite/systemtap.examples/network/tcpdumplike.meta
@@ -10,4 +10,4 @@ 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_check: stap -p4 tcpdumplike.stp
-test_installcheck: stap tcpdumplike.stp -c "sleep 1"
+test_installcheck: stap tcpdumplike.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/chng_cpu.meta b/testsuite/systemtap.examples/process/chng_cpu.meta
index 944f417a..7be73b78 100644
--- a/testsuite/systemtap.examples/process/chng_cpu.meta
+++ b/testsuite/systemtap.examples/process/chng_cpu.meta
@@ -11,4 +11,4 @@ scope: pid
description: The chng_cpu.stp script takes an argument which is the executable name of the task it should monitor. Each time a task with that executable name is found running on a different processor, the script prints out the thread id (tid), the executable name, the processor now running the task, the thread state, and a backtrace showing the kernel functions that triggered the running of the task on the processor.
arg_1: The name of the executable to monitor
test_check: stap -p4 chng_cpu.stp bash
-test_installcheck: stap chng_cpu.stp -c "sleep 1" bash
+test_installcheck: stap chng_cpu.stp -c "sleep 0.2" bash
diff --git a/testsuite/systemtap.examples/process/errsnoop.meta b/testsuite/systemtap.examples/process/errsnoop.meta
index 34b8cb7c..8afcdd96 100644
--- a/testsuite/systemtap.examples/process/errsnoop.meta
+++ b/testsuite/systemtap.examples/process/errsnoop.meta
@@ -4,4 +4,4 @@ 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"
+test_installcheck: stap errsnoop.stp 1 10 -c "sleep 1"
diff --git a/testsuite/systemtap.examples/process/forktracker.meta b/testsuite/systemtap.examples/process/forktracker.meta
index 87d43d7a..2ba3a659 100644
--- a/testsuite/systemtap.examples/process/forktracker.meta
+++ b/testsuite/systemtap.examples/process/forktracker.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: The forktracker.stp script prints out a time-stamped entry showing each fork and exec operation on the machine. This can be useful for determine what process is creating a flurry of short-lived processes.
test_check: stap -p4 forktracker.stp
-test_installcheck: stap forktracker.stp -c "sleep 1"
+test_installcheck: stap forktracker.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/futexes.meta b/testsuite/systemtap.examples/process/futexes.meta
index ff303122..404f576d 100644
--- a/testsuite/systemtap.examples/process/futexes.meta
+++ b/testsuite/systemtap.examples/process/futexes.meta
@@ -10,4 +10,4 @@ output: sorted-list on-exit
scope: system-wide
description: 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.
test_check: stap -p4 futexes.stp
-test_installcheck: stap futexes.stp -c "sleep 1"
+test_installcheck: stap futexes.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/migrate.meta b/testsuite/systemtap.examples/process/migrate.meta
index 09a25de0..24e8bdc9 100644
--- a/testsuite/systemtap.examples/process/migrate.meta
+++ b/testsuite/systemtap.examples/process/migrate.meta
@@ -11,4 +11,4 @@ scope: pid
description: The migrate.stp script takes an argument which is the executable name of the task it should monitor. Each time a task with that executable name migrates between processors an entry is printed with the process id (pid), the executable name, the processor off loading the task, and the process taking the task. Note that the task may or may not be executing at the time of the migration.
arg_1: The name of the executable to watch
test_check: stap -p4 migrate.stp bash
-test_installcheck: stap migrate.stp -c "sleep 1" bash
+test_installcheck: stap migrate.stp -c "sleep 0.2" bash
diff --git a/testsuite/systemtap.examples/process/pf2.meta b/testsuite/systemtap.examples/process/pf2.meta
index d0a534bd..8fa14d04 100644
--- a/testsuite/systemtap.examples/process/pf2.meta
+++ b/testsuite/systemtap.examples/process/pf2.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The pf2.stp script sets up time-based sampling. Every five seconds it prints out a sorted list with the top ten kernel functions with samples.
test_check: stap -p4 pf2.stp
-test_installcheck: stap pf2.stp -c "sleep 1"
+test_installcheck: stap pf2.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/schedtimes.meta b/testsuite/systemtap.examples/process/schedtimes.meta
index 0074731f..960d8eda 100644
--- a/testsuite/systemtap.examples/process/schedtimes.meta
+++ b/testsuite/systemtap.examples/process/schedtimes.meta
@@ -9,5 +9,6 @@ exit: user-controlled
output: sorted-list
scope: system-wide
description: The schedtimes.stp script instruments the scheduler to track the amount of time that each process spends running, sleeping, queued, and waiting for io. On exit the script prints out the accumulated time for each state of processes observed. Optionally, this script can be used with the '-c' or '-x' options to focus on a specific PID.
+test_support: stap -l kernel.trace("sched_switch"),kernel.trace("sched_wakeup")
test_check: stap -p4 schedtimes.stp
-test_installcheck: stap schedtimes.stp -c "sleep 1"
+test_installcheck: stap schedtimes.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/sig_by_pid.meta b/testsuite/systemtap.examples/process/sig_by_pid.meta
index 03b02fba..7f371151 100644
--- a/testsuite/systemtap.examples/process/sig_by_pid.meta
+++ b/testsuite/systemtap.examples/process/sig_by_pid.meta
@@ -10,4 +10,4 @@ output: sorted-list on-exit
scope: system-wide
description: Print signal counts by process ID in descending order.
test_check: stap -p4 sig_by_pid.stp
-test_installcheck: stap sig_by_pid.stp -c "sleep 1"
+test_installcheck: stap sig_by_pid.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/sig_by_proc.meta b/testsuite/systemtap.examples/process/sig_by_proc.meta
index eea42be4..8a454373 100644
--- a/testsuite/systemtap.examples/process/sig_by_proc.meta
+++ b/testsuite/systemtap.examples/process/sig_by_proc.meta
@@ -10,4 +10,4 @@ output: sorted-list on-exit
scope: system-wide
description: Print signal counts by process name in descending order.
test_check: stap -p4 sig_by_proc.stp
-test_installcheck: stap sig_by_proc.stp -c "sleep 1"
+test_installcheck: stap sig_by_proc.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/sigkill.meta b/testsuite/systemtap.examples/process/sigkill.meta
index 57032224..b0e04ce8 100644
--- a/testsuite/systemtap.examples/process/sigkill.meta
+++ b/testsuite/systemtap.examples/process/sigkill.meta
@@ -11,4 +11,4 @@ scope: systemwide
description: The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the desination executable and process ID, the executable name user ID that sent the signal.
arg_1: The name of the signal to look for on selected process.
test_check: stap -p4 sigkill.stp
-test_installcheck: stap sigkill.stp -c "sleep 1"
+test_installcheck: stap sigkill.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/sigmon.meta b/testsuite/systemtap.examples/process/sigmon.meta
index fe192248..03c54f96 100644
--- a/testsuite/systemtap.examples/process/sigmon.meta
+++ b/testsuite/systemtap.examples/process/sigmon.meta
@@ -11,4 +11,4 @@ scope: pid
description: The script watches for a particular signal sent to a specific process. When that signal is sent to the specified process, the script prints out the PID and executable of the process sending the signal, the PID and executable name of the process receiving the signal, and the signal number and name.
arg_1: The name of the signal to look for on selected process.
test_check: stap -p4 sigmon.stp SIGKILL
-test_installcheck: stap sigmon.stp -c "sleep 1" SIGKILL
+test_installcheck: stap sigmon.stp -c "sleep 0.2" SIGKILL
diff --git a/testsuite/systemtap.examples/process/sleepingBeauties.meta b/testsuite/systemtap.examples/process/sleepingBeauties.meta
index 3338edbf..b2692ba0 100644
--- a/testsuite/systemtap.examples/process/sleepingBeauties.meta
+++ b/testsuite/systemtap.examples/process/sleepingBeauties.meta
@@ -4,4 +4,4 @@ keywords: io scheduler backtrace
subsystem: scheduler
description: The script monitors the time that threads spend waiting for IO operations (in "D" state) in the wait_for_completion function. If a thread spends over 10ms, its name and backtrace is printed, and later so is the total delay.
test_check: stap -p4 sleepingBeauties.stp
-test_installcheck: stap sleepingBeauties.stp -c "sleep 1"
+test_installcheck: stap sleepingBeauties.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/sleeptime.meta b/testsuite/systemtap.examples/process/sleeptime.meta
index d6c59345..7318c7aa 100644
--- a/testsuite/systemtap.examples/process/sleeptime.meta
+++ b/testsuite/systemtap.examples/process/sleeptime.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "nanosleep:" key, and the duration of the sleep in microseconds.
test_check: stap -p4 sleeptime.stp
-test_installcheck: stap sleeptime.stp -c "sleep 1"
+test_installcheck: stap sleeptime.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/syscalls_by_pid.meta b/testsuite/systemtap.examples/process/syscalls_by_pid.meta
index 590652b3..65bb97ac 100644
--- a/testsuite/systemtap.examples/process/syscalls_by_pid.meta
+++ b/testsuite/systemtap.examples/process/syscalls_by_pid.meta
@@ -10,4 +10,4 @@ output: sorted-list on-exit
scope: system-wide
description: The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each PID ordered from greatest to least number of syscalls.
test_check: stap -p4 syscalls_by_pid.stp
-test_installcheck: stap syscalls_by_pid.stp -c "sleep 1"
+test_installcheck: stap syscalls_by_pid.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/syscalls_by_proc.meta b/testsuite/systemtap.examples/process/syscalls_by_proc.meta
index 79aa3e87..42668bc8 100644
--- a/testsuite/systemtap.examples/process/syscalls_by_proc.meta
+++ b/testsuite/systemtap.examples/process/syscalls_by_proc.meta
@@ -10,4 +10,4 @@ output: sorted-list on-exit
scope: system-wide
description: The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greates to least number of syscalls.
test_check: stap -p4 syscalls_by_proc.stp
-test_installcheck: stap syscalls_by_proc.stp -c "sleep 1"
+test_installcheck: stap syscalls_by_proc.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/process/wait4time.meta b/testsuite/systemtap.examples/process/wait4time.meta
index a939d466..e798014b 100644
--- a/testsuite/systemtap.examples/process/wait4time.meta
+++ b/testsuite/systemtap.examples/process/wait4time.meta
@@ -10,4 +10,4 @@ output: trace
scope: system-wide
description: The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1".
test_check: stap -p4 wait4time.stp
-test_installcheck: stap wait4time.stp -c "sleep 1"
+test_installcheck: stap wait4time.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/profiling/functioncallcount.meta b/testsuite/systemtap.examples/profiling/functioncallcount.meta
index 4d419528..682b2f95 100644
--- a/testsuite/systemtap.examples/profiling/functioncallcount.meta
+++ b/testsuite/systemtap.examples/profiling/functioncallcount.meta
@@ -10,4 +10,4 @@ output: sorted-list on-exit
scope: system-wide
description: The functioncallcount.stp script takes one argument, a list of functions to probe. The script will run and count the number of times that each of the functions on the list is called. On exit the script will print a sorted list from most frequently to least frequently called function.
test_check: stap -p4 functioncallcount.stp "*@mm/*.c"
-test_installcheck: stap functioncallcount.stp "*@mm/*.c" -c "sleep 1"
+test_installcheck: stap functioncallcount.stp "*@mm/*.c" -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/profiling/thread-times.meta b/testsuite/systemtap.examples/profiling/thread-times.meta
index fcbf062e..3cb3e93d 100644
--- a/testsuite/systemtap.examples/profiling/thread-times.meta
+++ b/testsuite/systemtap.examples/profiling/thread-times.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The thread-times.stp script sets up time-based sampling. Every five seconds it prints out a sorted list with the top twenty processes with samples broken down into percentage total time spent in user-space and kernel-space.
test_check: stap -p4 thread-times.stp
-test_installcheck: stap thread-times.stp -c "sleep 1"
+test_installcheck: stap thread-times.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/profiling/timeout.meta b/testsuite/systemtap.examples/profiling/timeout.meta
index aa683c0a..a91ea1ec 100644
--- a/testsuite/systemtap.examples/profiling/timeout.meta
+++ b/testsuite/systemtap.examples/profiling/timeout.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The timeout.stp script is based on a blog entry (http://udrepper.livejournal.com/19041.html) mentioning a need for a tool to help developers find applications that are polling. The timeout.stp script monitors systemcall used for polling and records the systemcalls that timed out rather than returned because some action occurred. The script updates the screen once a second with the top twenty processes.
test_check: stap -p4 timeout.stp
-test_installcheck: stap timeout.stp -c "sleep 1"
+test_installcheck: stap timeout.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.examples/profiling/topsys.meta b/testsuite/systemtap.examples/profiling/topsys.meta
index 3642713d..f764ee49 100644
--- a/testsuite/systemtap.examples/profiling/topsys.meta
+++ b/testsuite/systemtap.examples/profiling/topsys.meta
@@ -10,4 +10,4 @@ output: sorted-list
scope: system-wide
description: The topsys.stp script lists out the top twenty systemcalls for the previous 5 seconds. The output is sorted from most frequent to least frequent.
test_check: stap -p4 topsys.stp
-test_installcheck: stap topsys.stp -c "sleep 1"
+test_installcheck: stap topsys.stp -c "sleep 0.2"
diff --git a/testsuite/systemtap.exelib/exelib.exp b/testsuite/systemtap.exelib/exelib.exp
index bd9c687e..1337d545 100644
--- a/testsuite/systemtap.exelib/exelib.exp
+++ b/testsuite/systemtap.exelib/exelib.exp
@@ -2,7 +2,11 @@
# (with gcc/g++, -O0/-O3, prelinked/pie, seperate debuginfo)
# Then runs tests with a list of execs.
-set subtestlist {lib mark uname ustack cleanup}
+# Don't enable all sub-tests by default, enable them separately when
+# you want to track down an issue.
+# Enable just the all-in-one test for regular test runs to safe time
+#set subtestlist {lib mark uname ustack cleanup}
+set subtestlist {libmarkunamestack cleanup}
proc seperate_debuginfo {elffile} {
set objcopy [list "objcopy" "--only-keep-debug"]
@@ -44,9 +48,9 @@ foreach arch $arches {
# and exploded the test search case a bit.
foreach compiler {gcc} { # Add g++
- # Just try -O0 and -O3.
- # Adding -O, -O2, -Os and mixing lib/exe is a bit overdone
- foreach opt {-O0 -O3} {
+ # Just try -O3.
+ # Adding -O0, -O, -O2, -Os and mixing lib/exe is a bit overdone
+ foreach opt {-O3} {
foreach libprelink {no yes} {
diff --git a/testsuite/systemtap.exelib/libmarkunamestack.stp b/testsuite/systemtap.exelib/libmarkunamestack.stp
new file mode 100644
index 00000000..0efbae0e
--- /dev/null
+++ b/testsuite/systemtap.exelib/libmarkunamestack.stp
@@ -0,0 +1,72 @@
+// Jumbo stp script
+// Arguments: @1 uprobes_exe, @2 libuprobes_lib.so
+
+# lib
+probe process(@1).function("main") {
+ printf("main\n");
+}
+
+probe process(@1).function("main_func") {
+ printf("main_func\n");
+}
+
+probe process(@2).function("lib_main") {
+ printf("lib_main\n");
+}
+
+probe process(@2).function("lib_func") {
+ printf("lib_func\n");
+}
+
+#mark
+probe process(@1).mark("main_count") {
+ printf("main_count: %d\n", $arg1);
+}
+
+probe process(@2).mark("func_count") {
+ printf("func_count: %d\n", $arg1);
+}
+
+#uname
+probe process(@1).function("*") {
+ printf("exe: %s=%s\n",probefunc(), usymname(uaddr()));
+}
+
+probe process(@2).function("*") {
+ printf("lib: %s=%s\n",probefunc(), usymname(uaddr()));
+}
+
+# ustack
+global hits = 0;
+
+probe process(@1).function("main_func")
+{
+ if (hits == 0)
+ {
+ log("print_ubacktrace exe 0");
+ print_ubacktrace();
+ hits++;
+ }
+ else if (hits == 1)
+ {
+ log("print_ustack exe 1");
+ print_ustack(ubacktrace());
+ hits++;
+ }
+}
+
+probe process(@2).function("lib_func")
+{
+ if (hits == 2)
+ {
+ log("print_ubacktrace lib 2");
+ print_ubacktrace();
+ hits++;
+ }
+ else if (hits == 3)
+ {
+ log("print_ustack lib 3");
+ print_ustack(ubacktrace());
+ hits++;
+ }
+}
diff --git a/testsuite/systemtap.exelib/libmarkunamestack.tcl b/testsuite/systemtap.exelib/libmarkunamestack.tcl
new file mode 100644
index 00000000..55dc10ee
--- /dev/null
+++ b/testsuite/systemtap.exelib/libmarkunamestack.tcl
@@ -0,0 +1,104 @@
+# Only run on make installcheck
+if {! [installtest_p]} { untested "libmarkunamestack-$testname"; return }
+if {! [uprobes_p]} { untested "libmarkunamestack-$testname"; return }
+
+# Big jumbo test, for tracking down bugs, use the individual tests.
+
+# Output for ustack part is:
+#print_ubacktrace exe 0
+# 0x080484ba : main_func+0xa/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+#print_ustack exe 1
+# 0x080484ba : main_func+0xa/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+#print_ubacktrace lib 2
+# 0x00db2422 : lib_func+0x16/0x2b [.../libuprobes_lib.so]
+# 0x00db2455 : lib_main+0x1e/0x29 [.../libuprobes_lib.so]
+# 0x080484d0 : main_func+0x20/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+#print_ustack lib 3
+# 0x00db2422 : lib_func+0x16/0x2b [.../libuprobes_lib.so]
+# 0x00db2431 : lib_func+0x25/0x2b [.../libuprobes_lib.so]
+# 0x00db2455 : lib_main+0x1e/0x29 [.../libuprobes_lib.so]
+# 0x080484d0 : main_func+0x20/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+
+set lib 0
+set mark 0
+set uname 0
+
+set print 0
+set main 0
+set main_func 0
+set lib_main 0
+set lib_func 0
+send_log "Running: stap $srcdir/$subdir/libmarkunamestack.stp $testexe $testlib -c $testexe\n"
+spawn stap $srcdir/$subdir/libmarkunamestack.stp $testexe $testlib -c $testexe
+
+wait -i $spawn_id
+expect {
+ -timeout 60
+ -re {^print_[^\r\n]+\r\n} {incr print; exp_continue}
+
+# lib
+ -re {^main\r\n} {incr lib; exp_continue}
+ -re {^main_func\r\n} {incr lib; exp_continue}
+ -re {^lib_main\r\n} {incr lib; exp_continue}
+ -re {^lib_func\r\n} {incr lib; exp_continue}
+
+# mark
+ -re {^main_count: [1-3]\r\n} {incr mark; exp_continue}
+ -re {^func_count: [1-3]\r\n} {incr mark; exp_continue}
+
+# uname
+ -re {^exe: main=main\r\n} {incr uname; exp_continue}
+ -re {^exe: main_func=main_func\r\n} {incr uname; exp_continue}
+ -re {^lib: lib_main=lib_main\r\n} {incr uname; exp_continue}
+ -re {^lib: lib_func=lib_func\r\n} {incr uname; exp_continue}
+
+# ustack
+ -re {^ 0x[a-f0-9]+ : main\+0x[^\r\n]+\r\n} {incr main; exp_continue}
+ -re {^ 0x[a-f0-9]+ : main_func\+0x[^\r\n]+\r\n} {incr main_func; exp_continue}
+ -re {^ 0x[a-f0-9]+ : lib_main\+0x[^\r\n]+\r\n} {incr lib_main; exp_continue}
+ -re {^ 0x[a-f0-9]+ : lib_func\+0x[^\r\n]+\r\n} {incr lib_func; exp_continue}
+
+ timeout { fail "libmarkunamestack-$testname (timeout)" }
+ eof { }
+}
+
+if {$lib == 8} { pass "lib-$testname" } {
+ fail "lib-$testname ($lib)"
+}
+
+if {$mark == 6} { pass "mark-$testname" } {
+ fail "mark-$testname ($mark)"
+}
+
+if {$uname == 8} { pass "uname-$testname" } {
+ fail "uname-$testname ($uname)"
+}
+
+if {$print == 4} { pass "ustack-$testname print" } {
+ fail "ustack-$testname print ($print)"
+}
+
+if {$main == 4} { pass "ustack-$testname main" } {
+ fail "ustack-$testname main ($main)"
+}
+
+if {$main_func == 9} { pass "ustack-$testname main_func" } {
+ fail "ustack-$testname main_func ($main_func)"
+}
+
+if {$lib_main == 2} { pass "ustack-$testname lib_main" } {
+ fail "ustack-$testname lib_main ($lib_main)"
+}
+
+if {$lib_func == 3} { pass "ustack-$testname lib_func" } {
+ fail "ustack-$testname lib_func ($lib_func)"
+}
diff --git a/testsuite/systemtap.syscall/syscall.exp b/testsuite/systemtap.syscall/syscall.exp
index 22e9dc07..a4978997 100644
--- a/testsuite/systemtap.syscall/syscall.exp
+++ b/testsuite/systemtap.syscall/syscall.exp
@@ -32,17 +32,9 @@ proc test_procedure {} {
if {$do_64_bit_pass} {
foreach filename [lsort [glob $pattern]] {
set testname [file tail [string range $filename 0 end-2]]
- if {![installtest_p]} { untested $testname; continue }
+ if {![installtest_p]} { untested "64-bit $testname"; continue }
send_log "Testing 64-bit ${testname}\n"
- set res [run_one_test $filename $flags]
- if {$res == "PASS"} {
- pass "$testname"
- } elseif {$res == "UNSUPP"} {
- unsupported "$testname not supported on this arch"
- } else {
- fail "64-bit $testname"
- send_log "$res\n"
- }
+ run_one_test $filename $flags 64
}
}
@@ -56,17 +48,9 @@ proc test_procedure {} {
if {$do_32_bit_pass} {
foreach filename [lsort [glob $pattern]] {
set testname [file tail [string range $filename 0 end-2]]
- if {![installtest_p]} { untested $testname; continue }
+ if {![installtest_p]} { untested "32-bit $testname"; continue }
send_log "Testing 32-bit ${testname}\n"
- set res [run_one_test $filename $flags]
- if {$res == "PASS"} {
- pass "32-bit $testname"
- } elseif {$res == "UNSUPP"} {
- unsupported "$testname not supported on this arch"
- } else {
- fail "32-bit $testname"
- send_log "$res\n"
- }
+ run_one_test $filename $flags 32
}
}
}
diff --git a/testsuite/systemtap.syscall/test.tcl b/testsuite/systemtap.syscall/test.tcl
index 8a5801af..b9d3c0d9 100755
--- a/testsuite/systemtap.syscall/test.tcl
+++ b/testsuite/systemtap.syscall/test.tcl
@@ -26,19 +26,23 @@ proc bgerror {error} {
}
trap {cleanup_and_exit} SIGINT
-proc run_one_test {filename flags} {
+proc run_one_test {filename flags bits} {
global dir current_dir
set testname [file tail [string range $filename 0 end-2]]
- set result "UNSUPP"
if {[catch {exec mktemp -d [pwd]/staptestXXXXXX} dir]} {
puts stderr "Failed to create temporary directory: $dir"
cleanup
}
- target_compile $filename $dir/$testname executable $flags
-
+ set res [target_compile $filename $dir/$testname executable $flags]
+ if { $res != "" } {
+ send_log "$bits-bit $testname : no corresponding devel environment found\n"
+ untested "$bits-bit $testname"
+ return
+ }
+
set sys_prog "[file dirname [file normalize $filename]]/sys.stp"
set cmd "stap --skip-badvars -c $dir/${testname} ${sys_prog}"
@@ -74,7 +78,8 @@ proc run_one_test {filename flags} {
if {$ind == 0} {
# unsupported
cleanup
- return $result
+ unsupported "$bits-bit $testname not supported on this arch"
+ return
}
set current_dir [pwd]
@@ -91,10 +96,9 @@ proc run_one_test {filename flags} {
}
}
if {$i >= $ind} {
- set result "PASS"
# puts "PASS $testname"
+ pass "$bits-bit $testname"
} else {
- set result "FAIL $testname"
send_log "$testname FAILED. output of \"$cmd\" was:"
send_log "\n------------------------------------------\n"
send_log $output
@@ -118,7 +122,8 @@ proc run_one_test {filename flags} {
for {} {$i < $ind} {incr i} {
send_log "$results($i)\n"
}
+ fail "$bits-bit $testname"
}
cleanup
- return $result
+ return
}
diff --git a/translate.cxx b/translate.cxx
index 9a25df61..e32f932a 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1161,22 +1161,12 @@ c_unparser::emit_module_init ()
o->newline(-1) << "}";
o->newline() << "#endif";
- // PR10228: set up symbol table-related task finders
- o->newline() << "#if defined(STP_NEED_VMA_TRACKER) && defined(CONFIG_UTRACE)";
+ // PR10228: set up symbol table-related task finders.
+ o->newline() << "#if defined(STP_NEED_VMA_TRACKER)";
o->newline() << "_stp_sym_init();";
- o->newline() << "for (i=0; i<_stp_num_modules; i++) {";
- o->newline(1) << "if (_stp_modules[i]->vmcb) {";
- o->newline(1) << "rc = stap_register_task_finder_target (_stp_modules[i]->vmcb);";
- o->newline() << "if (rc) {";
- o->newline(1) << "_stp_error ("
- << "\"couldn't initialize task-finder for %s\\n\","
- << "_stp_modules[i]->vmcb->procname);";
- o->newline() << "goto out;";
- o->newline(-1) << "}";
- o->newline(-1) << "}";
- o->newline(-1) << "}";
o->newline() << "#endif";
-
+ // NB: we don't need per-_stp_module task_finders, since a single common one
+ // set up in runtime/sym.c's _stp_sym_init() will scan through all _stp_modules.
o->newline() << "(void) probe_point;";
o->newline() << "(void) i;";
o->newline() << "(void) j;";
@@ -4857,27 +4847,9 @@ dump_unwindsyms (Dwfl_Module *m,
mainfile = canonicalize_file_name(mainfile);
- // PR10228: populate the task_finder_vmcb.
- if (modname[0] == '/') // user-space module
- {
- // NB: runtime/sym.c
- c->output << "static struct stap_task_finder_target _stp_vmcb_" << stpmod_idx << "= {\n";
- c->output << "#ifdef CONFIG_UTRACE\n";
- c->output << ".procname = " << lex_cast_qstring (mainfile) << ",\n";
- c->output << ".mmap_callback = &_stp_tf_mmap_cb,\n";
- c->output << ".munmap_callback = &_stp_tf_munmap_cb,\n";
- c->output << "#endif\n";
- c->output << "};\n";
- }
-
c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n";
c->output << ".name = " << lex_cast_qstring (modname) << ", \n";
c->output << ".path = " << lex_cast_qstring (mainfile) << ",\n";
-
- // PR10228: populate the task_finder_vmcb.
- if (modname[0] == '/') // user-space module
- c->output << ".vmcb = & _stp_vmcb_" << stpmod_idx << ",\n";
-
c->output << ".dwarf_module_base = 0x" << hex << base << dec << ", \n";
c->output << ".eh_frame_addr = 0x" << hex << eh_addr << dec << ", \n";
@@ -4928,11 +4900,12 @@ dump_unwindsyms (Dwfl_Module *m,
c->output << ".build_id_len = " << build_id_len << ",\n";
/* XXX: kernel data boot-time relocation works differently from text.
- This hack disables relocation altogether, but that's not necessarily
+ This hack assumes that offset between _stext and build id
+ stays constant after relocation, but that's not necessarily
correct either. We may instead need a relocation basis different
from _stext, such as __start_notes. */
if (modname == "kernel")
- c->output << ".build_id_offset = 0x" << hex << build_id_vaddr
+ c->output << ".build_id_offset = 0x" << hex << build_id_vaddr - (base + extra_offset)
<< dec << ",\n";
else
c->output << ".build_id_offset = 0x" << hex
diff --git a/translate.h b/translate.h
index d1bff678..5a0e0a4a 100644
--- a/translate.h
+++ b/translate.h
@@ -33,7 +33,7 @@ public:
std::ostream& newline (int indent = 0);
void indent (int indent = 0);
- void assert_0_indent () { assert (tablevel == 0); }
+ void assert_0_indent () { o << std::flush; assert (tablevel == 0); }
std::ostream& line();
std::ostream::pos_type tellp() { return o.tellp(); }
diff --git a/util.h b/util.h
index b38d01fd..24845545 100644
--- a/util.h
+++ b/util.h
@@ -97,4 +97,16 @@ lex_cast_qstring(std::string const & in)
return out;
}
+
+// Delete all values from a map-like container and clear it
+// (The template is permissive -- be good!)
+template <typename T>
+void delete_map(T& t)
+{
+ for (typename T::iterator i = t.begin(); i != t.end(); ++i)
+ delete i->second;
+ t.clear();
+}
+
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */