summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-04-12 11:03:19 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-04-12 11:03:19 -0400
commit1c86aa2adc1165906057cdde4cc7484468726fc4 (patch)
treee4da7047f20489b9fc4b11cf501d42cf59c4b283
parentb53c1feef55dc74501a90257e4beff6c1a9cf03b (diff)
parent48899faa2d1280f7715b0abf892fb8b4b5c8ff43 (diff)
downloadsystemtap-steved-1c86aa2adc1165906057cdde4cc7484468726fc4.tar.gz
systemtap-steved-1c86aa2adc1165906057cdde4cc7484468726fc4.tar.xz
systemtap-steved-1c86aa2adc1165906057cdde4cc7484468726fc4.zip
Merge branch 'master' into unwind
* master: 2008-04-11 David Smith <dsmith@redhat.com> 2008-04-11 David Smith <dsmith@redhat.com> 2008-04-11 David Smith <dsmith@redhat.com> PR2949: add missing line PR2949: listings mode (stap -l PROBE) PR6393: don't bother print build (configure) date any more, with reliable git ids PR6393: regenerate git_version.h at every make PR6393: git version tagging at build time 2008-04-09 David Smith <dsmith@redhat.com> 2008-04-04 Masami Hiramatsu <mhiramat@redhat.com> 2008-04-04 David Smith <dsmith@redhat.com> 2008-04-04 Masami Hiramatsu <mhiramat@redhat.com> removing another part of retired LKET removing abandoned experiment: safety/* disassembly/symbol checks Conflicts: .gitignore ChangeLog runtime/ChangeLog
-rw-r--r--.gitignore2
-rw-r--r--ChangeLog68
-rw-r--r--Makefile.am52
-rw-r--r--Makefile.in45
-rw-r--r--NEWS12
-rwxr-xr-xconfigure7
-rw-r--r--configure.ac7
-rw-r--r--doc/.gitignore8
-rw-r--r--doc/ChangeLog4
-rw-r--r--elaborate.cxx3
-rw-r--r--elaborate.h8
-rwxr-xr-xgit_version.sh348
-rw-r--r--main.cxx191
-rw-r--r--runtime/ChangeLog17
-rw-r--r--runtime/loc2c-runtime.h2
-rw-r--r--runtime/regs-ia64.c15
-rw-r--r--runtime/task_finder.c410
-rw-r--r--session.h1
-rw-r--r--stap.1.in14
-rw-r--r--stapex.5.in6
-rw-r--r--tapsets.cxx55
-rw-r--r--testsuite/.gitignore4
-rw-r--r--testsuite/ChangeLog11
-rw-r--r--testsuite/systemtap.base/cmd_parse.exp9
-rw-r--r--testsuite/systemtap.stress/conversions.exp5
-rw-r--r--translate.cxx11
26 files changed, 1201 insertions, 114 deletions
diff --git a/.gitignore b/.gitignore
index 90261357..ca2522a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,6 @@ CVS
.metadata
.project
.settings
+SNAPSHOT
*.o
+git_version.h
diff --git a/ChangeLog b/ChangeLog
index f2959b3b..7f3d347a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,74 @@
* translate.cxx (emit_symbol_data): When available,
grab symbols from debuginfo instead of /proc/kallsyms.
+2008-04-11 David Smith <dsmith@redhat.com>
+
+ * elaborate.h (struct derived_probe_group): Added
+ emit_module_header virtual function.
+ * translate.cxx (c_unparser::emit_common_header): Calls each probe
+ group's emit_module_header function.
+ (translate_pass): Moved inclusion of linux/marker.h to
+ mark_derived_probe_group::emit_module_header().
+ * tapsets.cxx (struct be_derived_probe_group): Added empty
+ emit_module_header function.
+ (struct timer_derived_probe_group): Ditto.
+ (struct profile_derived_probe_group): Ditto.
+ (struct procfs_derived_probe_group): Ditto.
+ (struct hrtimer_derived_probe_group): Ditto.
+ (struct perfmon_derived_probe_group): Ditto.
+ (dwarf_derived_probe_group::emit_module_header): Moved kprobes
+ kernel check from emit_module_decls() to here.
+ (uprobe_derived_probe_group::emit_module_header): Moved uprobe
+ kernel check from emit_module_decls() to here.
+ (uprobe_derived_probe_group::emit_module_decls): Moved uprobe
+ kernel check to emit_module_header().
+ (mark_derived_probe_group::emit_module_header): Moved marker
+ kernel check from emit_module_decls and translate_pass() to here.
+ (uprobe_derived_probe_group::emit_module_decls): Moved marker
+ kernel check to emit_module_header().
+
+2008-04-10 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 2949.
+ * session.h (listing_mode): New field.
+ * main.cxx (main): Test it. Enjoy it.
+ (printscript): Do it.
+ (usage): Document it.
+ * stap.1.in, stapex.5.in: Ditto.
+ * elaborate.cxx (print_error): Disable error messages in listing mode.
+
+2008-04-10 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 6393 cont'd.
+ * Makefile.am: Also copy RadeonHD.am fragment to force
+ git_version.h regeneration at every make, and also special
+ tagging for "make dist". Thanks <ndim>.
+
+2008-04-10 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 6393.
+ * git_version.sh: New file, copied from radeonhd.
+ * configure.ac: No longer generate $builddir/SNAPSHOT.
+ * Makefile.am: Generate $builddir/git_version.h.
+ (EXTRA_DIST): Add git_version.h and git_version.sh.
+ * main.cxx (version): Print generated GIT_MESSAGE therefrom.
+ * Makefile.in, configure: Regenerated.
+
+2008-04-09 David Smith <dsmith@redhat.com>
+
+ * .gitignore: Added more files to ignore.
+
+2008-04-04 Masami Hiramatsu <mhiramat@redhat.com>
+
+ PR 6028
+ * translate.cxx (c_unparser::emit_common_header): Add unwaddr for
+ caching unwound address.
+ * tapsets.cxx (common_probe_entryfn_prologue): Clear unwaddr.
+
+2008-04-01 Frank Ch. Eigler <fche@elastic.org>
+
+ * safety/*: Removed subdirectory containing abandoned experiment.
+
2008-03-31 Frank Ch. Eigler <fche@elastic.org>
* configure.ac: Bump version to 0.7.
diff --git a/Makefile.am b/Makefile.am
index a53fdba0..66df81cf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,12 +18,53 @@ stap_SOURCES = main.cxx \
cache.cxx util.cxx coveragedb.cxx
stap_LDADD = @stap_LIBS@ @sqlite3_LIBS@
+BUILT_SOURCES =
+CLEANFILES =
+
+# Arrange for git_version.h to be regenerated at every "make".
+# Code fragment is based upon RadeonHD.am.
+
+# The stamp file which is never created ensures that git_version.h is updated
+# before every build. Having git_version.h in foo_SOURCES ensures a recompile
+# of foo-bar.c if it is newer than the foo-bar.o file. Using noinst_foo_SOURCES
+# instead of foo_SOURCES prevents shipping git_version.h in dist tarballs,
+# which may cause false GIT_FOO readings.
+BUILT_SOURCES += git_version.stamp
+CLEANFILES += git_version.h
+GIT_VERSION_CMD = $(SHELL) $(top_srcdir)/git_version.sh
+git_version.stamp:
+ @if test -f "$(srcdir)/git_version.h"; then \
+ if test -f "git_version.h"; then :; \
+ else \
+ cp "$(srcdir)/git_version.h" "git_version.h"; \
+ fi; \
+ fi
+ $(GIT_VERSION_CMD) -k -s $(top_srcdir) -o git_version.h
+ @if test -s "$(srcdir)/git_version.h"; then \
+ if cmp "$(srcdir)/git_version.h" "git_version.h"; then :; \
+ else \
+ echo "Error: $(srcdir)/git_version.h and git_version.h differ."; \
+ echo " You probably want to remove the former."; \
+ exit 1; \
+ fi; \
+ fi
+
+dist-gitversion: git_version.stamp
+ if test -f "git_version.h"; then \
+ sed -e 's|^#undef GIT_IS_DIST.*|#define GIT_IS_DIST 1|' \
+ "git_version.h" > "$(distdir)/git_version.h"; \
+ fi
+
+
+git_version.h:
+ $(srcdir)/git_version.sh -k --srcdir $(srcdir) -o git_version.h
+
+
+
stap_CXXFLAGS = $(AM_CXXFLAGS)
stap_CPPFLAGS = $(AM_CPPFLAGS)
stap_LDFLAGS = $(AM_LDFLAGS)
-CLEANFILES =
-
if BUILD_ELFUTILS
# This tells automake's "make distcheck" what we need to compile.
DISTCHECK_CONFIGURE_FLAGS = --with-elfutils=$(elfutils_abs_srcdir)
@@ -31,7 +72,7 @@ DISTCHECK_CONFIGURE_FLAGS = --with-elfutils=$(elfutils_abs_srcdir)
stap_CPPFLAGS += -Iinclude-elfutils
stap_LDFLAGS += -Llib-elfutils -Wl,-rpath-link,lib-elfutils \
-Wl,--enable-new-dtags,-rpath,$(pkglibdir)
-BUILT_SOURCES = stamp-elfutils
+BUILT_SOURCES += stamp-elfutils
CLEANFILES += stamp-elfutils
stamp-elfutils: config.status
$(MAKE) $(AM_MAKEFLAGS) -C build-elfutils all
@@ -102,7 +143,8 @@ LDADD =
EXTRA_DIST = buildrun.h elaborate.h loc2c.h session.h \
parse.h staptree.h tapsets.h translate.h \
cache.h hash.h mdfour.h util.h staplog.c coveragedb.h \
- examples testsuite systemtap.spec runtime tapset
+ examples testsuite systemtap.spec runtime tapset \
+ git_version.h git_version.sh
SAMPLE_DEST_DIR = $(distdir)/examples/samples
@@ -121,7 +163,7 @@ dist-add-samples: $(SAMPLE_SRC)
mkdir -p $(SAMPLE_DEST_DIR)
cp $(SAMPLE_SRC) $(SAMPLE_DEST_DIR)
-dist-hook: dist-add-samples
+dist-hook: dist-add-samples dist-gitversion
find $(distdir) -name CVS -o -name '*~' -o -name '.#*' | xargs rm -rf
find $(distdir) -name '*.o' -o -name '*.ko' -o -name '*.cmd' -o -name '*.mod.c' -o -name '.??*' | xargs rm -rf
find $(distdir) -name 'stap' -o -name '*.log' -o -name '*.sum' -o -name 'site.exp' | xargs rm -rf
diff --git a/Makefile.in b/Makefile.in
index 9fc103d3..f9822cac 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -38,6 +38,7 @@ bin_PROGRAMS = stap$(EXEEXT) staprun$(EXEEXT)
@BUILD_ELFUTILS_TRUE@ -Wl,--enable-new-dtags,-rpath,$(pkglibdir)
@BUILD_ELFUTILS_TRUE@am__append_3 = stamp-elfutils
+@BUILD_ELFUTILS_TRUE@am__append_4 = stamp-elfutils
@BUILD_ELFUTILS_FALSE@stap_DEPENDENCIES =
pkglibexec_PROGRAMS = stapio$(EXEEXT)
noinst_PROGRAMS = loc2c-test$(EXEEXT)
@@ -275,14 +276,24 @@ stap_SOURCES = main.cxx \
cache.cxx util.cxx coveragedb.cxx
stap_LDADD = @stap_LIBS@ @sqlite3_LIBS@
+
+# Arrange for git_version.h to be regenerated at every "make".
+# Code fragment is based upon RadeonHD.am.
+
+# The stamp file which is never created ensures that git_version.h is updated
+# before every build. Having git_version.h in foo_SOURCES ensures a recompile
+# of foo-bar.c if it is newer than the foo-bar.o file. Using noinst_foo_SOURCES
+# instead of foo_SOURCES prevents shipping git_version.h in dist tarballs,
+# which may cause false GIT_FOO readings.
+BUILT_SOURCES = git_version.stamp $(am__append_3)
+CLEANFILES = git_version.h $(am__append_4) $(pkglibexec_PROGRAMS)
+GIT_VERSION_CMD = $(SHELL) $(top_srcdir)/git_version.sh
stap_CXXFLAGS = $(AM_CXXFLAGS)
stap_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_1)
stap_LDFLAGS = $(AM_LDFLAGS) $(am__append_2)
-CLEANFILES = $(am__append_3) $(pkglibexec_PROGRAMS)
# This tells automake's "make distcheck" what we need to compile.
@BUILD_ELFUTILS_TRUE@DISTCHECK_CONFIGURE_FLAGS = --with-elfutils=$(elfutils_abs_srcdir)
-@BUILD_ELFUTILS_TRUE@BUILT_SOURCES = stamp-elfutils
@BUILD_ELFUTILS_TRUE@stap_DEPENDENCIES = lib-elfutils/libdw.so
staprun_SOURCES = runtime/staprun/staprun.c runtime/staprun/staprun_funcs.c\
runtime/staprun/ctl.c runtime/staprun/common.c \
@@ -311,7 +322,8 @@ LDADD =
EXTRA_DIST = buildrun.h elaborate.h loc2c.h session.h \
parse.h staptree.h tapsets.h translate.h \
cache.h hash.h mdfour.h util.h staplog.c coveragedb.h \
- examples testsuite systemtap.spec runtime tapset
+ examples testsuite systemtap.spec runtime tapset \
+ git_version.h git_version.sh
SAMPLE_DEST_DIR = $(distdir)/examples/samples
SAMPLE_SRC = $(srcdir)/testsuite/systemtap.samples/iotask.stp \
@@ -1458,6 +1470,31 @@ uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
uninstall-man uninstall-man1 uninstall-man5 uninstall-man8 \
uninstall-pkglibexecPROGRAMS
+git_version.stamp:
+ @if test -f "$(srcdir)/git_version.h"; then \
+ if test -f "git_version.h"; then :; \
+ else \
+ cp "$(srcdir)/git_version.h" "git_version.h"; \
+ fi; \
+ fi
+ $(GIT_VERSION_CMD) -k -s $(top_srcdir) -o git_version.h
+ @if test -s "$(srcdir)/git_version.h"; then \
+ if cmp "$(srcdir)/git_version.h" "git_version.h"; then :; \
+ else \
+ echo "Error: $(srcdir)/git_version.h and git_version.h differ."; \
+ echo " You probably want to remove the former."; \
+ exit 1; \
+ fi; \
+ fi
+
+dist-gitversion: git_version.stamp
+ if test -f "git_version.h"; then \
+ sed -e 's|^#undef GIT_IS_DIST.*|#define GIT_IS_DIST 1|' \
+ "git_version.h" > "$(distdir)/git_version.h"; \
+ fi
+
+git_version.h:
+ $(srcdir)/git_version.sh -k --srcdir $(srcdir) -o git_version.h
@BUILD_ELFUTILS_TRUE@stamp-elfutils: config.status
@BUILD_ELFUTILS_TRUE@ $(MAKE) $(AM_MAKEFLAGS) -C build-elfutils all
@BUILD_ELFUTILS_TRUE@ for dir in libelf libebl libdw libdwfl backends; do \
@@ -1492,7 +1529,7 @@ dist-add-samples: $(SAMPLE_SRC)
mkdir -p $(SAMPLE_DEST_DIR)
cp $(SAMPLE_SRC) $(SAMPLE_DEST_DIR)
-dist-hook: dist-add-samples
+dist-hook: dist-add-samples dist-gitversion
find $(distdir) -name CVS -o -name '*~' -o -name '.#*' | xargs rm -rf
find $(distdir) -name '*.o' -o -name '*.ko' -o -name '*.cmd' -o -name '*.mod.c' -o -name '.??*' | xargs rm -rf
find $(distdir) -name 'stap' -o -name '*.log' -o -name '*.sum' -o -name 'site.exp' | xargs rm -rf
diff --git a/NEWS b/NEWS
index fd9df29d..d794cd86 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+* What's new in version 0.7
+
+- A probe listing mode is available.
+ % stap -l vm.*
+ vm.brk
+ vm.mmap
+ vm.munmap
+ vm.oom_kill
+ vm.pagefault
+ vm.write_shared
+
+
* What's new in version 0.6
- A copy of the systemtap tutorial and language reference guide
diff --git a/configure b/configure
index c8be8582..819c6f06 100755
--- a/configure
+++ b/configure
@@ -6812,13 +6812,6 @@ cap_LIBS="$LIBS"
LIBS="$SAVE_LIBS"
CFLAGS="$SAVE_CFLAGS"
-if test -d $srcdir/.git -a ! -f $srcdir/SNAPSHOT; then
- snapshot=`cd $srcdir; git-rev-list --abbrev-commit --max-count=1 HEAD`
- echo $snapshot > SNAPSHOT
- { echo "$as_me:$LINENO: Created git SNAPSHOT $snapshot" >&5
-echo "$as_me: Created git SNAPSHOT $snapshot" >&6;}
-fi
-
ac_config_headers="$ac_config_headers config.h:config.in"
ac_config_files="$ac_config_files Makefile doc/Makefile systemtap.spec stap.1 stapprobes.5 stapfuncs.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5"
diff --git a/configure.ac b/configure.ac
index fa14516c..51ed83a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -204,13 +204,6 @@ AC_SUBST(cap_LIBS)
LIBS="$SAVE_LIBS"
CFLAGS="$SAVE_CFLAGS"
-dnl Create SNAPSHOT file from git commit id if possible
-if test -d $srcdir/.git -a ! -f $srcdir/SNAPSHOT; then
- snapshot=`cd $srcdir; git-rev-list --abbrev-commit --max-count=1 HEAD`
- echo $snapshot > SNAPSHOT
- AC_MSG_NOTICE([Created git SNAPSHOT $snapshot])
-fi
-
AC_CONFIG_HEADERS([config.h:config.in])
AC_CONFIG_FILES(Makefile doc/Makefile systemtap.spec stap.1 stapprobes.5 stapfuncs.5 stapex.5 staprun.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5)
AC_CONFIG_SUBDIRS(testsuite)
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 00000000..d8a93302
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,8 @@
+*.aux
+*.glo
+*.idx
+*.log
+*.lot
+*.out
+*.pdf
+*.toc
diff --git a/doc/ChangeLog b/doc/ChangeLog
index e652078d..21b3cbf7 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2008-04-09 David Smith <dsmith@redhat.com>
+
+ * .gitignore: New file.
+
2008-03-25 Frank Ch. Eigler <fche@elastic.org>
* langref.tex: Clarify utility of epilogue-type probe aliases.
diff --git a/elaborate.cxx b/elaborate.cxx
index 2d9fa7bc..1c41df64 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -1214,6 +1214,9 @@ systemtap_session::print_error (const semantic_error& e)
string message_str;
stringstream message;
+ // NB: we don't print error messages during listing mode.
+ if (listing_mode) return;
+
message << "semantic error: " << e.what ();
if (e.tok1 || e.tok2)
message << ": ";
diff --git a/elaborate.h b/elaborate.h
index fc8fbbcb..f53f3870 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -114,6 +114,8 @@ struct derived_probe: public probe
derived_probe (probe* b, probe_point* l);
probe* base; // the original parsed probe
virtual probe* basest () { return base->basest(); }
+ // XXX: might be helpful for listing and stepwise expansion, but aliases/wildcards don't show up right
+ // virtual probe* almost_basest () { probe* bb = base->basest(); return (bb == base) ? this : bb; }
virtual ~derived_probe () {}
virtual void join_group (systemtap_session& s) = 0;
virtual probe_point* sole_location () const;
@@ -148,6 +150,12 @@ struct derived_probe_group
{
virtual ~derived_probe_group () {}
+ virtual void emit_module_header (systemtap_session& s) = 0;
+ // The _header-generated code may assume that only basic includes
+ // have been generated. _header is called near the start of the
+ // code generation process, before the context, embedded-C code,
+ // etc. are generated.
+
virtual void emit_module_decls (systemtap_session& s) = 0;
// The _decls-generated code may assume that declarations such as
// the context, embedded-C code, function and probe handler bodies
diff --git a/git_version.sh b/git_version.sh
new file mode 100755
index 00000000..69eb0f24
--- /dev/null
+++ b/git_version.sh
@@ -0,0 +1,348 @@
+#!/bin/sh
+#
+# Generate some basic versioning information which can be piped to a header.
+#
+# Copyright (c) 2006-2007 Luc Verhaegen <libv@skynet.be>
+# Copyright (C) 2007 Hans Ulrich Niedermann <hun@n-dimensional.de>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# This script is based on the one written for xf86-video-unichrome by
+# Luc Verhaegen, but was rewritten almost completely by Hans Ulrich
+# Niedermann. The script contains a few bug fixes from Egbert Eich,
+# Matthias Hopf, Joerg Sonnenberger, and possibly others.
+#
+# The author thanks the nice people on #git for the assistance.
+#
+# Simple testing of this script:
+# /sbin/busybox sh git_version.sh --example > moo.c \
+# && gcc -Wall -Wextra -Wno-unused -o moo moo.c \
+# && ./moo
+# (bash should also do)
+#
+# For how to hook this up to your automake- and/or imake-based build
+# system, best take a look at how the RadeonHD.am and/or RadeonHD.tmpl
+# work in the xf86-video-radeonhd build system. For non-recursive make,
+# you can probably make things a little bit simpler.
+#
+# KNOWN BUGS:
+# * Uses hyphenated ("git-foo-bar") program names, which git upstream
+# have declared deprecated.
+#
+
+# Help messages
+USAGE="[<option>...]"
+LONG_USAGE="\
+Options:
+ -h, --help Print this help message.
+
+ -k, --keep-if-no-repo Keep old output file if no git repo found.
+ -o, --output FILENAME Set output file name.
+ -q, --quiet Quiet output.
+ -s, --srcdir DIRNAME Set source tree dir name.
+ -x, --example Print complete example program."
+
+# The caller may have set these for us
+SED="${SED-sed}"
+
+# Initialize
+working_dir="$(pwd)"
+
+# Who am I?
+self="$(basename "$0")"
+
+# Defaults
+ifndef_symbol="GIT_VERSION_H"
+outfile="-"
+print_example=false
+keep_if_no_repo=no
+quiet=false
+srcdir="$(pwd)"
+
+# Parse command line parameter, affecting defaults
+while [ "x$1" != "x" ]
+do
+ case "$1" in
+ -x|--example)
+ print_example=:
+ ;;
+ -o|--output)
+ if shift; then
+ outfile="$1"
+ if [ "x$outfile" = "x-" ]; then
+ : # keep default ifndef_symbol
+ else
+ ifndef_symbol=`basename "$outfile" | $SED 's|\.|_|g; s|[^A-Za-z0-9_]||g' | tr a-z A-Z`
+ fi
+ else
+ echo "$self: Fatal: \"$1\" option requires parameter." >&2
+ exit 1
+ fi
+ ;;
+ -q|--quiet)
+ quiet=:
+ ;;
+ -h|--help)
+ echo "Usage: ${self} $USAGE"
+ [ -n "$LONG_USAGE" ] && echo "$LONG_USAGE"
+ exit
+ ;;
+ -k|--keep-if-no-repo)
+ keep_if_no_repo=yes
+ ;;
+ -s|--srcdir)
+ if shift; then
+ if test -d "$1"; then
+ srcdir="$1"
+ else
+ echo "$self: Fatal: \"$1\" not a directory." >&2
+ exit 1
+ fi
+ else
+ echo "$self: Fatal: \"$1\" option requires directory parameter." >&2
+ exit 1
+ fi
+ ;;
+ *)
+ echo "$self: Fatal: Invalid command line paramenter: \"$1\"" >&2
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+# If not printing to stdout, redirect stdout to output file
+rename_new_output=false
+if [ "x$outfile" = "x-" ]
+then
+ : # keep using stdout
+else
+ exec 1> "${outfile}.new"
+fi
+
+# Done with creating output files, so we can change to source dir
+abs_srcdir="$(cd "$srcdir" && pwd)"
+cd "$srcdir"
+
+# Write program header
+cat<<EOF
+/*
+ * Basic versioning gathered from the git repository.
+ * Automatically generated by $0.
+ */
+
+#ifndef ${ifndef_symbol}
+#define ${ifndef_symbol} 1
+
+/* whether this is a dist tarball or not */
+#undef GIT_IS_DIST
+
+EOF
+
+# Detect git tools (should work with old and new git versions)
+git_found=yes
+for git_tool in git-symbolic-ref git-rev-parse git-diff-files git-diff-index git
+do
+ if [ x`which $git_tool 2>/dev/null` = "x" ]; then
+ git_found="'$git_tool' not found"
+ break
+ fi
+done
+
+# Determine git specific defines
+unset git_errors ||:
+if [ "x$git_found" = "xyes" ]; then
+ git_version=`git --version`
+ if [ "x$git_version" = "x" ]; then
+ git_errors="${git_errors+${git_errors}; }error running 'git --version'"
+ fi
+fi
+
+git_repo=no
+# "git-rev-parse --git-dir" since git-0.99.7
+git_repo_dir="$(git-rev-parse --git-dir 2> /dev/null || true)"
+abs_repo_dir="$(cd "$git_repo_dir" && pwd)"
+# Only accept the found git repo iff it is in our top srcdir, as determined
+# by comparing absolute pathnames creaged by running pwd in the respective dir.
+if [ "x$git_repo_dir" != "x" ] && [ "x${abs_repo_dir}" = "x${abs_srcdir}/.git" ]; then
+ git_repo=yes
+ if [ "x$git_found" = "xyes" ]; then
+ # git-1.4 and probably earlier understand "git-rev-parse HEAD"
+ git_shaid=`git-rev-parse HEAD | $SED -n 's/^\(.\{8\}\).*/\1/p'`
+ if [ "x$git_shaid" = "x" ]; then
+ git_errors="${git_errors+${git_errors}; }error running 'git-rev-parse HEAD'"
+ fi
+ # git-1.4 and probably earlier understand "git-symbolic-ref HEAD"
+ git_branch=`git-symbolic-ref HEAD | $SED -n 's|^refs/heads/||p'`
+ if [ "x$git_branch" = "x" ]; then
+ # This happens, is OK, and "(no branch)" is what "git branch" prints.
+ git_branch="(no branch)"
+ fi
+ git_dirty=yes
+ # git-1.4 does not understand "git-diff-files --quiet"
+ # git-1.4 does not understand "git-diff-index --cached --quiet HEAD"
+ if [ "x$(git-diff-files)" = "x" ] && [ "x$(git-diff-index --cached HEAD)" = "x" ]; then
+ git_dirty=no
+ fi
+ fi
+fi
+
+# Write git specific defines
+if [ "x$git_errors" = "x" ]; then
+ echo "/* No errors occured while running git */"
+ echo "#undef GIT_ERRORS"
+else
+ echo "/* Some errors occured while running git */"
+ echo "#define GIT_ERRORS \"${git_errors}\""
+fi
+echo ""
+
+if [ "x$git_found" = "xyes" ]; then
+ echo "/* git utilities found */"
+ echo "#undef GIT_NOT_FOUND"
+ echo "#define GIT_VERSION \"${git_version}\""
+else
+ echo "/* git utilities not found */"
+ echo "#define GIT_NOT_FOUND \"${git_found}\""
+ echo "#undef GIT_VERSION"
+fi
+echo ""
+
+if [ "x$git_repo" = "xno" ]; then
+ echo "/* No git repo found, probably building from dist tarball */"
+ echo "#undef GIT_REPO"
+else
+ echo "/* git repo found */"
+ echo "#define GIT_REPO 1"
+ echo ""
+ if [ "x$git_found" = "xyes" ]; then
+ echo "/* Git SHA ID of last commit */"
+ echo "#define GIT_SHAID \"${git_shaid}\""
+ echo ""
+
+ echo "/* Branch this tree is on */"
+ echo "#define GIT_BRANCH \"$git_branch\""
+ echo ""
+
+ # Any uncommitted changes we should know about?
+ # Or technically: Are the working tree or index dirty?
+ if [ "x$git_dirty" = "xno" ]; then
+ echo "/* SHA-ID uniquely defines the state of this code */"
+ echo "#undef GIT_DIRTY"
+ else
+ echo "/* Local changes might be breaking things */"
+ echo "#define GIT_DIRTY 1"
+ fi
+ fi
+fi
+
+# Define a few immediately useful message strings
+cat<<EOF
+
+/* Define GIT_MESSAGE such that
+ * printf("%s: built from %s", argv[0], GIT_MESSAGE);
+ * forms a proper sentence.
+ */
+
+#ifdef GIT_DIRTY
+# define GIT_DIRTY_MSG " + changes"
+#else /* !GIT_DIRTY */
+# define GIT_DIRTY_MSG ""
+#endif /* GIT_DIRTY */
+
+#ifdef GIT_ERRORS
+# define GIT_ERROR_MSG " with error: " GIT_ERRORS
+#else /* !GIT_ERRORS */
+# define GIT_ERROR_MSG ""
+#endif /* GIT_ERRORS */
+
+#ifdef GIT_IS_DIST
+# define GIT_DIST_MSG "dist of "
+#else /* !GIT_IS_DIST */
+# define GIT_DIST_MSG ""
+#endif /* GIT_IS_DIST */
+
+#ifdef GIT_REPO
+# ifdef GIT_NOT_FOUND
+# define GIT_MESSAGE GIT_DIST_MSG "git sources without git: " GIT_NOT_FOUND
+# else /* !GIT_NOT_FOUND */
+# define GIT_MESSAGE \\
+ GIT_DIST_MSG \\
+ "git branch " GIT_BRANCH ", " \\
+ "commit " GIT_SHAID GIT_DIRTY_MSG \\
+ GIT_ERROR_MSG
+# endif /* GIT_NOT_FOUND */
+#else /* !GIT_REPO */
+# define GIT_MESSAGE GIT_DIST_MSG "non-git sources" GIT_ERROR_MSG
+#endif /* GIT_REPO */
+
+#endif /* ${ifndef_symbol} */
+EOF
+
+# Example program
+if "$print_example"
+then
+ cat<<EOF
+
+/* example program demonstrating the use of git_version.sh output */
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+int main(int argc, char *argv[])
+{
+ const char *const idx = strrchr(argv[0], '/');
+ const char *const prog = (idx)?(idx+1):(argv[0]);
+#ifdef PACKAGE_VERSION
+ printf("%s: version %s, built from %s\n", prog, PACKAGE_VERSION, GIT_MESSAGE);
+#elif defined(GIT_USED)
+ printf("%s: built from %s\n", prog, GIT_MESSAGE);
+#endif
+ return 0;
+}
+EOF
+fi
+
+# Change back to working dir for the remaining output file manipulations.
+cd "$working_dir"
+
+# If necessary, overwrite outdated output file with new one
+if [ "x$outfile" != "x-" ]
+then
+ if [ -f "$outfile" ]; then
+ if [ "x$keep_if_no_repo" = "xyes" ] && [ "x$git_repo" = "xno" ]; then
+ "$quiet" || echo "$self: Not a git repo, keeping existing $outfile" >&2
+ rm -f "$outfile.new"
+ elif cmp "$outfile" "$outfile.new" > /dev/null; then
+ "$quiet" || echo "$self: Output is unchanged, keeping $outfile" >&2
+ rm -f "$outfile.new"
+ else
+ echo "$self: Output has changed, updating $outfile" >&2
+ mv -f "$outfile.new" "$outfile"
+ fi
+ else
+ echo "$self: Output is new file, creating $outfile" >&2
+ mv -f "$outfile.new" "$outfile"
+ fi
+fi
+
+# THE END.
diff --git a/main.cxx b/main.cxx
index 4364f664..03021d8c 100644
--- a/main.cxx
+++ b/main.cxx
@@ -19,6 +19,7 @@
#include "cache.h"
#include "util.h"
#include "coveragedb.h"
+#include "git_version.h"
#include <iostream>
#include <fstream>
@@ -47,7 +48,7 @@ version ()
clog
<< "SystemTap translator/driver "
<< "(version " << VERSION << "/" << dwfl_version (NULL)
- << " built " << DATE << ")" << endl
+ << " " << GIT_MESSAGE << ")" << endl
<< "Copyright (C) 2005-2008 Red Hat, Inc. and others" << endl
<< "This is free software; see the source for copying conditions." << endl;
}
@@ -64,9 +65,11 @@ usage (systemtap_session& s, int exitcode)
<< endl
<< " or: stap [options] -e SCRIPT Run given script."
<< endl
+ << " or: stap [options] -l PROBE List matching probes."
+ << endl
<< endl
<< "Options:" << endl
- << " -- no more options after this" << endl
+ << " -- end of translator options, script options follow" << endl
<< " -v increase verbosity [" << s.verbose << "]" << endl
<< " -h show help" << endl
<< " -V show version" << endl
@@ -116,75 +119,118 @@ usage (systemtap_session& s, int exitcode)
static void
printscript(systemtap_session& s, ostream& o)
{
- if (s.embeds.size() > 0)
- o << "# global embedded code" << endl;
- for (unsigned i=0; i<s.embeds.size(); i++)
+ if (s.listing_mode)
{
- embeddedcode* ec = s.embeds[i];
- ec->print (o);
- o << endl;
- }
+ // We go through some heroic measures to produce clean output.
+ set<string> seen;
- if (s.globals.size() > 0)
- o << "# globals" << endl;
- for (unsigned i=0; i<s.globals.size(); i++)
- {
- vardecl* v = s.globals[i];
- v->printsig (o);
- if (s.verbose && v->init)
+ for (unsigned i=0; i<s.probes.size(); i++)
{
- o << " = ";
- v->init->print(o);
+ derived_probe* p = s.probes[i];
+ // NB: p->basest() is not so interesting;
+ // p->almost_basest() doesn't quite work, so ...
+ vector<probe*> chain;
+ p->collect_derivation_chain (chain);
+ probe* second = (chain.size()>1) ? chain[chain.size()-2] : chain[0];
+
+ #if 0
+ cerr << "\tchain[" << chain.size() << "]:" << endl;
+ for (unsigned i=0; i<chain.size(); i++)
+ { cerr << "\t"; chain[i]->printsig(cerr); cerr << endl; }
+ #endif
+
+ stringstream tmps;
+ second->printsig (tmps);
+ string tmp = tmps.str();
+ // trim anything other than the "head" of the probe point signature:
+ // alias1 *CUT* = exp1, exp2
+ // probe1 *CUT* /* pc=0xdeadbeef */ /* <- foo */
+ string::size_type space_pos = tmp.find(' ');
+ assert (space_pos != string::npos);
+ string pp = tmp.substr (0, space_pos);
+
+ // Now duplicate-eliminate. An alias may have expanded to
+ // several actual derived probe points, but we only want to
+ // print the alias head name once.
+ if (seen.find (pp) == seen.end())
+ {
+ o << pp << endl;
+ seen.insert (pp);
+ }
}
- o << endl;
}
-
- if (s.functions.size() > 0)
- o << "# functions" << endl;
- for (unsigned i=0; i<s.functions.size(); i++)
+ else
{
- functiondecl* f = s.functions[i];
- f->printsig (o);
- o << endl;
- if (f->locals.size() > 0)
- o << " # locals" << endl;
- for (unsigned j=0; j<f->locals.size(); j++)
+ if (s.embeds.size() > 0)
+ o << "# global embedded code" << endl;
+ for (unsigned i=0; i<s.embeds.size(); i++)
{
- vardecl* v = f->locals[j];
- o << " ";
- v->printsig (o);
- o << endl;
- }
- if (s.verbose)
+ embeddedcode* ec = s.embeds[i];
+ ec->print (o);
+ o << endl;
+ }
+
+ if (s.globals.size() > 0)
+ o << "# globals" << endl;
+ for (unsigned i=0; i<s.globals.size(); i++)
{
- f->body->print (o);
- o << endl;
- }
- }
-
- if (s.probes.size() > 0)
- o << "# probes" << endl;
- for (unsigned i=0; i<s.probes.size(); i++)
- {
- derived_probe* p = s.probes[i];
- p->printsig (o);
- o << endl;
- if (p->locals.size() > 0)
- o << " # locals" << endl;
- for (unsigned j=0; j<p->locals.size(); j++)
+ vardecl* v = s.globals[i];
+ v->printsig (o);
+ if (s.verbose && v->init)
+ {
+ o << " = ";
+ v->init->print(o);
+ }
+ o << endl;
+ }
+
+ if (s.functions.size() > 0)
+ o << "# functions" << endl;
+ for (unsigned i=0; i<s.functions.size(); i++)
{
- vardecl* v = p->locals[j];
- o << " ";
- v->printsig (o);
- o << endl;
- }
- if (s.verbose)
+ functiondecl* f = s.functions[i];
+ f->printsig (o);
+ o << endl;
+ if (f->locals.size() > 0)
+ o << " # locals" << endl;
+ for (unsigned j=0; j<f->locals.size(); j++)
+ {
+ vardecl* v = f->locals[j];
+ o << " ";
+ v->printsig (o);
+ o << endl;
+ }
+ if (s.verbose)
+ {
+ f->body->print (o);
+ o << endl;
+ }
+ }
+
+ if (s.probes.size() > 0)
+ o << "# probes" << endl;
+ for (unsigned i=0; i<s.probes.size(); i++)
{
- p->body->print (o);
- o << endl;
- }
+ derived_probe* p = s.probes[i];
+ p->printsig (o);
+ o << endl;
+ if (p->locals.size() > 0)
+ o << " # locals" << endl;
+ for (unsigned j=0; j<p->locals.size(); j++)
+ {
+ vardecl* v = p->locals[j];
+ o << " ";
+ v->printsig (o);
+ o << endl;
+ }
+ if (s.verbose)
+ {
+ p->body->print (o);
+ o << endl;
+ }
+ }
+ }
}
-}
int pending_interrupts;
@@ -224,6 +270,7 @@ main (int argc, char * const argv [])
s.bulk_mode = false;
s.unoptimized = false;
s.suppress_warnings = false;
+ s.listing_mode = false;
#ifdef ENABLE_PROLOGUES
s.prologue_searching = true;
@@ -295,7 +342,7 @@ main (int argc, char * const argv [])
while (true)
{
// NB: also see find_hash(), usage(), switch stmt below, stap.1 man page
- int grc = getopt (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqw");
+ int grc = getopt (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:");
if (grc < 0)
break;
switch (grc)
@@ -321,6 +368,11 @@ main (int argc, char * const argv [])
break;
case 'p':
+ if (s.listing_mode)
+ {
+ cerr << "Listing (-l) mode implies pass 2." << endl;
+ usage (s, 1);
+ }
s.last_pass = atoi (optarg);
if (s.last_pass < 1 || s.last_pass > 5)
{
@@ -453,6 +505,19 @@ main (int argc, char * const argv [])
usage (s, 0);
break;
+ case 'l':
+ s.listing_mode = true;
+ s.last_pass = 2;
+ if (have_script)
+ {
+ cerr << "Only one script can be given on the command line."
+ << endl;
+ usage (s, 1);
+ }
+ cmdline_script = string("probe ") + string(optarg) + " {}";
+ have_script = true;
+ break;
+
default:
usage (s, 1);
break;
@@ -718,7 +783,7 @@ main (int argc, char * const argv [])
// PASS 2: ELABORATION
rc = semantic_pass (s);
- if (rc == 0 && s.last_pass == 2)
+ if (s.listing_mode || (rc == 0 && s.last_pass == 2))
printscript(s, cout);
times (& tms_after);
@@ -767,7 +832,7 @@ main (int argc, char * const argv [])
}
}
- if (rc || s.last_pass == 2 || pending_interrupts) goto cleanup;
+ if (rc || s.listing_mode || s.last_pass == 2 || pending_interrupts) goto cleanup;
// PASS 3: TRANSLATION
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index e6d8ed72..067c5820 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -2,6 +2,14 @@
* runtime.h (STP_USE_DWARF_UNWINDER): Define.
+2008-04-04 Masami Hiramatsu <mhiramat@redhat.com>
+
+ PR 6028
+ * loc2c-runtime.h (fetch_register): Call ia64_fetch_register with
+ the address of c->unwaddr.
+ * regs-ia64.c (ia64_fetch_register): Don't unwind stack if it has
+ already unwound stack in same probe.
+
2008-03-30 Martin Hunt <hunt@redhat.com>
* runtime.h (STP_USE_FRAME_POINTER): Define when frame pointers
@@ -11,6 +19,11 @@
* unwind/i386.h: Ditto.
* unwind/x86_64.h: Ditto.
+2008-04-04 David Smith <dsmith@redhat.com>
+
+ PR 5961 (partial)
+ * task_finder.c: New file.
+
2008-03-28 Martin Hunt <hunt@redhat.com>
* copy.c (_stp_read_address): New function. Safely read
@@ -28,6 +41,10 @@
* unwind.c (unwind): Return a positive number to indicate
that unwinding is done.
+2008-04-01 Frank Ch. Eigler <fche@elastic.org>
+
+ * lket/*: Belatedly remove retired LKET code.
+
2008-03-17 Eugene Teo <eteo@redhat.com>
PR 5947
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index 7ea1b1e4..66fd1e43 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -129,7 +129,7 @@
#undef fetch_register
#undef store_register
-#define fetch_register(regno) ia64_fetch_register(regno, c->regs)
+#define fetch_register(regno) ia64_fetch_register(regno, c->regs, &c->unwaddr)
#define store_register(regno,value) ia64_store_register(regno, c->regs, value)
#elif defined __x86_64__
diff --git a/runtime/regs-ia64.c b/runtime/regs-ia64.c
index 2a5a1d17..66dc60f3 100644
--- a/runtime/regs-ia64.c
+++ b/runtime/regs-ia64.c
@@ -35,7 +35,7 @@ static void ia64_stap_get_arbsp(struct unw_frame_info *info, void *arg)
lp->address = 0;
}
-static long ia64_fetch_register(int regno, struct pt_regs *pt_regs)
+static long ia64_fetch_register(int regno, struct pt_regs *pt_regs, unsigned long **cache)
{
struct ia64_stap_get_arbsp_param pa;
@@ -47,12 +47,15 @@ static long ia64_fetch_register(int regno, struct pt_regs *pt_regs)
else if (regno < 32 || regno > 127)
return 0;
- pa.ip = pt_regs->cr_iip;
- unw_init_running(ia64_stap_get_arbsp, &pa);
- if (pa.address == 0)
- return 0;
+ if (!*cache) {
+ pa.ip = pt_regs->cr_iip;
+ unw_init_running(ia64_stap_get_arbsp, &pa);
+ if (pa.address == 0)
+ return 0;
+ *cache = pa.address;
+ }
- return *ia64_rse_skip_regs(pa.address, regno-32);
+ return *ia64_rse_skip_regs(*cache, regno-32);
}
static void ia64_store_register(int regno,
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
new file mode 100644
index 00000000..d2e57a6b
--- /dev/null
+++ b/runtime/task_finder.c
@@ -0,0 +1,410 @@
+#include <linux/list.h>
+
+static LIST_HEAD(__stp_task_finder_list);
+
+struct stap_task_finder_target;
+
+typedef int (*stap_task_finder_callback)(struct task_struct *tsk,
+ int register_p,
+ struct stap_task_finder_target *tgt);
+
+struct stap_task_finder_target {
+/* private: */
+ struct list_head list; /* __stp_task_finder_list linkage */
+ struct list_head callback_list_head;
+ struct list_head callback_list;
+ struct utrace_engine_ops ops;
+ int engine_attached;
+ size_t pathlen;
+
+/* public: */
+ const char *pathname;
+ pid_t pid;
+ stap_task_finder_callback callback;
+};
+
+static int
+stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
+{
+ // Since this __stp_task_finder_list is (currently) only
+ // written to in one big setup operation before the task
+ // finder process is started, we don't need to lock it.
+ struct list_head *node;
+ struct stap_task_finder_target *tgt = NULL;
+ int found_node = 0;
+
+ if (new_tgt->pathname != NULL)
+ new_tgt->pathlen = strlen(new_tgt->pathname);
+ else
+ new_tgt->pathlen = 0;
+
+ // Search the list for an existing entry for pathname/pid.
+ list_for_each(node, &__stp_task_finder_list) {
+ tgt = list_entry(node, struct stap_task_finder_target, list);
+ if (tgt != NULL
+ /* pathname-based target */
+ && ((new_tgt->pathlen > 0
+ && tgt->pathlen == new_tgt->pathlen
+ && strcmp(tgt->pathname, new_tgt->pathname) == 0)
+ /* pid-based target */
+ || (new_tgt->pid != 0 && tgt->pid == new_tgt->pid))) {
+ found_node = 1;
+ break;
+ }
+ }
+
+ // If we didn't find a matching existing entry, add the new
+ // target to the task list.
+ if (! found_node) {
+ INIT_LIST_HEAD(&new_tgt->callback_list_head);
+ list_add(&new_tgt->list, &__stp_task_finder_list);
+ tgt = new_tgt;
+ }
+
+ // Add this target to the callback list for this task.
+ new_tgt->engine_attached = 0;
+ list_add_tail(&new_tgt->callback_list, &tgt->callback_list_head);
+ return 0;
+}
+
+static void
+stap_utrace_detach_ops(struct utrace_engine_ops *ops)
+{
+ struct task_struct *tsk;
+ struct utrace_attached_engine *engine;
+ long error = 0;
+ pid_t pid = 0;
+
+ rcu_read_lock();
+ for_each_process(tsk) {
+ struct mm_struct *mm;
+ mm = get_task_mm(tsk);
+ if (mm) {
+ mmput(mm);
+ engine = utrace_attach(tsk, UTRACE_ATTACH_MATCH_OPS,
+ ops, 0);
+ if (IS_ERR(engine)) {
+ error = -PTR_ERR(engine);
+ if (error != ENOENT) {
+ pid = tsk->pid;
+ break;
+ }
+ error = 0;
+ }
+ else if (engine != NULL) {
+ utrace_detach(tsk, engine);
+ }
+ }
+ }
+ rcu_read_unlock();
+
+ if (error != 0) {
+ _stp_error("utrace_attach returned error %d on pid %d",
+ error, pid);
+ }
+}
+
+static void
+__stp_task_finder_cleanup(void)
+{
+ struct list_head *tgt_node, *tgt_next;
+ struct list_head *cb_node, *cb_next;
+ struct stap_task_finder_target *tgt;
+
+ // Walk the main list, cleaning up as we go.
+ list_for_each_safe(tgt_node, tgt_next, &__stp_task_finder_list) {
+ tgt = list_entry(tgt_node, struct stap_task_finder_target,
+ list);
+ if (tgt == NULL)
+ continue;
+
+ list_for_each_safe(cb_node, cb_next,
+ &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+ cb_tgt = list_entry(cb_node,
+ struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL)
+ continue;
+
+ if (cb_tgt->engine_attached) {
+ stap_utrace_detach_ops(&cb_tgt->ops);
+ cb_tgt->engine_attached = 0;
+ }
+
+ list_del(&cb_tgt->callback_list);
+ }
+ list_del(&tgt->list);
+ }
+}
+
+static char *
+__stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
+{
+ struct vm_area_struct *vma;
+ char *rc = NULL;
+
+ down_read(&mm->mmap_sem);
+ vma = mm->mmap;
+ while (vma) {
+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
+ break;
+ vma = vma->vm_next;
+ }
+ if (vma) {
+ struct vfsmount *mnt = mntget(vma->vm_file->f_path.mnt);
+ struct dentry *dentry = dget(vma->vm_file->f_path.dentry);
+ rc = d_path(dentry, mnt, buf, buflen);
+ dput(dentry);
+ mntput(mnt);
+ }
+ else {
+ *buf = '\0';
+ rc = ERR_PTR(ENOENT);
+ }
+ up_read(&mm->mmap_sem);
+ return rc;
+}
+
+#define __STP_UTRACE_TASK_FINDER_EVENTS (UTRACE_EVENT(CLONE) \
+ | UTRACE_EVENT(EXEC))
+
+#define __STP_UTRACE_ATTACHED_TASK_EVENTS (UTRACE_EVENT(DEATH))
+
+static u32
+__stp_utrace_task_finder_clone(struct utrace_attached_engine *engine,
+ struct task_struct *parent,
+ unsigned long clone_flags,
+ struct task_struct *child)
+{
+ struct utrace_attached_engine *child_engine;
+ struct mm_struct *mm;
+
+ // On clone, attach to the child. Ignore threads with no mm
+ // (which are kernel threads).
+ mm = get_task_mm(child);
+ if (mm) {
+ mmput(mm);
+ child_engine = utrace_attach(child, UTRACE_ATTACH_CREATE,
+ engine->ops, 0);
+ if (IS_ERR(child_engine))
+ _stp_error("attach to clone child %d failed: %ld",
+ (int)child->pid, PTR_ERR(child_engine));
+ else {
+ utrace_set_flags(child, child_engine,
+ __STP_UTRACE_TASK_FINDER_EVENTS);
+ }
+ }
+ return UTRACE_ACTION_RESUME;
+}
+
+static u32
+__stp_utrace_task_finder_death(struct utrace_attached_engine *engine,
+ struct task_struct *tsk)
+{
+ struct stap_task_finder_target *tgt = engine->data;
+
+ // The first implementation of this added a
+ // UTRACE_EVENT(DEATH) handler to
+ // __stp_utrace_task_finder_ops. However, dead threads don't
+ // have a mm_struct, so we can't find the exe's path. So, we
+ // don't know which callback(s) to call.
+ //
+ // So, now when an "interesting" thread is found, we add a
+ // separate UTRACE_EVENT(DEATH) handler for every probe.
+
+ if (tgt != NULL && tgt->callback != NULL) {
+ int rc;
+
+ // Call the callback
+ rc = tgt->callback(tsk, 0, tgt);
+ if (rc != 0) {
+ _stp_error("death callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ }
+ }
+ return UTRACE_ACTION_RESUME;
+}
+
+static u32
+__stp_utrace_task_finder_exec(struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ const struct linux_binprm *bprm,
+ struct pt_regs *regs)
+{
+ size_t filelen;
+ struct list_head *tgt_node;
+ struct stap_task_finder_target *tgt;
+ int found_node = 0;
+
+ // On exec, check bprm
+ if (bprm->filename == NULL)
+ return UTRACE_ACTION_RESUME;
+
+ filelen = strlen(bprm->filename);
+ list_for_each(tgt_node, &__stp_task_finder_list) {
+ tgt = list_entry(tgt_node, struct stap_task_finder_target,
+ list);
+ // Note that we don't bother with looking for pids
+ // here, since they are handled at startup.
+ if (tgt != NULL && tgt->pathlen > 0
+ && tgt->pathlen == filelen
+ && strcmp(tgt->pathname, bprm->filename) == 0) {
+ found_node = 1;
+ break;
+ }
+ }
+ if (found_node) {
+ struct list_head *cb_node;
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+ cb_tgt = list_entry(cb_node,
+ struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL)
+ continue;
+
+ if (cb_tgt->callback != NULL) {
+ int rc = cb_tgt->callback(tsk, 1, cb_tgt);
+ if (rc != 0) {
+ _stp_error("exec callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ break;
+ }
+ }
+
+ // Set up thread death notification.
+ memset(&cb_tgt->ops, 0, sizeof(cb_tgt->ops));
+ cb_tgt->ops.report_death
+ = &__stp_utrace_task_finder_death;
+
+ engine = utrace_attach(tsk,
+ UTRACE_ATTACH_CREATE,
+ &cb_tgt->ops, cb_tgt);
+ if (IS_ERR(engine)) {
+ _stp_error("attach to exec'ed %d failed: %ld",
+ (int)tsk->pid,
+ PTR_ERR(engine));
+ }
+ else {
+ utrace_set_flags(tsk, engine,
+ __STP_UTRACE_ATTACHED_TASK_EVENTS);
+ cb_tgt->engine_attached = 1;
+ }
+ }
+ }
+ return UTRACE_ACTION_RESUME;
+}
+
+struct utrace_engine_ops __stp_utrace_task_finder_ops = {
+ .report_clone = __stp_utrace_task_finder_clone,
+ .report_exec = __stp_utrace_task_finder_exec,
+};
+
+int
+stap_start_task_finder(void)
+{
+ int rc = 0;
+ struct task_struct *tsk;
+ char *mmpath_buf;
+
+ mmpath_buf = _stp_kmalloc(PATH_MAX);
+ if (mmpath_buf == NULL) {
+ _stp_error("Unable to allocate space for path");
+ return ENOMEM;
+ }
+
+ rcu_read_lock();
+ for_each_process(tsk) {
+ struct utrace_attached_engine *engine;
+ struct mm_struct *mm;
+ char *mmpath;
+ size_t mmpathlen;
+ struct list_head *tgt_node;
+
+ mm = get_task_mm(tsk);
+ if (! mm) {
+ /* If the thread doesn't have a mm_struct, it is
+ * a kernel thread which we need to skip. */
+ continue;
+ }
+
+ /* Attach to the thread */
+ engine = utrace_attach(tsk, UTRACE_ATTACH_CREATE,
+ &__stp_utrace_task_finder_ops, 0);
+ if (IS_ERR(engine)) {
+ int error = -PTR_ERR(engine);
+ if (error != ENOENT) {
+ mmput(mm);
+ _stp_error("utrace_attach returned error %d on pid %d",
+ error, (int)tsk->pid);
+ rc = error;
+ break;
+ }
+ }
+ else if (unlikely(engine == NULL)) {
+ mmput(mm);
+ _stp_error("utrace_attach returned NULL on pid %d",
+ (int)tsk->pid);
+ rc = EFAULT;
+ break;
+ }
+ utrace_set_flags(tsk, engine, __STP_UTRACE_TASK_FINDER_EVENTS);
+
+ /* Check the thread's exe's path/pid against our list. */
+ mmpath = __stp_get_mm_path(mm, mmpath_buf, PATH_MAX);
+ mmput(mm); /* We're done with mm */
+ if (IS_ERR(mmpath)) {
+ rc = -PTR_ERR(mmpath);
+ _stp_error("Unable to get path (error %d) for pid %d",
+ rc, (int)tsk->pid);
+ break;
+ }
+
+ mmpathlen = strlen(mmpath);
+ list_for_each(tgt_node, &__stp_task_finder_list) {
+ struct stap_task_finder_target *tgt;
+ struct list_head *cb_node;
+
+ tgt = list_entry(tgt_node,
+ struct stap_task_finder_target, list);
+ if (tgt == NULL)
+ continue;
+ /* pathname-based target */
+ else if (tgt->pathlen > 0
+ && (tgt->pathlen != mmpathlen
+ || strcmp(tgt->pathname, mmpath) != 0))
+ continue;
+ /* pid-based target */
+ else if (tgt->pid != 0 && tgt->pid != tsk->pid)
+ continue;
+
+ list_for_each(cb_node, &tgt->callback_list_head) {
+ struct stap_task_finder_target *cb_tgt;
+ cb_tgt = list_entry(cb_node,
+ struct stap_task_finder_target,
+ callback_list);
+ if (cb_tgt == NULL || cb_tgt->callback == NULL)
+ continue;
+
+ // Call the callback.
+ rc = cb_tgt->callback(tsk, 1, cb_tgt);
+ if (rc != 0) {
+ _stp_error("attach callback for %d failed: %d",
+ (int)tsk->pid, rc);
+ break;
+ }
+ }
+ }
+ }
+ rcu_read_unlock();
+ _stp_kfree(mmpath_buf);
+ return rc;
+}
+
+static void
+stap_stop_task_finder(void)
+{
+ stap_utrace_detach_ops(&__stp_utrace_task_finder_ops);
+ __stp_task_finder_cleanup();
+}
diff --git a/session.h b/session.h
index b06d9ecc..d8f3e38a 100644
--- a/session.h
+++ b/session.h
@@ -88,6 +88,7 @@ struct systemtap_session
bool timing;
bool keep_tmpdir;
bool guru_mode;
+ bool listing_mode;
bool bulk_mode;
bool unoptimized;
bool merge;
diff --git a/stap.1.in b/stap.1.in
index acfc64c3..db64748f 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -45,6 +45,15 @@ stap \- systemtap script translator/driver
[
.I ARGUMENTS
]
+.br
+.B stap
+[
+.I OPTIONS
+]
+.BI \-l " PROBE"
+[
+.I ARGUMENTS
+]
.SH DESCRIPTION
@@ -153,6 +162,11 @@ Start the probes, run CMD, and exit when CMD finishes.
.BI \-x " PID"
Sets target() to PID. This allows scripts to be written that filter on
a specific process.
+.TP
+.BI \-l " PROBE"
+Instead of running a probe script, just list all available probe
+points matching the given pattern. The pattern may include wildcards
+and aliases.
.SH ARGUMENTS
diff --git a/stapex.5.in b/stapex.5.in
index 86e1c87b..2c9ecb60 100644
--- a/stapex.5.in
+++ b/stapex.5.in
@@ -101,11 +101,9 @@ probe kernel.function("sys_mkdir") { println ("enter") }
probe kernel.function("sys_mkdir").return { println ("exit") }
.ESAMPLE
-To list the probeable functions in the kernel, use the last-pass
-option to the translator. That output needs to be filtered because
-each inlined function instance is listed separately.
+To list the probeable functions in the kernel, use the listings mode.
.SAMPLE
-% stap \-p2 \-e \[aq]probe kernel.function("*") {}\[aq] | sort | uniq
+% stap \-l \[aq]kernel.function("*")\[aq]
.ESAMPLE
.SH SEE ALSO
diff --git a/tapsets.cxx b/tapsets.cxx
index 079d87e8..a7f8034e 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -104,6 +104,7 @@ struct be_derived_probe: public derived_probe
struct be_derived_probe_group: public generic_dpg<be_derived_probe>
{
public:
+ void emit_module_header (systemtap_session& ) { };
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -205,6 +206,8 @@ common_probe_entryfn_prologue (translator_output* o, string statestr,
o->newline() << "c->last_error = 0;";
o->newline() << "c->nesting = 0;";
o->newline() << "c->regs = 0;";
+ o->newline() << "c->unwaddr = 0;";
+ // reset unwound address cache
o->newline() << "c->pi = 0;";
o->newline() << "c->probe_point = 0;";
if (! interruptible)
@@ -2066,6 +2069,7 @@ private:
public:
void enroll (dwarf_derived_probe* probe);
+ void emit_module_header (systemtap_session& s);
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -3925,17 +3929,22 @@ dwarf_derived_probe_group::enroll (dwarf_derived_probe* p)
void
-dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
+dwarf_derived_probe_group::emit_module_header (systemtap_session& s)
{
if (probes_by_module.empty()) return;
- s.op->newline() << "/* ---- dwarf probes ---- */";
-
- // Warn of misconfigured kernels
+ // Warn of misconfigured kernels
s.op->newline() << "#if ! defined(CONFIG_KPROBES)";
s.op->newline() << "#error \"Need CONFIG_KPROBES!\"";
s.op->newline() << "#endif";
- s.op->newline();
+}
+
+void
+dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
+{
+ if (probes_by_module.empty()) return;
+
+ s.op->newline() << "/* ---- dwarf probes ---- */";
// Forward declare the master entry functions
s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,";
@@ -4262,6 +4271,7 @@ struct uprobe_derived_probe: public derived_probe
struct uprobe_derived_probe_group: public generic_dpg<uprobe_derived_probe>
{
public:
+ void emit_module_header (systemtap_session& s);
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -4311,10 +4321,9 @@ struct uprobe_builder: public derived_probe_builder
void
-uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
+uprobe_derived_probe_group::emit_module_header (systemtap_session& s)
{
if (probes.empty()) return;
- s.op->newline() << "/* ---- user probes ---- */";
// If uprobes isn't in the kernel, pull it in from the runtime.
s.op->newline() << "#if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)";
@@ -4322,6 +4331,14 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "#else";
s.op->newline() << "#include \"uprobes/uprobes.h\"";
s.op->newline() << "#endif";
+}
+
+
+void
+uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
+{
+ if (probes.empty()) return;
+ s.op->newline() << "/* ---- user probes ---- */";
s.op->newline() << "struct stap_uprobe {";
s.op->newline(1) << "union { struct uprobe up; struct uretprobe urp; };";
@@ -4440,6 +4457,7 @@ struct timer_derived_probe_group: public generic_dpg<timer_derived_probe>
{
void emit_interval (translator_output* o);
public:
+ void emit_module_header (systemtap_session& ) { };
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -4581,6 +4599,7 @@ struct profile_derived_probe: public derived_probe
struct profile_derived_probe_group: public generic_dpg<profile_derived_probe>
{
public:
+ void emit_module_header (systemtap_session& ) { };
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -4709,6 +4728,7 @@ profile_derived_probe_group::emit_module_exit (systemtap_session& s)
}
+
// ------------------------------------------------------------------------
// procfs file derived probes
// ------------------------------------------------------------------------
@@ -4747,6 +4767,7 @@ public:
has_read_probes(false), has_write_probes(false) {}
void enroll (procfs_derived_probe* probe);
+ void emit_module_header (systemtap_session& ) { };
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -5187,6 +5208,7 @@ procfs_builder::build(systemtap_session & sess,
}
+
// ------------------------------------------------------------------------
// statically inserted macro-based derived probes
// ------------------------------------------------------------------------
@@ -5221,6 +5243,7 @@ struct mark_derived_probe: public derived_probe
struct mark_derived_probe_group: public generic_dpg<mark_derived_probe>
{
public:
+ void emit_module_header (systemtap_session& s);
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -5659,18 +5682,26 @@ mark_derived_probe::initialize_probe_context_vars (translator_output* o)
void
-mark_derived_probe_group::emit_module_decls (systemtap_session& s)
+mark_derived_probe_group::emit_module_header (systemtap_session& s)
{
if (probes.empty())
return;
- s.op->newline() << "/* ---- marker probes ---- */";
-
// Warn of misconfigured kernels
s.op->newline() << "#if ! defined(CONFIG_MARKERS)";
s.op->newline() << "#error \"Need CONFIG_MARKERS!\"";
s.op->newline() << "#endif";
+ s.op->newline() << "#include <linux/marker.h>";
s.op->newline();
+}
+
+void
+mark_derived_probe_group::emit_module_decls (systemtap_session& s)
+{
+ if (probes.empty())
+ return;
+
+ s.op->newline() << "/* ---- marker probes ---- */";
s.op->newline() << "struct stap_marker_probe {";
s.op->newline(1) << "const char * const name;";
@@ -5885,6 +5916,7 @@ mark_builder::build(systemtap_session & sess,
}
+
// ------------------------------------------------------------------------
// hrtimer derived probes
// ------------------------------------------------------------------------
@@ -5926,6 +5958,7 @@ struct hrtimer_derived_probe_group: public generic_dpg<hrtimer_derived_probe>
{
void emit_interval (translator_output* o);
public:
+ void emit_module_header (systemtap_session& ) { };
void emit_module_decls (systemtap_session& s);
void emit_module_init (systemtap_session& s);
void emit_module_exit (systemtap_session& s);
@@ -6178,6 +6211,7 @@ timer_builder::register_patterns(match_node *root)
}
+
// ------------------------------------------------------------------------
// perfmon derived probes
// ------------------------------------------------------------------------
@@ -6280,6 +6314,7 @@ public:
struct perfmon_derived_probe_group: public generic_dpg<perfmon_derived_probe>
{
public:
+ void emit_module_header (systemtap_session& ) { };
void emit_module_decls (systemtap_session&) {}
void emit_module_init (systemtap_session&) {}
void emit_module_exit (systemtap_session&) {}
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
new file mode 100644
index 00000000..34a4e8d0
--- /dev/null
+++ b/testsuite/.gitignore
@@ -0,0 +1,4 @@
+.systemtap
+site.exp
+systemtap.log
+systemtap.sum
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index da789127..8bfb1ce4 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2008-04-10 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 2949
+ * systemtap.base/cmd_parse.exp: Add "-l" listing test.
+
+2008-04-04 Masami Hiramatsu <mhiramat@redhat.com>
+
+ PR 5528
+ * systemtap.stress/conversions.exp: Update a script to catch up
+ recently changes of conversions.stp.
+
2008-03-31 Frank Ch. Eigler <fche@elastic.org>
* configure.ac: Bump version to 0.7.
diff --git a/testsuite/systemtap.base/cmd_parse.exp b/testsuite/systemtap.base/cmd_parse.exp
index ff347a9d..cbce0455 100644
--- a/testsuite/systemtap.base/cmd_parse.exp
+++ b/testsuite/systemtap.base/cmd_parse.exp
@@ -75,3 +75,12 @@ expect {
eof {fail "cmd_parse7: unexpected EOF"}
}
wait
+
+spawn stap -l {vm.*}
+expect {
+ -timeout 60
+ -re "vm.*" {pass "cmd_parse8"}
+ timeout {fail "cmd_parse8: unexpected timeout"}
+ eof {fail "cmd_parse8: unexpected EOF"}
+}
+wait
diff --git a/testsuite/systemtap.stress/conversions.exp b/testsuite/systemtap.stress/conversions.exp
index 34cd3889..9c2c2fa9 100644
--- a/testsuite/systemtap.stress/conversions.exp
+++ b/testsuite/systemtap.stress/conversions.exp
@@ -12,13 +12,12 @@ foreach value {0 0xffffffff 0xffffffffffffffff} {
verbose -log "exp $test $errs"
expect {
-timeout 180
- -re {ERROR[^\r\n]*\r\n} { incr errs; exp_continue }
- -re {WARNING[^\r\n]*\r\n} { incr errs; exp_continue }
+ -re {(ERROR|WARNING)[^\r\n]*\r\n} { incr errs; exp_continue }
eof { }
timeout { fail "$test (timeout)" }
}
verbose -log "done exp $test $errs"
wait
- if {$errs == 9} { pass $test } else { fail "$test ($errs)" }
+ if {$errs == 14} { pass $test } else { fail "$test ($errs)" }
verbose -log "done $test $errs"
}
diff --git a/translate.cxx b/translate.cxx
index a72cb1d8..776e6770 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -849,6 +849,11 @@ translator_output::line ()
void
c_unparser::emit_common_header ()
{
+ vector<derived_probe_group*> g = all_session_groups (*session);
+ for (unsigned i=0; i<g.size(); i++)
+ g[i]->emit_module_header (*session);
+
+ o->newline();
o->newline() << "typedef char string_t[MAXSTRINGLEN];";
o->newline();
o->newline() << "#define STAP_SESSION_STARTING 0";
@@ -874,6 +879,8 @@ c_unparser::emit_common_header ()
// See c_unparser::visit_statement()
o->newline() << "const char *last_stmt;";
o->newline() << "struct pt_regs *regs;";
+ o->newline() << "unsigned long *unwaddr;";
+ // unwaddr is caching unwound address in each probe handler on ia64.
o->newline() << "struct kretprobe_instance *pi;";
o->newline() << "va_list *mark_va_list;";
o->newline() << "void *data;";
@@ -4568,10 +4575,6 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#define read_trylock(x) ({ read_lock(x); 1; })";
s.op->newline() << "#endif";
- s.op->newline() << "#if defined(CONFIG_MARKERS)";
- s.op->newline() << "#include <linux/marker.h>";
- s.op->newline() << "#endif";
-
s.up->emit_common_header (); // context etc.
for (unsigned i=0; i<s.embeds.size(); i++)