summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-08-04 12:35:41 -0400
committerDave Brolley <brolley@redhat.com>2009-08-04 12:35:41 -0400
commitbc9077d171b8250a93a1b5a481e34913e5585dd5 (patch)
tree1fa945c76a66e297e783354ccd7a860aa65d304b
parent3174c3ca37371d738b86d630dc4d8b15104e57d0 (diff)
parent8b095b454b34e88c04592be6c651153f802eced6 (diff)
downloadsystemtap-steved-bc9077d171b8250a93a1b5a481e34913e5585dd5.tar.gz
systemtap-steved-bc9077d171b8250a93a1b5a481e34913e5585dd5.tar.xz
systemtap-steved-bc9077d171b8250a93a1b5a481e34913e5585dd5.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
Conflicts: cache.cxx
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in2
-rw-r--r--NEWS3
-rw-r--r--cache.cxx7
-rwxr-xr-xconfigure480
-rw-r--r--doc/Makefile.in131
-rwxr-xr-xdoc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh4
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.in71
-rwxr-xr-xdtrace.in17
-rw-r--r--dwflpp.cxx107
-rw-r--r--dwflpp.h3
-rw-r--r--elaborate.cxx100
-rw-r--r--grapher/Graph.cxx262
-rw-r--r--grapher/Graph.hxx48
-rw-r--r--grapher/GraphData.hxx49
-rw-r--r--grapher/GraphWidget.cxx251
-rw-r--r--grapher/GraphWidget.hxx38
-rw-r--r--grapher/Makefile.am2
-rw-r--r--grapher/Makefile.in162
-rw-r--r--grapher/StapParser.cxx204
-rw-r--r--grapher/StapParser.hxx23
-rw-r--r--grapher/grapher.cxx200
-rw-r--r--loc2c.c13
-rw-r--r--main.cxx49
-rw-r--r--parse.cxx74
-rw-r--r--parse.h3
-rw-r--r--runtime/staprun/common.c1
-rw-r--r--runtime/staprun/mainloop.c1
-rw-r--r--runtime/staprun/staprun.c1
-rw-r--r--runtime/staprun/staprun.h3
-rw-r--r--runtime/staprun/staprun_funcs.c1
-rw-r--r--runtime/transport/ring_buffer.c178
-rw-r--r--runtime/unwind/i386.h2
-rw-r--r--runtime/unwind/x86_64.h2
-rw-r--r--session.h1
-rw-r--r--stap.1.in2
-rw-r--r--staptree.cxx187
-rw-r--r--staptree.h46
-rw-r--r--tapset-mark.cxx38
-rw-r--r--tapset-perfmon.cxx21
-rw-r--r--tapset-procfs.cxx21
-rw-r--r--tapset-utrace.cxx141
-rw-r--r--tapset/stap_staticmarkers.stp267
-rw-r--r--tapsets.cxx1097
-rw-r--r--testsuite/Makefile.in40
-rw-r--r--testsuite/aclocal.m4145
-rwxr-xr-xtestsuite/configure245
-rwxr-xr-xtestsuite/semok/bz10475.stp10
-rw-r--r--testsuite/systemtap.base/bz6905.c7
-rw-r--r--testsuite/systemtap.base/bz6905.exp25
-rw-r--r--testsuite/systemtap.base/bz6905.stp4
-rw-r--r--testsuite/systemtap.base/cmd_parse.exp2
-rw-r--r--testsuite/systemtap.base/crash.exp2
-rw-r--r--testsuite/systemtap.base/pointer_array.stp11
-rw-r--r--testsuite/systemtap.base/utrace_p4.exp19
-rw-r--r--testsuite/systemtap.base/utrace_p5.exp22
-rw-r--r--testsuite/systemtap.context/uprobe_stmt_num.c20
-rw-r--r--testsuite/systemtap.context/uprobe_stmt_num.exp78
-rw-r--r--testsuite/systemtap.context/uprobe_stmt_num.stp4
-rw-r--r--[-rwxr-xr-x]testsuite/systemtap.examples/general/grapher.stp23
-rw-r--r--testsuite/systemtap.exelib/ustack.tcl9
-rw-r--r--translate.cxx16
-rw-r--r--util.cxx4
63 files changed, 3356 insertions, 1645 deletions
diff --git a/Makefile.am b/Makefile.am
index 37491eef..c2234d1c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = no-dist foreign
pkglibexecdir = ${libexecdir}/${PACKAGE}
oldincludedir = ${includedir}/sys
-AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"'
+AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' -I$(srcdir)/includes
AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W
AM_CXXFLAGS = -Wall -Werror
diff --git a/Makefile.in b/Makefile.in
index 9410eaae..a1b45add 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -358,7 +358,7 @@ top_srcdir = @top_srcdir@
# we don't maintain a ChangeLog, which makes us non-GNU -> foreign
AUTOMAKE_OPTIONS = no-dist foreign
-AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"'
+AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DPKGDATADIR='"${pkgdatadir}"' -DPKGLIBDIR='"$(pkglibexecdir)"' -I$(srcdir)/includes
AM_CFLAGS = -D_GNU_SOURCE -fexceptions -Wall -Werror -Wunused -Wformat=2 -W
AM_CXXFLAGS = -Wall -Werror
man_MANS = stapprobes.3stap stapfuncs.3stap stapvars.3stap \
diff --git a/NEWS b/NEWS
index 8fa10401..a56787bd 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,9 @@
- Systemwide kernel .function.return (kretprobe) maxactive defaults may
be overridden with the -DKRETACTIVE=nnn parameter.
+- Translation pass 2 is significantly faster by avoiding unnecessary
+ searching through a kernel build/module directory tree.
+
* What's new in version 0.9.8
- Miscellaneous new tapset functions:
diff --git a/cache.cxx b/cache.cxx
index 200e51e9..ee6d0bf6 100644
--- a/cache.cxx
+++ b/cache.cxx
@@ -10,6 +10,7 @@
#include "session.h"
#include "cache.h"
#include "util.h"
+#include "sys/sdt.h"
#include <cerrno>
#include <string>
#include <fstream>
@@ -59,6 +60,7 @@ add_to_cache(systemtap_session& s)
}
string module_src_path = s.tmpdir + "/" + s.module_name + ".ko";
+ STAP_PROBE2(stap, cache__add__module, module_src_path.c_str(), s.hash_path.c_str());
if (s.verbose > 1)
clog << "Copying " << module_src_path << " to " << s.hash_path << endl;
if (copy_file(module_src_path.c_str(), s.hash_path.c_str()) != 0)
@@ -81,6 +83,7 @@ add_to_cache(systemtap_session& s)
if (file_exists (module_signature_src_path))
{
+ STAP_PROBE2(stap, cache__add__nss, module_signature_src_path.c_str(), module_signature_dest_path.c_str());
if (s.verbose > 1)
clog << "Copying " << module_signature_src_path << " to " << module_signature_dest_path << endl;
if (copy_file(module_signature_src_path.c_str(), module_signature_dest_path.c_str()) != 0)
@@ -100,6 +103,7 @@ add_to_cache(systemtap_session& s)
c_dest_path.resize(c_dest_path.size() - 3);
c_dest_path += ".c";
+ STAP_PROBE2(stap, cache__add__source, s.translated_source.c_str(), c_dest_path.c_str());
if (s.verbose > 1)
clog << "Copying " << s.translated_source << " to " << c_dest_path
<< endl;
@@ -244,6 +248,8 @@ get_from_cache(systemtap_session& s)
clog << "Pass 4: using cached " << s.hash_path << endl;
}
+ STAP_PROBE2(stap, cache__get, c_src_path.c_str(), s.hash_path.c_str());
+
return true;
}
@@ -344,6 +350,7 @@ clean_cache(systemtap_session& s)
if ( (r_cache_size / 1024 / 1024) < cache_mb_max) //convert r_cache_size to MiB
break;
+ STAP_PROBE1(stap, cache__clean, (i->path).c_str());
//remove this (*i) cache_entry, add to removed list
i->unlink();
r_cache_size -= i->size;
diff --git a/configure b/configure
index 5eb5eb05..e646b3c6 100755
--- a/configure
+++ b/configure
@@ -637,7 +637,9 @@ ac_includes_default="\
#endif"
enable_option_checking=no
-ac_subst_vars='LTLIBOBJS
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
LIBOBJS
subdirs
CXXCPP
@@ -1943,7 +1945,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-am__api_version='1.10'
+am__api_version='1.11'
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@@ -2074,16 +2076,33 @@ $as_echo_n "checking whether build environment is sane... " >&6; }
# Just in case
sleep 1
echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ { { $as_echo "$as_me:$LINENO: error: unsafe absolute working directory name" >&5
+$as_echo "$as_me: error: unsafe absolute working directory name" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ { { $as_echo "$as_me:$LINENO: error: unsafe srcdir value: \`$srcdir'" >&5
+$as_echo "$as_me: error: unsafe srcdir value: \`$srcdir'" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
- set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$*" = "X"; then
# -L didn't work.
- set X `ls -t $srcdir/configure conftest.file`
+ set X `ls -t "$srcdir/configure" conftest.file`
fi
rm -f conftest.file
if test "$*" != "X $srcdir/configure conftest.file" \
@@ -2127,7 +2146,14 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
-test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
@@ -2137,6 +2163,115 @@ else
$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
fi
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
{ $as_echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
if test -z "$MKDIR_P"; then
@@ -2319,108 +2454,6 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
-install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
-
-# Installed binaries are usually stripped using `strip' when the user
-# run `make install-strip'. However `strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the `STRIP' environment variable to overrule this program.
-if test "$cross_compiling" != no; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_STRIP+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- if test -n "$STRIP"; then
- ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_STRIP="${ac_tool_prefix}strip"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
- { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
-$as_echo "$STRIP" >&6; }
-else
- { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_STRIP"; then
- ac_ct_STRIP=$STRIP
- # Extract the first word of "strip", so it can be a program name with args.
-set dummy strip; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_STRIP"; then
- ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_STRIP="strip"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
-if test -n "$ac_ct_STRIP"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
-$as_echo "$ac_ct_STRIP" >&6; }
-else
- { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_STRIP" = x; then
- STRIP=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- STRIP=$ac_ct_STRIP
- fi
-else
- STRIP="$ac_cv_prog_STRIP"
-fi
-
-fi
-INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
-
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
# Always define AMTAR for backward compatibility.
@@ -2433,6 +2466,7 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
{ $as_echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
# Check whether --enable-maintainer-mode was given.
@@ -3414,7 +3448,7 @@ ac_config_commands="$ac_config_commands depfiles"
am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
- @echo done
+ @echo this is the am__doit target
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
@@ -3425,24 +3459,24 @@ am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
-# We grep out `Entering directory' and `Leaving directory'
-# messages which can occur if `w' ends up in MAKEFLAGS.
-# In particular we don't look at `^make:' because GNU make might
-# be invoked under some other name (usually "gmake"), in which
-# case it prints its new name instead of `make'.
-if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
- am__include=include
- am__quote=
- _am_result=GNU
-fi
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
- if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
- am__include=.include
- am__quote="\""
- _am_result=BSD
- fi
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
fi
@@ -3499,6 +3533,11 @@ else
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
@@ -3516,7 +3555,17 @@ else
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
@@ -3526,19 +3575,23 @@ else
break
fi
;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
none) break ;;
esac
- # We check with `-c' and `-o' for the sake of the "dashmstdout"
- # mode. It turns out that the SunPro C++ compiler does not properly
- # handle `-M -o', and we need to detect this.
if depmode=$depmode \
- source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
@@ -3979,6 +4032,11 @@ else
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
@@ -3996,7 +4054,17 @@ else
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
@@ -4006,19 +4074,23 @@ else
break
fi
;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
none) break ;;
esac
- # We check with `-c' and `-o' for the sake of the "dashmstdout"
- # mode. It turns out that the SunPro C++ compiler does not properly
- # handle `-M -o', and we need to detect this.
if depmode=$depmode \
- source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
@@ -5006,6 +5078,11 @@ else
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
@@ -5023,7 +5100,17 @@ else
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
@@ -5033,19 +5120,23 @@ else
break
fi
;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
none) break ;;
esac
- # We check with `-c' and `-o' for the sake of the "dashmstdout"
- # mode. It turns out that the SunPro C++ compiler does not properly
- # handle `-M -o', and we need to detect this.
if depmode=$depmode \
- source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
@@ -8854,7 +8945,7 @@ _ACEOF
ac_config_headers="$ac_config_headers config.h:config.in"
-ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile grapher/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap"
+ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile grapher/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap man/stapprobes.snmp.3stap initscript/systemtap"
@@ -8965,6 +9056,14 @@ LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
{ { $as_echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
@@ -9596,6 +9695,7 @@ do
"man/stapprobes.socket.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.socket.3stap" ;;
"man/stapprobes.tcp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.tcp.3stap" ;;
"man/stapprobes.udp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.udp.3stap" ;;
+ "man/stapprobes.snmp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.snmp.3stap" ;;
"initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;;
"run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;;
"run-staprun") CONFIG_FILES="$CONFIG_FILES run-staprun" ;;
@@ -10254,27 +10354,28 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
case $ac_file$ac_mode in
- "depfiles":C) test x"$AMDEP_TRUE" != x"" || # Autoconf 2.62 quotes --file arguments for eval, but not when files
-# are listed without --file. Let's play safe and only enable the eval
-# if we detect the quoting.
-case $CONFIG_FILES in
-*\'*) eval set x "$CONFIG_FILES" ;;
-*) set x $CONFIG_FILES ;;
-esac
-shift
-for mf
-do
- # Strip MF so we end up with the name of the file.
- mf=`echo "$mf" | sed -e 's/:.*$//'`
- # Check whether this is an Automake generated Makefile or not.
- # We used to match only the files named `Makefile.in', but
- # some people rename them; so instead we look at the file content.
- # Grep'ing the first line is not enough: some people post-process
- # each Makefile.in and add a new line on top of each file to say so.
- # Grep'ing the whole file is not good either: AIX grep has a line
- # limit of 2048, but all sed's we know have understand at least 4000.
- if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
- dirpart=`$as_dirname -- "$mf" ||
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$mf" : 'X\(//\)[^/]' \| \
X"$mf" : 'X\(//\)$' \| \
@@ -10297,28 +10398,28 @@ $as_echo X"$mf" |
q
}
s/.*/./; q'`
- else
- continue
- fi
- # Extract the definition of DEPDIR, am__include, and am__quote
- # from the Makefile without running `make'.
- DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
- test -z "$DEPDIR" && continue
- am__include=`sed -n 's/^am__include = //p' < "$mf"`
- test -z "am__include" && continue
- am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
- # When using ansi2knr, U may be empty or an underscore; expand it
- U=`sed -n 's/^U = //p' < "$mf"`
- # Find all dependency output files, they are included files with
- # $(DEPDIR) in their names. We invoke sed twice because it is the
- # simplest approach to changing $(DEPDIR) to its actual value in the
- # expansion.
- for file in `sed -n "
- s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
- # Make sure the directory exists.
- test -f "$dirpart/$file" && continue
- fdir=`$as_dirname -- "$file" ||
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$file" : 'X\(//\)[^/]' \| \
X"$file" : 'X\(//\)$' \| \
@@ -10341,7 +10442,7 @@ $as_echo X"$file" |
q
}
s/.*/./; q'`
- { as_dir=$dirpart/$fdir
+ { as_dir=$dirpart/$fdir
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
@@ -10382,10 +10483,11 @@ $as_echo X"$as_dir" |
} || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
{ (exit 1); exit 1; }; }; }
- # echo "creating $dirpart/$file"
- echo '# dummy' > "$dirpart/$file"
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
done
-done
+}
;;
"run-stap":F) chmod +x run-stap ;;
"run-staprun":F) chmod +x run-staprun ;;
diff --git a/doc/Makefile.in b/doc/Makefile.in
index f7d902a7..996700ec 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -17,8 +18,9 @@
# Makefile.am --- automake input file for systemtap docs
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -40,6 +42,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
@@ -51,10 +54,38 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
ps-recursive uninstall-recursive
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
@@ -190,9 +221,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu doc/Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu doc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -210,6 +241,7 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
@@ -235,7 +267,7 @@ $(RECURSIVE_TARGETS):
else \
local_target="$$target"; \
fi; \
- (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
@@ -269,16 +301,16 @@ $(RECURSIVE_CLEAN_TARGETS):
else \
local_target="$$target"; \
fi; \
- (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
@@ -293,7 +325,7 @@ tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
+ set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
@@ -305,7 +337,7 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
- tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -314,29 +346,34 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
+ $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -357,29 +394,44 @@ distdir: $(DISTFILES)
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
- list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
- distdir=`$(am__cd) $(distdir) && pwd`; \
- top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
- (cd $$subdir && \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
- top_distdir="$$top_distdir" \
- distdir="$$distdir/$$subdir" \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
+ am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
@@ -410,6 +462,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -431,6 +484,8 @@ dvi-am:
html: html-recursive
+html-am:
+
info: info-recursive
info-am:
@@ -438,21 +493,30 @@ info-am:
install-data-am:
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-data-hook
-
install-dvi: install-dvi-recursive
+install-dvi-am:
+
install-exec-am:
install-html: install-html-recursive
+install-html-am:
+
install-info: install-info-recursive
+install-info-am:
+
install-man:
install-pdf: install-pdf-recursive
+install-pdf-am:
+
install-ps: install-ps-recursive
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-recursive
@@ -473,8 +537,8 @@ ps-am:
uninstall-am: uninstall-local
-.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
- install-data-am install-strip
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-data-am install-strip tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am all-local check check-am clean clean-generic \
@@ -520,6 +584,7 @@ uninstall-am: uninstall-local
latex -output-directory=$$pwd $<; \
latex -output-directory=$$pwd $<; \
latex -output-directory=$$pwd $<
+
# 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/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh b/doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh
index 6905c9cc..3c6bf785 100755
--- a/doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh
+++ b/doc/SystemTap_Beginners_Guide/en-US/extras/stapprep.sh
@@ -26,6 +26,10 @@ if [ "$NEEDED" != "" ]; then
echo -e "Need to install the following packages:\n$NEEDED"
if [ `id -u` = "0" ]; then #attempt download and install
DIR=`mktemp -d` || exit 1
+ if [ ! -x /usr/bin/yumdownloader ]; then
+ echo "Need to first install yum-utils for yumdownloader"
+ yum install -y yum-utils
+ fi
yumdownloader --enablerepo="*debuginfo*" $NEEDED --destdir=$DIR
check_error $? "problem downloading rpm(s) $NEEDED"
rpm --force -ivh $DIR/*.rpm
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in
index 82217f3a..2368ccad 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.in
+++ b/doc/SystemTap_Tapset_Reference/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -18,8 +19,9 @@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -42,6 +44,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
docproc_SOURCES = docproc.c
docproc_OBJECTS = docproc.$(OBJEXT)
@@ -49,6 +52,7 @@ docproc_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
+am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@@ -195,9 +199,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu doc/SystemTap_Tapset_Reference/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -215,6 +219,7 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
clean-noinstPROGRAMS:
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
@@ -232,14 +237,14 @@ distclean-compile:
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
@@ -256,7 +261,7 @@ tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
+ set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -264,29 +269,34 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
+ $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -307,13 +317,17 @@ distdir: $(DISTFILES)
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@@ -341,6 +355,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -362,6 +377,8 @@ dvi-am:
html: html-am
+html-am:
+
info: info-am
info-am:
@@ -369,21 +386,30 @@ info-am:
install-data-am:
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-data-hook
-
install-dvi: install-dvi-am
+install-dvi-am:
+
install-exec-am:
install-html: install-html-am
+install-html-am:
+
install-info: install-info-am
+install-info-am:
+
install-man:
install-pdf: install-pdf-am
+install-pdf-am:
+
install-ps: install-ps-am
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-am
@@ -452,6 +478,7 @@ 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)
+
# 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/dtrace.in b/dtrace.in
index 91885977..168bfb18 100755
--- a/dtrace.in
+++ b/dtrace.in
@@ -137,6 +137,7 @@ i = 1
build_header = False
build_source = False
add_typedefs = False
+h_ext = '.h'
filename = ""
while (i < len (sys.argv)):
if (sys.argv[i] == "-o"):
@@ -148,7 +149,6 @@ while (i < len (sys.argv)):
elif (sys.argv[i] == "-h"):
build_header = True
elif (sys.argv[i] == "-G"):
- build_header = True
build_source = True
elif (sys.argv[i] == "--types"):
add_typedefs = True
@@ -162,22 +162,23 @@ if (build_header == False and build_source == False):
if (filename == ""):
if (s_filename != ""):
(filename,ext) = os.path.splitext(s_filename)
- filename = os.path.basename(filename)
else:
usage
sys.exit(1)
else:
- (filename,ext) = os.path.splitext(filename)
-
+ if (build_header):
+ h_ext = ""
+ else:
+ (filename,ext) = os.path.splitext(filename)
if (build_header):
providers = provider()
- providers.generate(s_filename, filename + ".h", add_typedefs)
-if (build_source):
+ providers.generate(s_filename, filename + h_ext, add_typedefs)
+elif (build_source):
(basename,ext) = os.path.splitext(s_filename)
basename = os.path.basename(basename)
(d,fn) = mkstemp(suffix=".c",prefix=basename)
f = open(fn,mode='w')
- f.write("#include \"" + filename + ".h\"\nstatic __dtrace () {}\n")
+ f.write("static __dtrace () {}\n")
f.close()
- call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"], shell=False)
+ call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", os.path.basename(filename) + ".o"], shell=False)
os.remove(fn)
diff --git a/dwflpp.cxx b/dwflpp.cxx
index ce9993c8..6ede1d68 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -124,7 +124,7 @@ dwflpp::get_module_dwarf(bool required, bool report)
if (required)
throw semantic_error (msg);
- else
+ else if (! sess.suppress_warnings)
cerr << "WARNING: " << msg << "\n";
}
}
@@ -808,19 +808,43 @@ dwflpp::iterate_over_srcfile_lines (char const * srcfile,
}
else if (line_type == WILDCARD)
function_line (&lineno);
+ else if (line_type == RANGE) { /* correct lineno */
+ int start_lineno;
+
+ function_line (&start_lineno);
+ lineno = lineno < start_lineno ? start_lineno : lineno;
+ if (lineno > lines[1]) { /* invalid line range */
+ stringstream advice;
+ advice << "Invalid line range (" << lines[0] << "-" << lines[1] << ")";
+ if (start_lineno > lines[1])
+ advice << ", the end line number " << lines[1] << " < " << start_lineno;
+ throw semantic_error (advice.str());
+ }
+ }
+
for (int l = lineno; ; l = l + 1)
{
set<int> lines_probed;
pair<set<int>::iterator,bool> line_probed;
- dwarf_assert ("dwarf_getsrc_file",
- dwarf_getsrc_file (module_dwarf,
- srcfile, l, 0,
- &srcsp, &nsrcs));
+ int ret = 0;
+
+ ret = dwarf_getsrc_file (module_dwarf, srcfile, l, 0,
+ &srcsp, &nsrcs);
+ if (line_type != WILDCARD && line_type != RANGE)
+ dwarf_assert ("dwarf_getsrc_file", ret);
+
if (line_type == WILDCARD || line_type == RANGE)
{
Dwarf_Addr line_addr;
+
+ if (ret != 0) /* tolerate invalid line number */
+ break;
+
dwarf_lineno (srcsp [0], &lineno);
+ /* Maybe lineno will exceed the input end */
+ if (line_type == RANGE && lineno > lines[1])
+ break;
line_probed = lines_probed.insert(lineno);
if (lineno != l || line_probed.second == false || nsrcs > 1)
continue;
@@ -1596,9 +1620,8 @@ dwflpp::print_members(Dwarf_Die *vardie, ostream &o)
bool
-dwflpp::find_struct_member(const string& member,
+dwflpp::find_struct_member(const target_symbol::component& c,
Dwarf_Die *parentdie,
- const target_symbol *e,
Dwarf_Die *memberdie,
vector<Dwarf_Attribute>& locs)
{
@@ -1616,7 +1639,7 @@ dwflpp::find_struct_member(const string& member,
throw semantic_error (string (dwarf_tag(&die) == DW_TAG_union_type ? "union" : "struct")
+ string (dwarf_diename_integrate (&die) ?: "<anonymous>")
+ string (dwarf_errmsg (-1)),
- e->tok);
+ c.tok);
}
do
@@ -1634,10 +1657,10 @@ dwflpp::find_struct_member(const string& member,
!dwarf_formref_die (&attr, &subdie))
continue;
- if (find_struct_member(member, &subdie, e, memberdie, locs))
+ if (find_struct_member(c, &subdie, memberdie, locs))
goto success;
}
- else if (name == member)
+ else if (name == c.member)
{
*memberdie = die;
goto success;
@@ -1656,9 +1679,9 @@ success:
/* Union members don't usually have a location,
* but just use the containing union's location. */
else if (dwarf_tag(parentdie) != DW_TAG_union_type)
- throw semantic_error ("no location for field '" + member
+ throw semantic_error ("no location for field '" + c.member
+ "': " + string(dwarf_errmsg (-1)),
- e->tok);
+ c.tok);
return true;
}
@@ -1685,6 +1708,8 @@ dwflpp::translate_components(struct obstack *pool,
while (i < e->components.size())
{
+ const target_symbol::component& c = e->components[i];
+
/* XXX: This would be desirable, but we don't get the target_symbol token,
and printing that gives us the file:line number too early anyway. */
#if 0
@@ -1706,39 +1731,53 @@ dwflpp::translate_components(struct obstack *pool,
case DW_TAG_pointer_type:
c_translate_pointer (pool, 1, 0 /* PR9768*/, die, tail);
- if (e->components[i].first != target_symbol::comp_literal_array_index)
+ if (c.type != target_symbol::comp_literal_array_index &&
+ c.type != target_symbol::comp_expression_array_index)
break;
/* else fall through as an array access */
case DW_TAG_array_type:
- if (e->components[i].first == target_symbol::comp_literal_array_index)
+ if (c.type == target_symbol::comp_literal_array_index)
{
c_translate_array (pool, 1, 0 /* PR9768 */, die, tail,
- NULL, lex_cast<Dwarf_Word>(e->components[i].second));
+ NULL, c.num_index);
+ ++i;
+ }
+ else if (c.type == target_symbol::comp_expression_array_index)
+ {
+ string index = "THIS->index" + lex_cast<string>(i);
+ c_translate_array (pool, 1, 0 /* PR9768 */, die, tail,
+ index.c_str(), 0);
++i;
}
else
- throw semantic_error("bad field '"
- + e->components[i].second
- + "' for array type",
- e->tok);
+ throw semantic_error ("invalid access '"
+ + lex_cast<string>(c)
+ + "' for array type",
+ c.tok);
break;
case DW_TAG_structure_type:
case DW_TAG_union_type:
+ if (c.type != target_symbol::comp_struct_member)
+ throw semantic_error ("invalid access '"
+ + lex_cast<string>(c)
+ + "' for struct/union type",
+ c.tok);
+
if (dwarf_hasattr(die, DW_AT_declaration))
{
Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die));
if (tmpdie == NULL)
throw semantic_error ("unresolved struct "
+ string (dwarf_diename_integrate (die) ?: "<anonymous>"),
- e->tok);
+ c.tok);
*die_mem = *tmpdie;
}
{
vector<Dwarf_Attribute> locs;
- if (!find_struct_member(e->components[i].second, die, e, die, locs))
+ if (!find_struct_member(c, die, die, locs))
{
string alternatives;
stringstream members;
@@ -1746,10 +1785,10 @@ dwflpp::translate_components(struct obstack *pool,
if (members.str().size() != 0)
alternatives = " (alternatives:" + members.str();
throw semantic_error("unable to find member '" +
- e->components[i].second + "' for struct "
+ c.member + "' for struct "
+ string(dwarf_diename_integrate(die) ?: "<unknown>")
+ alternatives,
- e->tok);
+ c.tok);
}
for (unsigned j = 0; j < locs.size(); ++j)
@@ -1760,39 +1799,41 @@ dwflpp::translate_components(struct obstack *pool,
break;
case DW_TAG_enumeration_type:
- throw semantic_error ("field '"
- + e->components[i].second
+ throw semantic_error ("invalid access '"
+ + lex_cast<string>(c)
+ "' vs. enum type "
+ string(dwarf_diename_integrate (die) ?: "<anonymous type>"),
- e->tok);
+ c.tok);
break;
case DW_TAG_base_type:
- throw semantic_error ("field '"
- + e->components[i].second
+ throw semantic_error ("invalid access '"
+ + lex_cast<string>(c)
+ "' vs. base type "
+ string(dwarf_diename_integrate (die) ?: "<anonymous type>"),
- e->tok);
+ c.tok);
break;
case -1:
throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)),
- e->tok);
+ c.tok);
break;
default:
throw semantic_error (string(dwarf_diename_integrate (die) ?: "<anonymous type>")
+ ": unexpected type tag "
+ lex_cast<string>(dwarf_tag (die)),
- e->tok);
+ c.tok);
break;
}
/* Now iterate on the type in DIE's attribute. */
if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL)
- throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), e->tok);
+ throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)),
+ c.tok);
}
/* For an array index, we need to dereference the final DIE */
- if (e->components.back().first == target_symbol::comp_literal_array_index)
+ if (e->components.back().type == target_symbol::comp_literal_array_index ||
+ e->components.back().type == target_symbol::comp_expression_array_index)
die = dwarf_formref_die (attr_mem, die_mem);
return die;
diff --git a/dwflpp.h b/dwflpp.h
index 20bcc0d0..3cada4f8 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -333,9 +333,8 @@ private:
struct location **tail,
const target_symbol *e);
- bool find_struct_member(const std::string& member,
+ bool find_struct_member(const target_symbol::component& c,
Dwarf_Die *parentdie,
- const target_symbol *e,
Dwarf_Die *memberdie,
std::vector<Dwarf_Attribute>& locs);
diff --git a/elaborate.cxx b/elaborate.cxx
index 88c5deb9..93500239 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -1129,7 +1129,7 @@ semantic_pass_symbols (systemtap_session& s)
try
{
for (unsigned j=0; j<s.code_filters.size(); j++)
- fd->body = s.code_filters[j]->require (fd->body);
+ s.code_filters[j]->replace (fd->body);
sym.current_function = fd;
sym.current_probe = 0;
@@ -1164,7 +1164,7 @@ semantic_pass_symbols (systemtap_session& s)
try
{
for (unsigned k=0; k<s.code_filters.size(); k++)
- dp->body = s.code_filters[k]->require (dp->body);
+ s.code_filters[k]->replace (dp->body);
sym.current_function = 0;
sym.current_probe = dp;
@@ -2157,8 +2157,8 @@ struct dead_assignment_remover: public update_visitor
void
dead_assignment_remover::visit_assignment (assignment* e)
{
- e->left = require (e->left);
- e->right = require (e->right);
+ replace (e->left);
+ replace (e->right);
symbol* left = get_symbol_within_expression (e->left);
vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target
@@ -2224,10 +2224,10 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p)
// This instance may be reused for multiple probe/function body trims.
for (unsigned i=0; i<s.probes.size(); i++)
- s.probes[i]->body = dar.require (s.probes[i]->body);
+ dar.replace (s.probes[i]->body);
for (map<string,functiondecl*>::iterator it = s.functions.begin();
it != s.functions.end(); it++)
- it->second->body = dar.require (it->second->body);
+ dar.replace (it->second->body);
// The rewrite operation is performed within the visitor.
// XXX: we could also zap write-only globals here
@@ -2311,8 +2311,8 @@ dead_stmtexpr_remover::visit_block (block *s)
void
dead_stmtexpr_remover::visit_if_statement (if_statement *s)
{
- s->thenblock = require (s->thenblock, true);
- s->elseblock = require (s->elseblock, true);
+ replace (s->thenblock, true);
+ replace (s->elseblock, true);
if (s->thenblock == 0)
{
@@ -2364,7 +2364,7 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s)
void
dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
{
- s->block = require(s->block, true);
+ replace (s->block, true);
if (s->block == 0)
{
@@ -2378,7 +2378,7 @@ dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s)
void
dead_stmtexpr_remover::visit_for_loop (for_loop *s)
{
- s->block = require(s->block, true);
+ replace (s->block, true);
if (s->block == 0)
{
@@ -2467,7 +2467,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
duv.focal_vars.insert (p->locals.begin(),
p->locals.end());
- p->body = duv.require(p->body, true);
+ duv.replace (p->body, true);
if (p->body == 0)
{
if (! s.suppress_warnings
@@ -2493,7 +2493,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p)
duv.focal_vars.insert (s.globals.begin(),
s.globals.end());
- fn->body = duv.require(fn->body, true);
+ duv.replace (fn->body, true);
if (fn->body == 0)
{
if (! s.suppress_warnings)
@@ -2555,6 +2555,7 @@ struct void_statement_reducer: public update_visitor
void visit_concatenation (concatenation* e);
void visit_functioncall (functioncall* e);
void visit_print_format (print_format* e);
+ void visit_target_symbol (target_symbol* e);
void visit_cast_op (cast_op* e);
// these are a bit hairy to grok due to the intricacies of indexables and
@@ -2576,7 +2577,7 @@ struct void_statement_reducer: public update_visitor
void
void_statement_reducer::visit_expr_statement (expr_statement* s)
{
- s->value = require (s->value, true);
+ replace (s->value, true);
// if the expression provides 0, that's our signal that a new
// statement has been provided, so we shouldn't provide this one.
@@ -2588,8 +2589,8 @@ void
void_statement_reducer::visit_if_statement (if_statement* s)
{
// s->condition is never void
- s->thenblock = require (s->thenblock);
- s->elseblock = require (s->elseblock);
+ replace (s->thenblock);
+ replace (s->elseblock);
provide (s);
}
@@ -2597,7 +2598,7 @@ void
void_statement_reducer::visit_for_loop (for_loop* s)
{
// s->init/cond/incr are never void
- s->block = require (s->block);
+ replace (s->block);
provide (s);
}
@@ -2605,7 +2606,7 @@ void
void_statement_reducer::visit_foreach_loop (foreach_loop* s)
{
// s->indexes/base/limit are never void
- s->block = require (s->block);
+ replace (s->block);
provide (s);
}
@@ -2824,16 +2825,73 @@ void_statement_reducer::visit_print_format (print_format* e)
}
void
+void_statement_reducer::visit_target_symbol (target_symbol* e)
+{
+ // When target_symbol isn't needed, it's just as good to
+ // evaluate any array indexes directly
+
+ block *b = new block;
+ b->tok = e->tok;
+
+ for (unsigned i=0; i<e->components.size(); i++ )
+ {
+ if (e->components[i].type != target_symbol::comp_expression_array_index)
+ continue;
+
+ expr_statement *es = new expr_statement;
+ es->value = e->components[i].expr_index;
+ es->tok = es->value->tok;
+ b->statements.push_back(es);
+ }
+
+ if (b->statements.empty())
+ {
+ delete b;
+ provide (e);
+ return;
+ }
+
+ if (session.verbose>2)
+ clog << "Eliding unused target symbol " << *e->tok << endl;
+
+ b->visit(this);
+ relaxed_p = false;
+ e = 0;
+ provide (e);
+}
+
+void
void_statement_reducer::visit_cast_op (cast_op* e)
{
// When the result of a cast operation isn't needed, it's just as good to
- // evaluate the operand directly
+ // evaluate the operand and any array indexes directly
+
+ block *b = new block;
+ b->tok = e->tok;
+
+ expr_statement *es = new expr_statement;
+ es->value = e->operand;
+ es->tok = es->value->tok;
+ b->statements.push_back(es);
+
+ for (unsigned i=0; i<e->components.size(); i++ )
+ {
+ if (e->components[i].type != target_symbol::comp_expression_array_index)
+ continue;
+
+ es = new expr_statement;
+ es->value = e->components[i].expr_index;
+ es->tok = es->value->tok;
+ b->statements.push_back(es);
+ }
if (session.verbose>2)
clog << "Eliding unused typecast " << *e->tok << endl;
+ b->visit(this);
relaxed_p = false;
- e->operand->visit(this);
+ e = 0;
+ provide (e);
}
@@ -2847,10 +2905,10 @@ void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p)
vuv.focal_vars.insert (s.globals.begin(), s.globals.end());
for (unsigned i=0; i<s.probes.size(); i++)
- s.probes[i]->body = vuv.require (s.probes[i]->body);
+ vuv.replace (s.probes[i]->body);
for (map<string,functiondecl*>::iterator it = s.functions.begin();
it != s.functions.end(); it++)
- it->second->body = vuv.require (it->second->body);
+ vuv.replace (it->second->body);
}
diff --git a/grapher/Graph.cxx b/grapher/Graph.cxx
new file mode 100644
index 00000000..1fa598c2
--- /dev/null
+++ b/grapher/Graph.cxx
@@ -0,0 +1,262 @@
+#include "Graph.hxx"
+
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+namespace systemtap
+{
+ using namespace std;
+ using namespace std::tr1;
+
+ Graph::Graph()
+ : _left(0.0), _right(1.0), _top(5.0), _bottom(0.0), _lineWidth(2),
+ _autoScaling(true), _autoScrolling(true), _zoomFactor(1.0),
+ _playButton(new CairoPlayButton)
+ {
+ }
+
+
+ void Graph::draw(Cairo::RefPtr<Cairo::Context> cr)
+ {
+
+ if (_autoScaling)
+ {
+ // line separation
+ int linesPossible = _graphWidth / (_lineWidth + 2);
+ // Find latest time.
+ double latestTime = 0;
+ for (DatasetList::iterator ditr = _datasets.begin(),
+ de = _datasets.end();
+ ditr != de;
+ ++ditr)
+ {
+ if (!(*ditr)->times.empty())
+ {
+ double lastDataTime = (*ditr)->times.back();
+ if (lastDataTime > latestTime)
+ latestTime = lastDataTime;
+ }
+ }
+ double minDiff = 0.0;
+ double maxTotal = 0.0;
+ for (DatasetList::iterator ditr = _datasets.begin(),
+ de = _datasets.end();
+ ditr != de;
+ ++ditr)
+ {
+ GraphDataBase::TimeList& gtimes = (*ditr)->times;
+ if (gtimes.size() <= 1)
+ continue;
+ double totalDiff = 0.0;
+ for (GraphDataBase::TimeList::reverse_iterator ritr = gtimes.rbegin(),
+ re = gtimes.rend();
+ ritr + 1 != gtimes.rend();
+ ritr++)
+ {
+ double timeDiff = *ritr - *(ritr + 1);
+ if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0))
+ minDiff = timeDiff;
+ if (minDiff != 0
+ && (totalDiff + timeDiff) / minDiff > linesPossible)
+ break;
+ totalDiff += timeDiff;
+ }
+ if (totalDiff > maxTotal)
+ maxTotal = totalDiff;
+ }
+ // Now we have a global scale.
+ _right = latestTime;
+ if (maxTotal != 0)
+ _left = latestTime - maxTotal;
+ else
+ _left = _right - 1.0;
+ }
+ cr->save();
+ double horizScale = _zoomFactor * _graphWidth / ( _right - _left);
+ cr->translate(20.0, 0.0);
+ cr->set_line_width(_lineWidth);
+ cr->save();
+ cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
+ cr->paint();
+ cr->restore();
+
+ for (DatasetList::iterator itr = _datasets.begin(), e = _datasets.end();
+ itr != e;
+ ++itr)
+ {
+ shared_ptr<GraphDataBase> graphData = *itr;
+ shared_ptr<GraphData<double> > realData
+ = dynamic_pointer_cast<GraphData<double> >(*itr);
+ shared_ptr<GraphData<string> > stringData
+ = dynamic_pointer_cast<GraphData<string> >(*itr);
+ cr->save();
+ cr->translate(0.0, _graphHeight);
+ cr->scale(1.0, -1.0);
+ GraphDataBase::TimeList::iterator lower
+ = std::lower_bound(graphData->times.begin(), graphData->times.end(),
+ _left);
+ GraphDataBase::TimeList::iterator upper
+ = std::upper_bound(graphData->times.begin(), graphData->times.end(),
+ _right);
+ // event bar
+ if (graphData->style == GraphDataBase::EVENT)
+ {
+ double eventHeight = _graphHeight * (graphData->scale / 100.0);
+ cr->save();
+ cr->set_line_width(3 * _lineWidth);
+ cr->set_source_rgba(graphData->color[0], graphData->color[1],
+ graphData->color[2], .33);
+ cr->move_to(0, eventHeight);
+ cr->line_to(_graphWidth, eventHeight);
+ cr->stroke();
+ cr->restore();
+ }
+ for (GraphDataBase::TimeList::iterator ditr = lower, de = upper;
+ ditr != de;
+ ++ditr)
+ {
+ size_t dataIndex = ditr - graphData->times.begin();
+ cr->set_source_rgba(graphData->color[0], graphData->color[1],
+ graphData->color[2], 1.0);
+ if (graphData->style == GraphDataBase::BAR && realData)
+ {
+ cr->move_to((*ditr - _left) * horizScale, 0);
+ cr->line_to((*ditr - _left) * horizScale,
+ realData->data[dataIndex] * _graphHeight
+ / graphData->scale);
+ cr->stroke();
+ }
+ else if (graphData->style == GraphDataBase::DOT && realData)
+ {
+ cr->arc((*ditr - _left) * horizScale,
+ realData->data[dataIndex] * _graphHeight / graphData->scale,
+ _lineWidth / 2.0, 0.0, M_PI * 2.0);
+ cr->fill();
+ }
+ else if (graphData->style == GraphDataBase::EVENT && stringData)
+ {
+ double eventHeight = _graphHeight * (graphData->scale / 100.0);
+ cr->save();
+ cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL,
+ Cairo::FONT_WEIGHT_NORMAL);
+ cr->set_font_size(12.0);
+ cr->save();
+ cr->scale(1.0, -1.0);
+ cr->move_to((*ditr - _left) * horizScale,
+ -eventHeight -3.0 * _lineWidth - 2.0);
+ cr->show_text(stringData->data[dataIndex]);
+ cr->restore();
+ cr->rectangle((*ditr - _left) * horizScale - 1.5 * _lineWidth,
+ eventHeight - 1.5 * _lineWidth,
+ 3.0 * _lineWidth, 3.0 * _lineWidth);
+ cr->fill();
+ cr->restore();
+ }
+ }
+ cr->restore();
+ cr->save();
+ cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL,
+ Cairo::FONT_WEIGHT_BOLD);
+ cr->set_font_size(14.0);
+ cr->set_source_rgba(1.0, 1.0, 1.0, .8);
+
+ if (!graphData->title.empty())
+ {
+ cr->move_to(20.0, 20.0);
+ cr->show_text(graphData->title);
+ }
+ if (!graphData->xAxisText.empty())
+ {
+ cr->move_to(10.0, _graphHeight - 5);
+ cr->show_text(graphData->xAxisText);
+ }
+ if (!graphData->yAxisText.empty())
+ {
+ cr->save();
+ cr->translate(10.0, _height - 10.0);
+ cr->rotate(-M_PI / 2.0);
+ cr->move_to(10.0, 0.0);
+ cr->show_text(graphData->yAxisText);
+ cr->restore();
+ }
+ cr->restore();
+
+ }
+ cr->restore();
+ // Draw axes
+ double diff = _right - _left;
+ double majorUnit = pow(10.0, floor(log(diff) / log(10.0)));
+ double startTime = ceil(_left / majorUnit) * majorUnit;
+ cr->save();
+ cr->set_source_rgba(1.0, 1.0, 1.0, .9);
+ cr->set_line_cap(Cairo::LINE_CAP_BUTT);
+ cr->set_line_width(_lineWidth);
+ cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL,
+ Cairo::FONT_WEIGHT_NORMAL);
+ cr->set_font_size(10.0);
+ cr->move_to(20.0, 0.0);
+ cr->line_to(20.0, _height);
+ cr->move_to(20.0, _graphHeight);
+ cr->line_to(_graphWidth, _graphHeight);
+ cr->stroke();
+ std::valarray<double> dash(1);
+ dash[0] = _graphHeight / 10;
+ cr->set_dash(dash, 0);
+ double prevTextAdvance = 0;
+ for (double tickVal = startTime; tickVal <= _right; tickVal += majorUnit)
+ {
+ double x = (tickVal - _left) * horizScale + 20.0;
+ cr->move_to(x, 0.0);
+ cr->line_to(x, _graphHeight);
+ cr->move_to(x, _graphHeight - 5);
+ std::ostringstream stream;
+ stream << std::fixed << std::setprecision(0) << tickVal;
+ Cairo::TextExtents extents;
+ cr->get_text_extents(stream.str(), extents);
+ // Room for this label?
+ if (x + extents.x_bearing > prevTextAdvance)
+ {
+ cr->show_text(stream.str());
+ prevTextAdvance = x + extents.x_advance;
+ }
+ }
+ cr->stroke();
+ cr->restore();
+
+ if (!_autoScrolling)
+ {
+ _playButton->setVisible(true);
+ _playButton->setOrigin(_graphWidth / 2 - 25, .875 * _graphHeight - 50);
+ _playButton->draw(cr);
+ }
+
+ }
+
+ void Graph::addGraphData(std::tr1::shared_ptr<GraphDataBase> data)
+ {
+ _datasets.push_back(data);
+ }
+
+ void Graph::getExtents(double& left, double& right, double& top,
+ double& bottom) const
+ {
+ left = _left;
+ right = _right;
+ top = _top;
+ bottom = _bottom;
+ }
+
+ void Graph::setExtents(double left, double right, double top, double bottom)
+ {
+ _left = left;
+ _right = right;
+ _top = top;
+ _bottom = bottom;
+ }
+
+ bool Graph::containsPoint(double x, double y)
+ {
+ return x >= _x0 && x < _x0 + _width && y >= _y0 && y < _y0 + _height;
+ }
+}
diff --git a/grapher/Graph.hxx b/grapher/Graph.hxx
new file mode 100644
index 00000000..1cc1892d
--- /dev/null
+++ b/grapher/Graph.hxx
@@ -0,0 +1,48 @@
+#ifndef SYSTEMTAP_GRAPH_HXX
+#define SYSTEMTAP_GRAPH_HXX 1
+
+#include <cairomm/context.h>
+
+#include "GraphData.hxx"
+#include "CairoWidget.hxx"
+
+namespace systemtap
+{
+ class Graph : public CairoWidget
+ {
+ public:
+ friend class GraphWidget;
+ Graph();
+ virtual void draw(Cairo::RefPtr<Cairo::Context> cr);
+ virtual bool containsPoint(double x, double y);
+ double getLineWidth() { return _lineWidth; }
+ void setLineWidth(double lineWidth) { _lineWidth = lineWidth; }
+ bool getAutoScaling() const { return _autoScaling; }
+ void setAutoScaling(bool val) { _autoScaling = val; }
+ void addGraphData(std::tr1::shared_ptr<GraphDataBase> data);
+ void getExtents(double& left, double& right, double& top, double& bottom)
+ const;
+ void setExtents(double left, double right, double top, double bottom);
+ // extents of the whole graph area
+ double _width;
+ double _height;
+ // Position, extents of the graph
+ double _graphX;
+ double _graphY;
+ double _graphWidth;
+ double _graphHeight;
+ double _lineWidth;
+ bool _autoScaling;
+ bool _autoScrolling;
+ double _zoomFactor;
+ std::tr1::shared_ptr<CairoPlayButton> _playButton;
+ protected:
+ typedef std::vector<std::tr1::shared_ptr<GraphDataBase> > DatasetList;
+ DatasetList _datasets;
+ double _left;
+ double _right;
+ double _top;
+ double _bottom;
+ };
+}
+#endif
diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx
index 0f3b0b31..e4c08cfd 100644
--- a/grapher/GraphData.hxx
+++ b/grapher/GraphData.hxx
@@ -1,44 +1,49 @@
#ifndef SYSTEMTAP_GRAPHDATA_HXX
#define SYSTEMTAP_GRAPHDATA_HXX 1
+#include <string>
#include <utility>
#include <vector>
+#include <tr1/memory>
namespace systemtap
{
- struct GraphData
+ struct GraphDataBase
{
- public:
+ virtual ~GraphDataBase() {}
enum Style
{ BAR,
- DOT
+ DOT,
+ EVENT
};
- GraphData() : scale(1.0), style(BAR)
+ GraphDataBase() : scale(1.0), style(BAR)
{
color[0] = 0.0; color[1] = 1.0; color[2] = 0.0;
}
- typedef std::pair<double, double> Datum;
- typedef std::vector<Datum> List;
+ typedef std::vector<double> TimeList;
// size of grid square at "normal" viewing
double scale;
double color[3];
Style style;
- List data;
- struct Compare
- {
- bool operator() (const Datum& lhs, const Datum& rhs) const
- {
- return lhs.first < rhs.first;
- }
- bool operator() (double lhs, const Datum& rhs) const
- {
- return lhs < rhs.first;
- }
- bool operator() (const Datum& lhs, double rhs) const
- {
- return lhs.first < rhs;
- }
- };
+ std::string title;
+ std::string xAxisText;
+ std::string yAxisText;
+ TimeList times;
+ };
+
+ template<typename T>
+ class GraphData : public GraphDataBase
+ {
+ public:
+ typedef T data_type;
+ typedef std::vector<data_type> DataList;
+ DataList data;
+ };
+ struct CSVData
+ {
+ typedef std::pair<std::string, std::tr1::shared_ptr<GraphDataBase> >
+ Element;
+ std::vector<Element> elements;
};
}
#endif
diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx
index 38f8078d..5b0d1b1c 100644
--- a/grapher/GraphWidget.cxx
+++ b/grapher/GraphWidget.cxx
@@ -1,18 +1,18 @@
#include <algorithm>
#include <ctime>
#include <math.h>
-#include <sstream>
-#include <iomanip>
+
#include <cairomm/context.h>
#include "GraphWidget.hxx"
#include "CairoWidget.hxx"
namespace systemtap
{
+ using namespace std;
+ using namespace std::tr1;
+
GraphWidget::GraphWidget()
- : _left(0.0), _right(1.0), _top(1.0), _bottom(0.0), _lineWidth(10),
- _autoScaling(true), _autoScrolling(true), _zoomFactor(1.0),
- _trackingDrag(false), _playButton(new CairoPlayButton)
+ : _trackingDrag(false)
{
add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK
| Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK);
@@ -31,33 +31,20 @@ namespace systemtap
false);
signal_scroll_event()
.connect(sigc::mem_fun(*this, &GraphWidget::on_scroll_event), false);
+ // Temporary testing of multiple graphs
+ shared_ptr<Graph> graph(new Graph);
+ graph->_graphHeight = 180;
+ graph->_graphWidth = 580;
+ _graphs.push_back(graph);
}
- void GraphWidget::getExtents(double& left, double& right, double& top,
- double& bottom) const
- {
- left = _left;
- right = _right;
- top = _top;
- bottom = _bottom;
- }
-
- void GraphWidget::setExtents(double left, double right, double top,
- double bottom)
- {
- _left = left;
- _right = right;
- _top = top;
- _bottom = bottom;
-
- }
GraphWidget::~GraphWidget()
{
}
- void GraphWidget::addGraphData(std::tr1::shared_ptr<GraphData> data)
+ void GraphWidget::addGraphData(std::tr1::shared_ptr<GraphDataBase> data)
{
- _datasets.push_back(data);
+ _graphs[0]->addGraphData(data);
}
bool GraphWidget::on_expose_event(GdkEventExpose* event)
@@ -75,6 +62,7 @@ namespace systemtap
const int height = graphHeight - 20;
Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+#if 0
if(event && !_autoScaling)
{
// clip to the area indicated by the expose event so that we only
@@ -83,189 +71,51 @@ namespace systemtap
event->area.width, event->area.height);
cr->clip();
}
- if (_autoScaling)
- {
- // line separation
- int linesPossible = width / ((int)_lineWidth + 2);
- // Find latest time.
- double latestTime = 0;
- for (DatasetList::iterator ditr = _datasets.begin(),
- de = _datasets.end();
- ditr != de;
- ++ditr)
- {
- if (!(*ditr)->data.empty())
- {
- double lastDataTime = (*ditr)->data.back().first;
- if (lastDataTime > latestTime)
- latestTime = lastDataTime;
- }
- }
- double minDiff = 0.0;
- double maxTotal = 0.0;
- for (DatasetList::iterator ditr = _datasets.begin(),
- de = _datasets.end();
- ditr != de;
- ++ditr)
- {
- GraphData::List& gdata = (*ditr)->data;
- if (gdata.size() <= 1)
- continue;
- double totalDiff = 0.0;
- for (GraphData::List::reverse_iterator ritr = gdata.rbegin(),
- re = gdata.rend();
- ritr + 1 != gdata.rend();
- ritr++)
- {
- double timeDiff = ritr->first - (ritr + 1)->first;
- if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0))
- minDiff = timeDiff;
- if (minDiff != 0
- && (totalDiff + timeDiff) / minDiff > linesPossible)
- break;
- totalDiff += timeDiff;
- }
- if (totalDiff > maxTotal)
- maxTotal = totalDiff;
- }
- // Now we have a global scale.
- _right = latestTime;
- if (maxTotal != 0)
- _left = latestTime - maxTotal;
- else
- _left = _right - 1.0;
- }
- cr->save();
- double horizScale = _zoomFactor * width / ( _right - _left);
- cr->translate(20.0, 0.0);
- cr->set_line_width(_lineWidth);
+#endif
cr->save();
cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
cr->paint();
- cr->restore();
-
- for (DatasetList::iterator itr = _datasets.begin(), e = _datasets.end();
- itr != e;
- ++itr)
+ for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g)
{
cr->save();
- cr->translate(0.0, height);
- cr->scale(1.0, -1.0);
- GraphData::List::iterator lower
- = std::lower_bound((*itr)->data.begin(), (*itr)->data.end(), _left,
- GraphData::Compare());
- GraphData::List::iterator upper
- = std::upper_bound((*itr)->data.begin(), (*itr)->data.end(), _right,
- GraphData::Compare());
- for (GraphData::List::iterator ditr = lower, de = upper;
- ditr != de;
- ++ditr)
- {
- cr->set_source_rgba((*itr)->color[0], (*itr)->color[1],
- (*itr)->color[2], 1.0);
- if ((*itr)->style == GraphData::BAR)
- {
- cr->move_to((ditr->first - _left) * horizScale, 0);
- cr->line_to((ditr->first - _left) * horizScale,
- ditr->second * height / (*itr)->scale);
- cr->stroke();
- }
- else
- {
- cr->arc((ditr->first - _left) * horizScale,
- ditr->second * height / (*itr)->scale,
- _lineWidth / 2.0, 0.0, M_PI * 2.0);
- cr->fill();
- }
- }
+ cr->translate((*g)->_graphX, (*g)->_graphY);
+ (*g)->draw(cr);
cr->restore();
}
- cr->restore();
- cr->save();
- cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL,
- Cairo::FONT_WEIGHT_BOLD);
- cr->set_font_size(14.0);
- cr->set_source_rgba(1.0, 1.0, 1.0, .8);
-
- if (!_title.empty())
- {
- cr->move_to(20.0, 20.0);
- cr->show_text(_title);
- }
- if (!_xAxisText.empty())
- {
- cr->move_to(10.0, graphHeight - 5);
- cr->show_text(_xAxisText);
- }
- if (!_yAxisText.empty())
- {
- cr->save();
- cr->translate(10.0, height - 10.0);
- cr->rotate(-M_PI / 2.0);
- cr->move_to(10.0, 0.0);
- cr->show_text(_yAxisText);
- cr->restore();
- }
- cr->restore();
- // Draw axes
- double diff = _right - _left;
- double majorUnit = pow(10.0, floor(log(diff) / log(10.0)));
- double startTime = floor(_left / majorUnit) * majorUnit;
- cr->save();
- cr->set_source_rgba(1.0, 1.0, 1.0, .9);
- cr->set_line_cap(Cairo::LINE_CAP_BUTT);
- cr->set_line_width(_lineWidth);
- cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL,
- Cairo::FONT_WEIGHT_NORMAL);
- cr->set_font_size(10.0);
- cr->move_to(20.0, 0.0);
- cr->line_to(20.0, height);
- cr->move_to(20.0, height);
- cr->line_to(graphWidth, height);
- cr->stroke();
- std::valarray<double> dash(1);
- dash[0] = height / 10;
- cr->set_dash(dash, 0.0);
- for (double tickVal = startTime; tickVal < _right; tickVal += majorUnit)
- {
- cr->move_to((tickVal - _left) * horizScale + 20.0, graphHeight - 5);
- std::ostringstream stream;
- stream << std::fixed << std::setprecision(0) << tickVal;
- cr->show_text(stream.str());
- cr->move_to((tickVal - _left) * horizScale + 20.0, 0.0);
- cr->line_to((tickVal - _left) * horizScale + 20.0, height);
- cr->stroke();
- }
- cr->stroke();
- cr->restore();
-
- if (!_autoScrolling)
- {
- _playButton->setVisible(true);
- _playButton->setOrigin(width / 2 - 25, .875 * height - 50);
- _playButton->draw(cr);
- }
-
return true;
}
bool GraphWidget::on_button_press_event(GdkEventButton* event)
{
- if (!_autoScrolling && _playButton->containsPoint(event->x, event->y))
+ for (GraphList::iterator g = _graphs.begin(); g != _graphs.end(); ++g)
+ {
+ if (event->x >= (*g)->_graphX
+ && event->x < (*g)->_graphX + (*g)->_graphWidth
+ && event->y >= (*g)->_graphY
+ && event->y < (*g)->_graphY + (*g)->_graphHeight)
+ {
+ _activeGraph = *g;
+ break;
+ }
+ }
+ if (!_activeGraph)
+ return true;
+ if (!_activeGraph->_autoScrolling
+ && _activeGraph->_playButton->containsPoint(event->x, event->y))
{
- _autoScaling = true;
- _autoScrolling = true;
+ _activeGraph->_autoScaling = true;
+ _activeGraph->_autoScrolling = true;
queue_draw();
}
else
{
_trackingDrag = true;
- _autoScaling = false;
- _autoScrolling = false;
+ _activeGraph->_autoScaling = false;
+ _activeGraph->_autoScrolling = false;
_dragOriginX = event->x;
_dragOriginY = event->y;
- _dragOrigLeft = _left;
- _dragOrigRight = _right;
+ _dragOrigLeft = _activeGraph->_left;
+ _dragOrigRight = _activeGraph->_right;
}
return true;
}
@@ -292,14 +142,14 @@ namespace systemtap
x = event->x;
y = event->y;
}
- if (_trackingDrag)
+ if (_trackingDrag && _activeGraph)
{
Gtk::Allocation allocation = get_allocation();
const int width = allocation.get_width();
double motion = (x - _dragOriginX) / (double) width;
double increment = motion * (_dragOrigLeft - _dragOrigRight);
- _left = _dragOrigLeft + increment;
- _right = _dragOrigRight + increment;
+ _activeGraph->_left = _dragOrigLeft + increment;
+ _activeGraph->_right = _dragOrigRight + increment;
queue_draw();
}
return true;
@@ -307,11 +157,20 @@ namespace systemtap
bool GraphWidget::on_scroll_event(GdkEventScroll* event)
{
- if (event->direction == GDK_SCROLL_UP)
- _zoomFactor += .1;
- else if (event->direction == GDK_SCROLL_DOWN)
- _zoomFactor -= .1;
- queue_draw();
+ for (GraphList::iterator gitr = _graphs.begin();
+ gitr != _graphs.end();
+ ++gitr)
+ {
+ if ((*gitr)->containsPoint(event->x, event->y))
+ {
+ if (event->direction == GDK_SCROLL_UP)
+ (*gitr)->_zoomFactor += .1;
+ else if (event->direction == GDK_SCROLL_DOWN)
+ (*gitr)->_zoomFactor -= .1;
+ queue_draw();
+ break;
+ }
+ }
return true;
}
diff --git a/grapher/GraphWidget.hxx b/grapher/GraphWidget.hxx
index 46075b78..c15f8fcd 100644
--- a/grapher/GraphWidget.hxx
+++ b/grapher/GraphWidget.hxx
@@ -6,7 +6,7 @@
#include <tr1/memory>
#include <gtkmm/drawingarea.h>
-#include "GraphData.hxx"
+#include <Graph.hxx>
namespace systemtap
{
@@ -17,20 +17,16 @@ namespace systemtap
public:
GraphWidget();
virtual ~GraphWidget();
- void addGraphData(std::tr1::shared_ptr<GraphData> data);
- void getExtents(double& left, double& right, double& top, double& bottom) const;
- void setExtents(double left, double right, double top, double bottom);
- double getLineWidth() { return _lineWidth; }
- void setLineWidth(double lineWidth) { _lineWidth = lineWidth; }
- bool getAutoScaling() const { return _autoScaling; }
- void setAutoScaling(bool val) { _autoScaling = val; }
- std::string getTitle() const { return _title; }
- void setTitle(const std::string& title) { _title = title; }
- std::string getXAxisText() const { return _xAxisText; }
- void setXAxisText(const std::string& text) { _xAxisText = text; }
- std::string getYAxisText() const { return _yAxisText; }
- void setYAxisText(const std::string& text) { _yAxisText = text; }
+ void addGraphData(std::tr1::shared_ptr<GraphDataBase> data);
+
protected:
+ typedef std::vector<std::tr1::shared_ptr<Graph> > GraphList;
+ GraphList _graphs;
+ // For click and drag
+ std::tr1::shared_ptr<Graph> _activeGraph;
+ // Dragging all graphs simultaneously, or perhaps seperately
+ typedef std::vector<std::pair<double, double> > DragList;
+ DragList dragCoords;
//Override default signal handler:
virtual bool on_expose_event(GdkEventExpose* event);
virtual bool on_motion_notify_event(GdkEventMotion* event);
@@ -38,25 +34,11 @@ namespace systemtap
virtual bool on_button_release_event(GdkEventButton* event);
virtual bool on_scroll_event(GdkEventScroll* event);
bool on_timeout();
- typedef std::vector<std::tr1::shared_ptr<GraphData> > DatasetList;
- DatasetList _datasets;
- double _left;
- double _right;
- double _top;
- double _bottom;
- double _lineWidth;
- bool _autoScaling;
- bool _autoScrolling;
- double _zoomFactor;
bool _trackingDrag;
double _dragOriginX;
double _dragOriginY;
double _dragOrigLeft;
double _dragOrigRight;
- std::string _title;
- std::string _xAxisText;
- std::string _yAxisText;
- std::tr1::shared_ptr<CairoPlayButton> _playButton;
};
}
#endif // SYSTEMTAP_GRAPHWIDGET_H
diff --git a/grapher/Makefile.am b/grapher/Makefile.am
index fdb52ef7..0f61d77b 100644
--- a/grapher/Makefile.am
+++ b/grapher/Makefile.am
@@ -2,6 +2,6 @@ if BUILD_GRAPHER
bin_PROGRAMS = grapher
grapher_CXXFLAGS = $(GRAPHER_CFLAGS)
-grapher_SOURCES = grapher.cxx GraphWidget.cxx CairoWidget.cxx
+grapher_SOURCES = grapher.cxx StapParser.cxx Graph.cxx GraphWidget.cxx CairoWidget.cxx
grapher_LDADD = $(GRAPHER_LIBS)
endif \ No newline at end of file
diff --git a/grapher/Makefile.in b/grapher/Makefile.in
index 88caeda1..227359be 100644
--- a/grapher/Makefile.in
+++ b/grapher/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -16,8 +17,9 @@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -40,11 +42,14 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
-binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
-am__grapher_SOURCES_DIST = grapher.cxx GraphWidget.cxx CairoWidget.cxx
+am__grapher_SOURCES_DIST = grapher.cxx StapParser.cxx Graph.cxx \
+ GraphWidget.cxx CairoWidget.cxx
@BUILD_GRAPHER_TRUE@am_grapher_OBJECTS = grapher-grapher.$(OBJEXT) \
+@BUILD_GRAPHER_TRUE@ grapher-StapParser.$(OBJEXT) \
+@BUILD_GRAPHER_TRUE@ grapher-Graph.$(OBJEXT) \
@BUILD_GRAPHER_TRUE@ grapher-GraphWidget.$(OBJEXT) \
@BUILD_GRAPHER_TRUE@ grapher-CairoWidget.$(OBJEXT)
grapher_OBJECTS = $(am_grapher_OBJECTS)
@@ -55,6 +60,7 @@ grapher_LINK = $(CXXLD) $(grapher_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
+am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
@@ -184,7 +190,7 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@BUILD_GRAPHER_TRUE@grapher_CXXFLAGS = $(GRAPHER_CFLAGS)
-@BUILD_GRAPHER_TRUE@grapher_SOURCES = grapher.cxx GraphWidget.cxx CairoWidget.cxx
+@BUILD_GRAPHER_TRUE@grapher_SOURCES = grapher.cxx StapParser.cxx Graph.cxx GraphWidget.cxx CairoWidget.cxx
@BUILD_GRAPHER_TRUE@grapher_LDADD = $(GRAPHER_LIBS)
all: all-am
@@ -199,9 +205,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu grapher/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu grapher/Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu grapher/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu grapher/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -219,26 +225,41 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
- $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
- else :; fi; \
- done
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
- rm -f "$(DESTDIR)$(bindir)/$$f"; \
- done
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
@@ -253,61 +274,91 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-CairoWidget.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-Graph.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-GraphWidget.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-StapParser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grapher-grapher.Po@am__quote@
.cxx.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
.cxx.obj:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
grapher-grapher.o: grapher.cxx
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-grapher.o -MD -MP -MF $(DEPDIR)/grapher-grapher.Tpo -c -o grapher-grapher.o `test -f 'grapher.cxx' || echo '$(srcdir)/'`grapher.cxx
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='grapher.cxx' object='grapher-grapher.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-grapher.o `test -f 'grapher.cxx' || echo '$(srcdir)/'`grapher.cxx
grapher-grapher.obj: grapher.cxx
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-grapher.obj -MD -MP -MF $(DEPDIR)/grapher-grapher.Tpo -c -o grapher-grapher.obj `if test -f 'grapher.cxx'; then $(CYGPATH_W) 'grapher.cxx'; else $(CYGPATH_W) '$(srcdir)/grapher.cxx'; fi`
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-grapher.Tpo $(DEPDIR)/grapher-grapher.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='grapher.cxx' object='grapher-grapher.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-grapher.obj `if test -f 'grapher.cxx'; then $(CYGPATH_W) 'grapher.cxx'; else $(CYGPATH_W) '$(srcdir)/grapher.cxx'; fi`
+grapher-StapParser.o: StapParser.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-StapParser.o -MD -MP -MF $(DEPDIR)/grapher-StapParser.Tpo -c -o grapher-StapParser.o `test -f 'StapParser.cxx' || echo '$(srcdir)/'`StapParser.cxx
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='StapParser.cxx' object='grapher-StapParser.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-StapParser.o `test -f 'StapParser.cxx' || echo '$(srcdir)/'`StapParser.cxx
+
+grapher-StapParser.obj: StapParser.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-StapParser.obj -MD -MP -MF $(DEPDIR)/grapher-StapParser.Tpo -c -o grapher-StapParser.obj `if test -f 'StapParser.cxx'; then $(CYGPATH_W) 'StapParser.cxx'; else $(CYGPATH_W) '$(srcdir)/StapParser.cxx'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-StapParser.Tpo $(DEPDIR)/grapher-StapParser.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='StapParser.cxx' object='grapher-StapParser.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-StapParser.obj `if test -f 'StapParser.cxx'; then $(CYGPATH_W) 'StapParser.cxx'; else $(CYGPATH_W) '$(srcdir)/StapParser.cxx'; fi`
+
+grapher-Graph.o: Graph.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-Graph.o -MD -MP -MF $(DEPDIR)/grapher-Graph.Tpo -c -o grapher-Graph.o `test -f 'Graph.cxx' || echo '$(srcdir)/'`Graph.cxx
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-Graph.Tpo $(DEPDIR)/grapher-Graph.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Graph.cxx' object='grapher-Graph.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-Graph.o `test -f 'Graph.cxx' || echo '$(srcdir)/'`Graph.cxx
+
+grapher-Graph.obj: Graph.cxx
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-Graph.obj -MD -MP -MF $(DEPDIR)/grapher-Graph.Tpo -c -o grapher-Graph.obj `if test -f 'Graph.cxx'; then $(CYGPATH_W) 'Graph.cxx'; else $(CYGPATH_W) '$(srcdir)/Graph.cxx'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-Graph.Tpo $(DEPDIR)/grapher-Graph.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Graph.cxx' object='grapher-Graph.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-Graph.obj `if test -f 'Graph.cxx'; then $(CYGPATH_W) 'Graph.cxx'; else $(CYGPATH_W) '$(srcdir)/Graph.cxx'; fi`
+
grapher-GraphWidget.o: GraphWidget.cxx
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-GraphWidget.o -MD -MP -MF $(DEPDIR)/grapher-GraphWidget.Tpo -c -o grapher-GraphWidget.o `test -f 'GraphWidget.cxx' || echo '$(srcdir)/'`GraphWidget.cxx
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='GraphWidget.cxx' object='grapher-GraphWidget.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-GraphWidget.o `test -f 'GraphWidget.cxx' || echo '$(srcdir)/'`GraphWidget.cxx
grapher-GraphWidget.obj: GraphWidget.cxx
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-GraphWidget.obj -MD -MP -MF $(DEPDIR)/grapher-GraphWidget.Tpo -c -o grapher-GraphWidget.obj `if test -f 'GraphWidget.cxx'; then $(CYGPATH_W) 'GraphWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/GraphWidget.cxx'; fi`
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-GraphWidget.Tpo $(DEPDIR)/grapher-GraphWidget.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='GraphWidget.cxx' object='grapher-GraphWidget.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-GraphWidget.obj `if test -f 'GraphWidget.cxx'; then $(CYGPATH_W) 'GraphWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/GraphWidget.cxx'; fi`
grapher-CairoWidget.o: CairoWidget.cxx
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-CairoWidget.o -MD -MP -MF $(DEPDIR)/grapher-CairoWidget.Tpo -c -o grapher-CairoWidget.o `test -f 'CairoWidget.cxx' || echo '$(srcdir)/'`CairoWidget.cxx
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='CairoWidget.cxx' object='grapher-CairoWidget.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-CairoWidget.o `test -f 'CairoWidget.cxx' || echo '$(srcdir)/'`CairoWidget.cxx
grapher-CairoWidget.obj: CairoWidget.cxx
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -MT grapher-CairoWidget.obj -MD -MP -MF $(DEPDIR)/grapher-CairoWidget.Tpo -c -o grapher-CairoWidget.obj `if test -f 'CairoWidget.cxx'; then $(CYGPATH_W) 'CairoWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/CairoWidget.cxx'; fi`
-@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/grapher-CairoWidget.Tpo $(DEPDIR)/grapher-CairoWidget.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='CairoWidget.cxx' object='grapher-CairoWidget.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(grapher_CXXFLAGS) $(CXXFLAGS) -c -o grapher-CairoWidget.obj `if test -f 'CairoWidget.cxx'; then $(CYGPATH_W) 'CairoWidget.cxx'; else $(CYGPATH_W) '$(srcdir)/CairoWidget.cxx'; fi`
@@ -324,7 +375,7 @@ tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
+ set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -332,29 +383,34 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
+ $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -375,13 +431,17 @@ distdir: $(DISTFILES)
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@@ -412,6 +472,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -432,6 +493,8 @@ dvi-am:
html: html-am
+html-am:
+
info: info-am
info-am:
@@ -440,18 +503,28 @@ install-data-am:
install-dvi: install-dvi-am
+install-dvi-am:
+
install-exec-am: install-binPROGRAMS
install-html: install-html-am
+install-html-am:
+
install-info: install-info-am
+install-info-am:
+
install-man:
install-pdf: install-pdf-am
+install-pdf-am:
+
install-ps: install-ps-am
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-am
@@ -488,6 +561,7 @@ uninstall-am: uninstall-binPROGRAMS
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-binPROGRAMS
+
# 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/grapher/StapParser.cxx b/grapher/StapParser.cxx
new file mode 100644
index 00000000..1c865614
--- /dev/null
+++ b/grapher/StapParser.cxx
@@ -0,0 +1,204 @@
+#include "StapParser.hxx"
+
+#include <gtkmm/window.h>
+#include <iostream>
+
+namespace systemtap
+{
+ using namespace std;
+ using namespace std::tr1;
+
+vector<string> commaSplit(const string& inStr, size_t pos = 0)
+{
+ size_t found = pos;
+ vector<string> result;
+ while (1)
+ {
+
+ size_t commaPos = inStr.find(',', found);
+ string token
+ = inStr.substr(found, (commaPos == string::npos
+ ? string::npos
+ : commaPos - 1 - found));
+ result.push_back(token);
+ if (commaPos != string::npos)
+ found = commaPos + 1;
+ else
+ break;
+ }
+ return result;
+}
+
+ void StapParser::parseData(shared_ptr<GraphDataBase> gdata,
+ double time, const string& dataString)
+ {
+ std::istringstream stream(dataString);
+ shared_ptr<GraphData<double> > dblptr;
+ shared_ptr<GraphData<string> > strptr;
+ dblptr = dynamic_pointer_cast<GraphData<double> >(gdata);
+ if (dblptr)
+ {
+ double data;
+ stream >> data;
+ dblptr->times.push_back(time);
+ dblptr->data.push_back(data);
+ }
+ else if ((strptr = std::tr1
+ ::dynamic_pointer_cast<GraphData<string> >(gdata))
+ != 0)
+ {
+ strptr->times.push_back(time);
+ strptr->data.push_back(dataString);
+ }
+ }
+
+ size_t findTaggedValue(const string& src, const char* tag, string& result)
+ {
+ size_t found;
+ if ((found = src.find(tag)) != string::npos)
+ result = src.substr(strlen(tag));
+ return found;
+ }
+
+ bool StapParser::ioCallback(Glib::IOCondition ioCondition)
+ {
+ using namespace std;
+ if ((ioCondition & Glib::IO_IN) == 0)
+ return true;
+ char buf[256];
+ ssize_t bytes_read = 0;
+ bytes_read = read(0, buf, sizeof(buf) - 1);
+ if (bytes_read <= 0)
+ {
+ _win.hide();
+ return true;
+ }
+ buf[bytes_read] = '\0';
+ _buffer += buf;
+ string::size_type ret = string::npos;
+ while ((ret = _buffer.find('\n')) != string::npos)
+ {
+ Glib::ustring dataString(_buffer, 0, ret);
+ // %DataSet and %CSV declare a data set; all other statements begin with
+ // the name of a data set.
+ size_t found;
+ if (dataString[0] == '%')
+ {
+ if ((found = dataString.find("%DataSet:") == 0))
+ {
+ std::string setName;
+ int hexColor;
+ double scale;
+ std::string style;
+ std::istringstream stream(dataString.substr(9));
+ stream >> setName >> scale >> std::hex >> hexColor
+ >> style;
+ if (style == "bar" || style == "dot")
+ {
+ shared_ptr<GraphData<double> >
+ dataSet(new GraphData<double>);
+ if (style == "dot")
+ dataSet->style = GraphDataBase::DOT;
+ dataSet->color[0] = (hexColor >> 16) / 255.0;
+ dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
+ dataSet->color[2] = (hexColor & 0xff) / 255.0;
+ dataSet->scale = scale;
+ _dataSets.insert(std::make_pair(setName, dataSet));
+ _widget.addGraphData(dataSet);
+ }
+ else if (style == "discreet")
+ {
+ shared_ptr<GraphData<string> >
+ dataSet(new GraphData<string>);
+ dataSet->style = GraphDataBase::EVENT;
+ dataSet->color[0] = (hexColor >> 16) / 255.0;
+ dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
+ dataSet->color[2] = (hexColor & 0xff) / 255.0;
+ dataSet->scale = scale;
+ _dataSets.insert(std::make_pair(setName, dataSet));
+ _widget.addGraphData(dataSet);
+ }
+ }
+ else if ((found = dataString.find("%CSV:") == 0))
+ {
+ vector<string> tokens = commaSplit(dataString, found + 5);
+ for (vector<string>::iterator tokIter = tokens.begin(),
+ e = tokens.end();
+ tokIter != e;
+ ++tokIter)
+ {
+ DataMap::iterator setIter = _dataSets.find(*tokIter);
+ if (setIter != _dataSets.end())
+ _csv.elements
+ .push_back(CSVData::Element(*tokIter,
+ setIter->second));
+ }
+ }
+ else
+ {
+ cerr << "Unknown declaration " << dataString << endl;
+ }
+ }
+ else
+ {
+ std::istringstream stream(dataString);
+ string setName;
+ stream >> setName;
+ DataMap::iterator itr = _dataSets.find(setName);
+ if (itr != _dataSets.end())
+ {
+ shared_ptr<GraphDataBase> gdata = itr->second;
+ string decl;
+ // Hack: scan from the beginning of dataString again
+ if (findTaggedValue(dataString, "%Title", decl)
+ != string::npos)
+ {
+ gdata->title = decl;
+ }
+ else if (findTaggedValue(dataString, "%XAxisTitle:", decl)
+ != string::npos)
+ {
+ gdata->xAxisText = decl;
+ }
+ else if (findTaggedValue(dataString, "%YAxisTitle:", decl)
+ != string::npos)
+ {
+ gdata->yAxisText = decl;
+ }
+ else if ((found = dataString.find("%YMax:")) != string::npos)
+ {
+ double ymax;
+ std::istringstream stream(dataString.substr(found));
+ stream >> ymax;
+ gdata->scale = ymax;
+ }
+
+ if (!_csv.elements.empty())
+ {
+ vector<string> tokens = commaSplit(dataString);
+ int i = 0;
+ double time;
+ vector<string>::iterator tokIter = tokens.begin();
+ std::istringstream timeStream(*tokIter++);
+ timeStream >> time;
+ for (vector<string>::iterator e = tokens.end();
+ tokIter != e;
+ ++tokIter, ++i)
+ {
+ parseData(_csv.elements[i].second, time, *tokIter);
+ }
+ }
+ else
+ {
+ double time;
+ string data;
+ stream >> time >> data;
+ parseData(itr->second, time, data);
+ }
+ }
+ }
+ _buffer.erase(0, ret + 1);
+ }
+ return true;
+ }
+}
diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx
new file mode 100644
index 00000000..e11e7302
--- /dev/null
+++ b/grapher/StapParser.hxx
@@ -0,0 +1,23 @@
+#include "GraphData.hxx"
+#include "GraphWidget.hxx"
+
+#include <string>
+namespace systemtap
+{
+class StapParser
+{
+ std::string _buffer;
+ typedef std::map<std::string, std::tr1::shared_ptr<GraphDataBase> > DataMap;
+ DataMap _dataSets;
+ CSVData _csv;
+ Gtk::Window& _win;
+ GraphWidget& _widget;
+public:
+ StapParser(Gtk::Window& win,
+ GraphWidget& widget) : _win(win), _widget(widget) {}
+ void parseData(std::tr1::shared_ptr<GraphDataBase> gdata,
+ double time, const std::string& dataString);
+ bool ioCallback(Glib::IOCondition ioCondition);
+
+};
+}
diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx
index 46182178..a0d35017 100644
--- a/grapher/grapher.cxx
+++ b/grapher/grapher.cxx
@@ -1,127 +1,135 @@
#include "GraphWidget.hxx"
+#include "StapParser.hxx"
+#include <cerrno>
#include <cmath>
+#include <cstdio>
+#include <iostream>
#include <sstream>
#include <string>
#include <map>
+#include <gtkmm.h>
+#include <gtkmm/stock.h>
#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <unistd.h>
#include <poll.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
using namespace systemtap;
-class StapParser
+class GrapherWindow : public Gtk::Window
{
- Glib::ustring _buffer;
- typedef std::map<std::string, std::tr1::shared_ptr<GraphData> > DataMap;
- DataMap _dataSets;
- Gtk::Window& _win;
- GraphWidget& _widget;
public:
- StapParser(Gtk::Window& win,
- GraphWidget& widget) : _win(win), _widget(widget) {}
-
- bool ioCallback(Glib::IOCondition ioCondition)
- {
- if ((ioCondition & Glib::IO_IN) == 0)
- return true;
- char buf[256];
- ssize_t bytes_read = 0;
- bytes_read = read(0, buf, sizeof(buf) - 1);
- if (bytes_read <= 0)
- {
- _win.hide();
- return true;
- }
- buf[bytes_read] = '\0';
- _buffer += buf;
- Glib::ustring::size_type ret = Glib::ustring::npos;
- while ((ret = _buffer.find('\n')) != Glib::ustring::npos)
- {
- Glib::ustring dataString(_buffer, 0, ret);
- if (dataString[0] == '%')
- {
- size_t found;
- if ((found = dataString.find("%Title:") == 0))
- {
- std::string title = dataString.substr(7);
- _widget.setTitle(title);
- }
- else if ((found = dataString.find("%XAxisTitle:") == 0))
- {
- _widget.setXAxisText(dataString.substr(12));
- }
- else if ((found = dataString.find("%YAxisTitle:") == 0))
- {
- _widget.setYAxisText(dataString.substr(12));
- }
- else if ((found = dataString.find("%YMax:") == 0))
- {
- double ymax;
- std::istringstream stream(dataString.substr(6));
- stream >> ymax;
- // _gdata->scale = ymax;
- }
- else if ((found = dataString.find("%DataSet:") == 0))
- {
- std::tr1::shared_ptr<GraphData> dataSet(new GraphData);
- std::string setName;
- int hexColor;
- std::string style;
- std::istringstream stream(dataString.substr(9));
- stream >> setName >> dataSet->scale >> std::hex >> hexColor
- >> style;
- dataSet->color[0] = (hexColor >> 16) / 255.0;
- dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
- dataSet->color[2] = (hexColor & 0xff) / 255.0;
- if (style == "dot")
- dataSet->style = GraphData::DOT;
- _dataSets.insert(std::make_pair(setName, dataSet));
- _widget.addGraphData(dataSet);
- }
- }
- else
- {
- std::string dataSet;
- double time;
- double data;
- std::istringstream stream(dataString);
- stream >> dataSet >> time >> data;
- DataMap::iterator itr = _dataSets.find(dataSet);
- if (itr != _dataSets.end())
- itr->second->data.push_back(std::make_pair(time, data));
- }
- _buffer.erase(0, ret + 1);
- }
- return true;
- }
+ GrapherWindow();
+ virtual ~GrapherWindow() {}
+ Gtk::VBox m_Box;
+ GraphWidget w;
+protected:
+ virtual void on_menu_file_quit();
+ // menu support
+ Glib::RefPtr<Gtk::UIManager> m_refUIManager;
+ Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup;
+
};
+GrapherWindow::GrapherWindow()
+{
+ set_title("systemtap grapher");
+ add(m_Box);
+
+
+ //Create actions for menus and toolbars:
+ m_refActionGroup = Gtk::ActionGroup::create();
+ //File menu:
+ m_refActionGroup->add(Gtk::Action::create("FileMenu", "File"));
+ m_refActionGroup->add(Gtk::Action::create("FileQuit", Gtk::Stock::QUIT),
+ sigc::mem_fun(*this, &GrapherWindow::on_menu_file_quit));
+ m_refUIManager = Gtk::UIManager::create();
+ m_refUIManager->insert_action_group(m_refActionGroup);
+
+ add_accel_group(m_refUIManager->get_accel_group());
+ //Layout the actions in a menubar and toolbar:
+ Glib::ustring ui_info =
+ "<ui>"
+ " <menubar name='MenuBar'>"
+ " <menu action='FileMenu'>"
+ " <menuitem action='FileQuit'/>"
+ " </menu>"
+ " </menubar>"
+ "</ui>";
+ try
+ {
+ m_refUIManager->add_ui_from_string(ui_info);
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << "building menus failed: " << ex.what();
+ }
+ Gtk::Widget* pMenubar = m_refUIManager->get_widget("/MenuBar");
+ if(pMenubar)
+ m_Box.pack_start(*pMenubar, Gtk::PACK_SHRINK);
+ m_Box.pack_start(w, Gtk::PACK_EXPAND_WIDGET);
+ w.show();
+
+ show_all_children();
+
+}
+void GrapherWindow::on_menu_file_quit()
+{
+ hide();
+}
+
int main(int argc, char** argv)
{
- Gtk::Main app(argc, argv);
+ Gtk::Main app(argc, argv);
- Gtk::Window win;
+ GrapherWindow win;
- win.set_title("Grapher");
- win.set_default_size(600, 200);
+ win.set_title("Grapher");
+ win.set_default_size(600, 200);
- GraphWidget w;
-
- w.setExtents(0.0, 1.0, 5.0, 0.0);
- w.setLineWidth(2);
+ StapParser stapParser(win, win.w);
- StapParser stapParser(win, w);
+ int childPid = -1;
+ if (argc > 1)
+ {
+ int pipefd[2];
+ if (pipe(pipefd) < 0)
+ {
+ std::perror("pipe");
+ exit(1);
+ }
+ if ((childPid = fork()) == -1)
+ {
+ exit(1);
+ }
+ else if (childPid)
+ {
+ dup2(pipefd[0], 0);
+ close(pipefd[0]);
+ }
+ else
+ {
+ dup2(pipefd[1], 1);
+ close(pipefd[1]);
+ execlp("stap", "stap", argv[1], static_cast<char*>(0));
+ exit(1);
+ return 1;
+ }
+ }
Glib::signal_io().connect(sigc::mem_fun(stapParser,
&StapParser::ioCallback),
0,
Glib::IO_IN);
- win.add(w);
- w.show();
-
Gtk::Main::run(win);
-
+ if (childPid > 0)
+ kill(childPid, SIGTERM);
+ int status;
+ while (wait(&status) != -1)
+ ;
return 0;
}
diff --git a/loc2c.c b/loc2c.c
index f5efccfe..26ca3ba1 100644
--- a/loc2c.c
+++ b/loc2c.c
@@ -1749,6 +1749,19 @@ array_stride (Dwarf_Die *typedie, struct location *origin)
dwarf_diename (typedie) ?: "<anonymous>",
dwarf_errmsg (-1));
+ int typetag = dwarf_tag(&die_mem);
+ while (typetag == DW_TAG_typedef ||
+ typetag == DW_TAG_const_type ||
+ typetag == DW_TAG_volatile_type)
+ {
+ if (dwarf_attr_integrate (&die_mem, DW_AT_type, &attr_mem) == NULL
+ || dwarf_formref_die (&attr_mem, &die_mem) == NULL)
+ FAIL (origin, N_("cannot get inner type of type %s: %s"),
+ dwarf_diename (&die_mem) ?: "<anonymous>",
+ dwarf_errmsg (-1));
+ typetag = dwarf_tag(&die_mem);
+ }
+
if (dwarf_attr_integrate (&die_mem, DW_AT_byte_size, &attr_mem) != NULL)
{
Dwarf_Word stride;
diff --git a/main.cxx b/main.cxx
index 4530075e..daf64561 100644
--- a/main.cxx
+++ b/main.cxx
@@ -21,6 +21,7 @@
#include "coveragedb.h"
#include "git_version.h"
#include "rpm_finder.h"
+#include "sys/sdt.h"
#include <iostream>
#include <fstream>
@@ -196,16 +197,17 @@ printscript(systemtap_session& s, ostream& o)
{
o << pp;
// Print the locals for -L mode only
- if (s.unoptimized) {
- for (unsigned j=0; j<p->locals.size(); j++)
- {
- o << " ";
- vardecl* v = p->locals[j];
- v->printsig (o);
- }
- // Print arguments of probe if there
- p->printargs(o);
- }
+ if (s.listing_mode_vars)
+ {
+ for (unsigned j=0; j<p->locals.size(); j++)
+ {
+ o << " ";
+ vardecl* v = p->locals[j];
+ v->printsig (o);
+ }
+ // Print arguments of probe if there
+ p->printargs(o);
+ }
o << endl;
seen.insert (pp);
}
@@ -464,6 +466,7 @@ main (int argc, char * const argv [])
s.unoptimized = false;
s.suppress_warnings = false;
s.listing_mode = false;
+ s.listing_mode_vars = false;
#ifdef ENABLE_PROLOGUES
s.prologue_searching = true;
@@ -763,6 +766,7 @@ main (int argc, char * const argv [])
break;
case 'L':
+ s.listing_mode_vars = true;
s.unoptimized = true; // This causes retention of variables for listing_mode
case 'l':
@@ -890,6 +894,8 @@ main (int argc, char * const argv [])
// PASS 0: setting up
s.verbose = s.perpass_verbose[0];
+ STAP_PROBE1(stap, pass0__start, &s);
+
// For PR1477, we used to override $PATH and $LC_ALL and other stuff
// here. We seem to use complete pathnames in
@@ -941,12 +947,15 @@ main (int argc, char * const argv [])
// and reasonably timely exit.
setup_signals(&handle_interrupt);
+ STAP_PROBE1(stap, pass0__end, &s);
+
struct tms tms_before;
times (& tms_before);
struct timeval tv_before;
gettimeofday (&tv_before, NULL);
// PASS 1a: PARSING USER SCRIPT
+ STAP_PROBE1(stap, pass1a__start, &s);
struct stat user_file_stat;
int user_file_stat_rc = -1;
@@ -998,6 +1007,8 @@ main (int argc, char * const argv [])
version_suffixes.push_back ("");
// PASS 1b: PARSING LIBRARY SCRIPTS
+ STAP_PROBE1(stap, pass1b__start, &s);
+
for (unsigned i=0; i<s.include_path.size(); i++)
{
// now iterate upon it
@@ -1085,6 +1096,8 @@ main (int argc, char * const argv [])
<< "Try again with another '--vp 1' option."
<< endl;
+ STAP_PROBE1(stap, pass1__end, &s);
+
if (rc || s.last_pass == 1 || pending_interrupts) goto cleanup;
times (& tms_before);
@@ -1092,6 +1105,7 @@ main (int argc, char * const argv [])
// PASS 2: ELABORATION
s.verbose = s.perpass_verbose[1];
+ STAP_PROBE1(stap, pass2__start, &s);
rc = semantic_pass (s);
if (s.listing_mode || (rc == 0 && s.last_pass == 2))
@@ -1146,12 +1160,15 @@ main (int argc, char * const argv [])
/* Print out list of missing files */
missing_rpm_list_print(s);
+ STAP_PROBE1(stap, pass2__end, &s);
+
if (rc || s.listing_mode || s.last_pass == 2 || pending_interrupts) goto cleanup;
// PASS 3: TRANSLATION
s.verbose = s.perpass_verbose[2];
times (& tms_before);
gettimeofday (&tv_before, NULL);
+ STAP_PROBE1(stap, pass3__start, &s);
rc = translate_pass (s);
@@ -1175,12 +1192,15 @@ main (int argc, char * const argv [])
<< "Try again with another '--vp 001' option."
<< endl;
+ STAP_PROBE1(stap, pass3__end, &s);
+
if (rc || s.last_pass == 3 || pending_interrupts) goto cleanup;
// PASS 4: COMPILATION
s.verbose = s.perpass_verbose[3];
times (& tms_before);
gettimeofday (&tv_before, NULL);
+ STAP_PROBE1(stap, pass4__start, &s);
rc = compile_pass (s);
if (rc == 0 && s.last_pass == 4)
@@ -1245,6 +1265,8 @@ main (int argc, char * const argv [])
}
}
+ STAP_PROBE1(stap, pass4__end, &s);
+
if (rc || s.last_pass == 4 || pending_interrupts) goto cleanup;
@@ -1256,6 +1278,7 @@ pass_5:
// NB: this message is a judgement call. The other passes don't emit
// a "hello, I'm starting" message, but then the others aren't interactive
// and don't take an indefinite amount of time.
+ STAP_PROBE1(stap, pass5__start, &s);
if (s.verbose) clog << "Pass 5: starting run." << endl;
rc = run_pass (s);
times (& tms_after);
@@ -1271,9 +1294,13 @@ pass_5:
// if (rc) goto cleanup;
+ STAP_PROBE1(stap, pass5__end, &s);
+
// PASS 6: cleaning up
cleanup:
+ STAP_PROBE1(stap, pass6__start, &s);
+
// update the database information
if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
#ifdef HAVE_LIBSQLITE3
@@ -1305,6 +1332,8 @@ pass_5:
}
}
+ STAP_PROBE1(stap, pass6__end, &s);
+
return (rc||pending_interrupts) ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/parse.cxx b/parse.cxx
index 35c78abe..41a13ca5 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -2346,27 +2346,8 @@ parser::parse_symbol ()
expect_unknown(tok_string, cop->module);
}
expect_op(")");
- while (true)
- {
- string c;
- if (peek_op ("->"))
- {
- next();
- expect_ident_or_keyword (c);
- cop->components.push_back
- (make_pair (target_symbol::comp_struct_member, c));
- }
- else if (peek_op ("["))
- {
- next();
- expect_unknown (tok_number, c);
- expect_op ("]");
- cop->components.push_back
- (make_pair (target_symbol::comp_literal_array_index, c));
- }
- else
- break;
- }
+ parse_target_symbol_components(cop);
+
// if there aren't any dereferences, then the cast is pointless
if (cop->components.empty())
{
@@ -2494,27 +2475,7 @@ parser::parse_symbol ()
target_symbol *tsym = new target_symbol;
tsym->tok = t;
tsym->base_name = name;
- while (true)
- {
- string c;
- if (peek_op ("->"))
- {
- next();
- expect_ident_or_keyword (c);
- tsym->components.push_back
- (make_pair (target_symbol::comp_struct_member, c));
- }
- else if (peek_op ("["))
- {
- next();
- expect_unknown (tok_number, c);
- expect_op ("]");
- tsym->components.push_back
- (make_pair (target_symbol::comp_literal_array_index, c));
- }
- else
- break;
- }
+ parse_target_symbol_components(tsym);
return tsym;
}
@@ -2604,4 +2565,33 @@ parser::parse_symbol ()
return sym;
}
+
+void
+parser::parse_target_symbol_components (target_symbol* e)
+{
+ while (true)
+ {
+ if (peek_op ("->"))
+ {
+ const token* t = next();
+ string member;
+ expect_ident_or_keyword (member);
+ e->components.push_back (target_symbol::component(t, member));
+ }
+ else if (peek_op ("["))
+ {
+ const token* t = next();
+ expression* index = parse_expression();
+ literal_number* ln = dynamic_cast<literal_number*>(index);
+ if (ln)
+ e->components.push_back (target_symbol::component(t, ln->value));
+ else
+ e->components.push_back (target_symbol::component(t, index));
+ expect_op ("]");
+ }
+ else
+ break;
+ }
+}
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/parse.h b/parse.h
index cae49b65..5587586e 100644
--- a/parse.h
+++ b/parse.h
@@ -112,6 +112,7 @@ struct next_statement;
struct continue_statement;
struct indexable;
struct expression;
+struct target_symbol;
struct hist_op;
class parser
@@ -203,6 +204,8 @@ private: // nonterminals
expression* parse_crement ();
expression* parse_value ();
expression* parse_symbol ();
+
+ void parse_target_symbol_components (target_symbol* e);
};
diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c
index 010cab12..6a2ac77e 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -451,6 +451,7 @@ int send_request(int type, void *data, int len)
char buf[1024];
int rc = 0;
+ STAP_PROBE3(stapio, send__ctlmsg, type, data, len);
/* Before doing memcpy, make sure 'buf' is big enough. */
if ((len + 4) > (int)sizeof(buf)) {
_err("exceeded maximum send_request size.\n");
diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c
index 7125a7bb..45b142bc 100644
--- a/runtime/staprun/mainloop.c
+++ b/runtime/staprun/mainloop.c
@@ -485,6 +485,7 @@ int stp_main_loop(void)
type = *(uint32_t *) recvbuf;
data = (void *)(recvbuf + sizeof(uint32_t));
nb -= sizeof(uint32_t);
+ STAP_PROBE3(staprun, recv__ctlmsg, type, data, nb);
switch (type) {
#if STP_TRANSPORT_VERSION == 1
diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c
index 917990dc..554eecc8 100644
--- a/runtime/staprun/staprun.c
+++ b/runtime/staprun/staprun.c
@@ -202,6 +202,7 @@ static int remove_module(const char *name, int verb)
close_ctl_channel();
dbug(2, "removing module %s\n", name);
+ STAP_PROBE1(staprun, remove__module, name);
ret = delete_module (name, 0);
if (ret != 0) {
err("Error removing module '%s': %s.\n", name, strerror(errno));
diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h
index 6af04042..0a1ca885 100644
--- a/runtime/staprun/staprun.h
+++ b/runtime/staprun/staprun.h
@@ -38,6 +38,9 @@
/* Include config.h to pick up dependency for --prefix usage. */
#include "config.h"
+/* For STAP_PROBE in staprun.c, staprun_funcs.c, mainloop.c and common.c */
+#include "sys/sdt.h"
+
extern void eprintf(const char *fmt, ...);
extern void switch_syslog(const char *name);
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index 669dc996..ed7f4fc3 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -94,6 +94,7 @@ int insert_module(const char *path, const char *special_options, char **options)
return -1;
}
+ STAP_PROBE1(staprun, insert__module, path);
/* Actually insert the module */
ret = init_module(file, sbuf.st_size, opts);
saved_errno = errno;
diff --git a/runtime/transport/ring_buffer.c b/runtime/transport/ring_buffer.c
index 3af1bf7d..39b79e10 100644
--- a/runtime/transport/ring_buffer.c
+++ b/runtime/transport/ring_buffer.c
@@ -18,12 +18,14 @@ struct _stp_data_entry {
* Trace iterator - used by printout routines who present trace
* results to users and which routines might sleep, etc:
*/
-struct _stp_ring_buffer_data {
+struct _stp_iterator {
#if 0
struct trace_array *tr;
struct tracer *trace;
void *private;
+#endif
int cpu_file;
+#if 0
struct mutex mutex;
#endif
struct ring_buffer_iter *buffer_iter[NR_CPUS];
@@ -44,10 +46,19 @@ struct _stp_ring_buffer_data {
#endif
};
+/* In bulk mode, we need 1 'struct _stp_iterator' for each cpu. In
+ * 'normal' mode, we only need 1 'struct _stp_iterator' (since all
+ * output is sent through 1 file). */
+#ifdef STP_BULKMODE
+#define NR_ITERS NR_CPUS
+#else
+#define NR_ITERS 1
+#endif
+
struct _stp_relay_data_type {
enum _stp_transport_state transport_state;
struct ring_buffer *rb;
- struct _stp_ring_buffer_data rb_data;
+ struct _stp_iterator iter[NR_ITERS];
cpumask_var_t trace_reader_cpumask;
struct timer_list timer;
int overwrite_flag;
@@ -99,7 +110,10 @@ fail:
static int _stp_data_open_trace(struct inode *inode, struct file *file)
{
- int cpu_file = (int)(long) inode->i_private;
+ struct _stp_iterator *iter = inode->i_private;
+#ifdef STP_BULKMODE
+ int cpu_file = iter->cpu_file;
+#endif
/* We only allow for one reader per cpu */
dbug_trans(1, "trace attach\n");
@@ -123,10 +137,11 @@ static int _stp_data_open_trace(struct inode *inode, struct file *file)
static int _stp_data_release_trace(struct inode *inode, struct file *file)
{
- int cpu_file = (int)(long) inode->i_private;
+ struct _stp_iterator *iter = inode->i_private;
+
dbug_trans(1, "trace detach\n");
#ifdef STP_BULKMODE
- cpumask_clear_cpu(cpu_file, _stp_relay_data.trace_reader_cpumask);
+ cpumask_clear_cpu(iter->cpu_file, _stp_relay_data.trace_reader_cpumask);
#else
cpumask_clear(_stp_relay_data.trace_reader_cpumask);
#endif
@@ -176,10 +191,14 @@ _stp_event_to_user(struct ring_buffer_event *event, char __user *ubuf,
return cnt;
}
-static int _stp_ring_buffer_empty_cpu(int cpu)
+static int _stp_ring_buffer_empty_cpu(struct _stp_iterator *iter)
{
- if (_stp_relay_data.rb_data.buffer_iter[cpu]) {
- if (ring_buffer_iter_empty(_stp_relay_data.rb_data.buffer_iter[cpu]))
+ int cpu;
+
+#ifdef STP_BULKMODE
+ cpu = iter->cpu_file;
+ if (iter->buffer_iter[cpu]) {
+ if (ring_buffer_iter_empty(iter->buffer_iter[cpu]))
return 1;
}
else {
@@ -187,39 +206,56 @@ static int _stp_ring_buffer_empty_cpu(int cpu)
return 1;
}
return 0;
+#else
+ for_each_possible_cpu(cpu) {
+ if (iter->buffer_iter[cpu]) {
+ if (!ring_buffer_iter_empty(iter->buffer_iter[cpu]))
+ return 0;
+ }
+ else {
+ if (!ring_buffer_empty_cpu(_stp_relay_data.rb, cpu))
+ return 0;
+ }
+ }
+ return 1;
+#endif
}
static int _stp_ring_buffer_empty(void)
{
+ struct _stp_iterator *iter;
#ifdef STP_BULKMODE
- return _stp_ring_buffer_empty_cpu(_stp_relay_data.rb_data.cpu);
-#else
int cpu;
+
for_each_possible_cpu(cpu) {
- if (! _stp_ring_buffer_empty_cpu(cpu))
+ iter = &_stp_relay_data.iter[cpu];
+ if (! _stp_ring_buffer_empty_cpu(iter))
return 0;
}
return 1;
+#else
+ iter = &_stp_relay_data.iter[0];
+ return _stp_ring_buffer_empty_cpu(iter);
#endif
}
-static void _stp_ring_buffer_iterator_increment(void)
+static void _stp_ring_buffer_iterator_increment(struct _stp_iterator *iter)
{
- if (_stp_relay_data.rb_data.buffer_iter[_stp_relay_data.rb_data.cpu]) {
- ring_buffer_read(_stp_relay_data.rb_data.buffer_iter[_stp_relay_data.rb_data.cpu], NULL);
- }
+ if (iter->buffer_iter[iter->cpu])
+ ring_buffer_read(iter->buffer_iter[iter->cpu], NULL);
}
-static void _stp_ring_buffer_consume(void)
+static void _stp_ring_buffer_consume(struct _stp_iterator *iter)
{
- _stp_ring_buffer_iterator_increment();
- ring_buffer_consume(_stp_relay_data.rb, _stp_relay_data.rb_data.cpu,
- &_stp_relay_data.rb_data.ts);
+ _stp_ring_buffer_iterator_increment(iter);
+ ring_buffer_consume(_stp_relay_data.rb, iter->cpu, &iter->ts);
}
static ssize_t _stp_tracing_wait_pipe(struct file *filp)
{
- if (_stp_ring_buffer_empty()) {
+ struct _stp_iterator *iter = filp->private_data;
+
+ if (_stp_ring_buffer_empty_cpu(iter)) {
if ((filp->f_flags & O_NONBLOCK)) {
dbug_trans(1, "returning -EAGAIN\n");
return -EAGAIN;
@@ -237,33 +273,32 @@ static ssize_t _stp_tracing_wait_pipe(struct file *filp)
return 1;
}
-static struct ring_buffer_event *_stp_peek_next_event(int cpu, u64 *ts)
+static struct ring_buffer_event *
+_stp_peek_next_event(struct _stp_iterator *iter, int cpu, u64 *ts)
{
- if (_stp_relay_data.rb_data.buffer_iter[cpu])
- return ring_buffer_iter_peek(_stp_relay_data.rb_data.buffer_iter[cpu], ts);
+ if (iter->buffer_iter[cpu])
+ return ring_buffer_iter_peek(iter->buffer_iter[cpu], ts);
else
return ring_buffer_peek(_stp_relay_data.rb, cpu, ts);
}
/* Find the next real event */
-static struct ring_buffer_event *_stp_find_next_event(int cpu_file)
+static struct ring_buffer_event *
+_stp_find_next_event(struct _stp_iterator *iter)
{
struct ring_buffer_event *event;
+ int cpu_file = iter->cpu_file;
#ifdef STP_BULKMODE
/*
* If we are in a per_cpu trace file, don't bother by iterating over
* all cpus and peek directly.
*/
- if (_stp_ring_buffer_empty_cpu(cpu_file))
+ if (ring_buffer_iter_empty(iter->buffer_iter[cpu_file]))
return NULL;
- event = _stp_peek_next_event(cpu_file, &_stp_relay_data.rb_data.ts);
- _stp_relay_data.rb_data.cpu = cpu_file;
+ event = _stp_peek_next_event(iter, cpu_file, &iter->ts);
+ iter->cpu = cpu_file;
-#if 0
- if (event)
- _stp_ring_buffer_iterator_increment();
-#endif
return event;
#else
struct ring_buffer_event *next = NULL;
@@ -272,10 +307,13 @@ static struct ring_buffer_event *_stp_find_next_event(int cpu_file)
int cpu;
for_each_possible_cpu(cpu) {
- if (_stp_ring_buffer_empty_cpu(cpu))
+ if (iter->buffer_iter[cpu] == NULL)
+ continue;
+
+ if (ring_buffer_iter_empty(iter->buffer_iter[cpu]))
continue;
- event = _stp_peek_next_event(cpu, &ts);
+ event = _stp_peek_next_event(iter, cpu, &ts);
/*
* Pick the event with the smallest timestamp:
@@ -287,12 +325,8 @@ static struct ring_buffer_event *_stp_find_next_event(int cpu_file)
}
}
- _stp_relay_data.rb_data.cpu = next_cpu;
- _stp_relay_data.rb_data.ts = next_ts;
-#if 0
- if (next)
- _stp_ring_buffer_iterator_increment();
-#endif
+ iter->cpu = next_cpu;
+ iter->ts = next_ts;
return next;
#endif
}
@@ -307,8 +341,10 @@ _stp_data_read_trace(struct file *filp, char __user *ubuf,
{
ssize_t sret;
struct ring_buffer_event *event;
- int cpu_file = (int)(long) filp->private_data;
-#ifndef STP_BULKMODE
+ struct _stp_iterator *iter = filp->private_data;
+#ifdef STP_BULKMODE
+ int cpu_file = iter->cpu_file;
+#else
int cpu;
#endif
@@ -320,36 +356,34 @@ _stp_data_read_trace(struct file *filp, char __user *ubuf,
goto out;
#ifdef STP_BULKMODE
- _stp_relay_data.rb_data.buffer_iter[cpu_file]
+ iter->buffer_iter[cpu_file]
= ring_buffer_read_start(_stp_relay_data.rb, cpu_file);
+ if (iter->buffer_iter[cpu_file] == NULL) {
+ dbug_trans(0, "buffer_iter[%d] was NULL\n", cpu_file);
+ goto out;
+ }
#else
for_each_possible_cpu(cpu) {
- _stp_relay_data.rb_data.buffer_iter[cpu]
+ iter->buffer_iter[cpu]
= ring_buffer_read_start(_stp_relay_data.rb, cpu);
}
#endif
- _stp_relay_data.rb_data.ts = 0;
+ iter->ts = 0;
dbug_trans(0, "iterator(s) started\n");
- /* stop when tracing is finished */
- if (_stp_ring_buffer_empty()) {
- sret = 0;
- goto out;
- }
-
if (cnt >= PAGE_SIZE)
cnt = PAGE_SIZE - 1;
dbug_trans(1, "sret = %lu\n", (unsigned long)sret);
sret = 0;
- while ((event = _stp_find_next_event(cpu_file)) != NULL) {
+ while ((event = _stp_find_next_event(iter)) != NULL) {
ssize_t len;
len = _stp_event_to_user(event, ubuf, cnt);
if (len <= 0)
break;
- _stp_ring_buffer_consume();
+ _stp_ring_buffer_consume(iter);
dbug_trans(1, "event consumed\n");
ubuf += len;
cnt -= len;
@@ -360,16 +394,16 @@ _stp_data_read_trace(struct file *filp, char __user *ubuf,
out:
#ifdef STP_BULKMODE
- if (_stp_relay_data.rb_data.buffer_iter[cpu_file]) {
- ring_buffer_read_finish(_stp_relay_data.rb_data.buffer_iter[cpu_file]);
- _stp_relay_data.rb_data.buffer_iter[cpu_file] = NULL;
+ if (iter->buffer_iter[cpu_file]) {
+ ring_buffer_read_finish(iter->buffer_iter[cpu_file]);
+ iter->buffer_iter[cpu_file] = NULL;
dbug_trans(0, "iterator finished\n");
}
#else
for_each_possible_cpu(cpu) {
- if (_stp_relay_data.rb_data.buffer_iter[cpu]) {
- ring_buffer_read_finish(_stp_relay_data.rb_data.buffer_iter[cpu]);
- _stp_relay_data.rb_data.buffer_iter[cpu] = NULL;
+ if (iter->buffer_iter[cpu]) {
+ ring_buffer_read_finish(iter->buffer_iter[cpu]);
+ iter->buffer_iter[cpu] = NULL;
}
}
dbug_trans(0, "iterator(s) finished\n");
@@ -381,11 +415,13 @@ out:
static unsigned int
_stp_data_poll_trace(struct file *filp, poll_table *poll_table)
{
+ struct _stp_iterator *iter = filp->private_data;
+
dbug_trans(1, "entry\n");
- if (! _stp_ring_buffer_empty())
+ if (! _stp_ring_buffer_empty_cpu(iter))
return POLLIN | POLLRDNORM;
poll_wait(filp, &_stp_poll_wait, poll_table);
- if (! _stp_ring_buffer_empty())
+ if (! _stp_ring_buffer_empty_cpu(iter))
return POLLIN | POLLRDNORM;
dbug_trans(1, "exit\n");
@@ -446,6 +482,7 @@ _stp_data_write_reserve(size_t size_request, void **entry)
#endif
if (unlikely(! event)) {
int cpu;
+ struct _stp_iterator *iter;
dbug_trans(0, "event = NULL (%p)?\n", event);
if (! _stp_relay_data.overwrite_flag) {
@@ -457,15 +494,20 @@ _stp_data_write_reserve(size_t size_request, void **entry)
* full, take a event out of the buffer and consume it
* (throw it away). This should make room for the new
* data. */
+#ifdef STP_BULKMODE
cpu = raw_smp_processor_id();
- event = _stp_find_next_event(cpu);
+ iter = &_stp_relay_data.iter[cpu];
+#else
+ iter = &_stp_relay_data.iter[0];
+#endif
+ event = _stp_find_next_event(iter);
if (event) {
ssize_t len;
sde = (struct _stp_data_entry *)ring_buffer_event_data(event);
if (sde->len < size_request)
size_request = sde->len;
- _stp_ring_buffer_consume();
+ _stp_ring_buffer_consume(iter);
/* Try to reserve again. */
#ifdef STAPCONF_RING_BUFFER_FLAGS
@@ -595,14 +637,20 @@ static int _stp_transport_data_fs_init(void)
__stp_entry[cpu]->d_inode->i_uid = _stp_uid;
__stp_entry[cpu]->d_inode->i_gid = _stp_gid;
- __stp_entry[cpu]->d_inode->i_private = (void *)(long)cpu;
+ __stp_entry[cpu]->d_inode->i_private = &_stp_relay_data.iter[cpu];
#ifndef STP_BULKMODE
- if (cpu != 0)
- break;
+ break;
#endif
}
+#ifdef STP_BULKMODE
+ for_each_possible_cpu(cpu) {
+ _stp_relay_data.iter[cpu].cpu_file = cpu;
+ _stp_relay_data.iter[cpu].cpu = cpu;
+ }
+#endif
+
dbug_trans(1, "returning 0...\n");
_stp_relay_data.transport_state = STP_TRANSPORT_INITIALIZED;
return 0;
diff --git a/runtime/unwind/i386.h b/runtime/unwind/i386.h
index 9f488f07..b19df584 100644
--- a/runtime/unwind/i386.h
+++ b/runtime/unwind/i386.h
@@ -92,7 +92,7 @@ static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
#endif
}
- info->call_frame = 1;
+ info->call_frame = 0;
}
static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
diff --git a/runtime/unwind/x86_64.h b/runtime/unwind/x86_64.h
index 3c70f206..8860b8ee 100644
--- a/runtime/unwind/x86_64.h
+++ b/runtime/unwind/x86_64.h
@@ -107,7 +107,7 @@ static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
/*const*/ struct pt_regs *regs)
{
info->regs = *regs;
- info->call_frame = 1;
+ info->call_frame = 0;
}
static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
diff --git a/session.h b/session.h
index ed17d5ae..ea914425 100644
--- a/session.h
+++ b/session.h
@@ -103,6 +103,7 @@ struct systemtap_session
bool keep_tmpdir;
bool guru_mode;
bool listing_mode;
+ bool listing_mode_vars;
bool bulk_mode;
bool unoptimized;
bool merge;
diff --git a/stap.1.in b/stap.1.in
index 7736a612..0e7a51f4 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -132,7 +132,7 @@ debugging information for $target variables.
Unoptimized mode. Disable unused code elision during elaboration.
.TP
.B \-w
-Suppressed warnings mode. Disable warning messages for elided code in user script.
+Suppressed warnings mode. Disables all warning messages.
.TP
.BI \-b
Use bulk mode (percpu files) for kernel-to-user data transfer.
diff --git a/staptree.cxx b/staptree.cxx
index a762cf47..aa37b754 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -187,6 +187,31 @@ operator << (ostream& o, const exp_type& e)
}
+void
+target_symbol::assert_no_components(const std::string& tapset)
+{
+ if (components.empty())
+ return;
+
+ switch (components[0].type)
+ {
+ case target_symbol::comp_literal_array_index:
+ case target_symbol::comp_expression_array_index:
+ throw semantic_error(tapset + " variable '" + base_name +
+ "' may not be used as array",
+ components[0].tok);
+ case target_symbol::comp_struct_member:
+ throw semantic_error(tapset + " variable '" + base_name +
+ "' may not be used as a structure",
+ components[0].tok);
+ default:
+ throw semantic_error ("invalid use of " + tapset +
+ " variable '" + base_name + "'",
+ components[0].tok);
+ }
+}
+
+
// ------------------------------------------------------------------------
// parse tree printing
@@ -260,27 +285,41 @@ void symbol::print (ostream& o) const
}
-void target_symbol::print (std::ostream& o) const
+void target_symbol::component::print (ostream& o) const
+{
+ switch (type)
+ {
+ case comp_struct_member:
+ o << "->" << member;
+ break;
+ case comp_literal_array_index:
+ o << '[' << num_index << ']';
+ break;
+ case comp_expression_array_index:
+ o << '[' << *expr_index << ']';
+ break;
+ }
+}
+
+
+std::ostream& operator << (std::ostream& o, const target_symbol::component& c)
+{
+ c.print (o);
+ return o;
+}
+
+
+void target_symbol::print (ostream& o) const
{
if (addressof)
o << "&";
o << base_name;
for (unsigned i = 0; i < components.size(); ++i)
- {
- switch (components[i].first)
- {
- case comp_literal_array_index:
- o << '[' << components[i].second << ']';
- break;
- case comp_struct_member:
- o << "->" << components[i].second;
- break;
- }
- }
+ o << components[i];
}
-void cast_op::print (std::ostream& o) const
+void cast_op::print (ostream& o) const
{
if (addressof)
o << "&";
@@ -290,17 +329,7 @@ void cast_op::print (std::ostream& o) const
o << ", " << lex_cast_qstring (module);
o << ')';
for (unsigned i = 0; i < components.size(); ++i)
- {
- switch (components[i].first)
- {
- case comp_literal_array_index:
- o << '[' << components[i].second << ']';
- break;
- case comp_struct_member:
- o << "->" << components[i].second;
- break;
- }
- }
+ o << components[i];
}
@@ -1247,6 +1276,22 @@ target_symbol::visit (visitor* u)
}
void
+target_symbol::visit_components (visitor* u)
+{
+ for (unsigned i = 0; i < components.size(); ++i)
+ if (components[i].type == comp_expression_array_index)
+ components[i].expr_index->visit (u);
+}
+
+void
+target_symbol::visit_components (update_visitor* u)
+{
+ for (unsigned i = 0; i < components.size(); ++i)
+ if (components[i].type == comp_expression_array_index)
+ u->replace (components[i].expr_index);
+}
+
+void
cast_op::visit (visitor* u)
{
u->visit_cast_op(this);
@@ -1614,14 +1659,16 @@ traversing_visitor::visit_symbol (symbol*)
}
void
-traversing_visitor::visit_target_symbol (target_symbol*)
+traversing_visitor::visit_target_symbol (target_symbol* e)
{
+ e->visit_components (this);
}
void
traversing_visitor::visit_cast_op (cast_op* e)
{
e->operand->visit (this);
+ e->visit_components (this);
}
void
@@ -1723,6 +1770,8 @@ varuse_collecting_visitor::visit_target_symbol (target_symbol *e)
if (is_active_lvalue (e))
embedded_seen = true;
+
+ functioncall_traversing_visitor::visit_target_symbol (e);
}
void
@@ -2164,7 +2213,7 @@ void
update_visitor::visit_block (block* s)
{
for (unsigned i = 0; i < s->statements.size(); ++i)
- s->statements[i] = require (s->statements[i]);
+ replace (s->statements[i]);
provide (s);
}
@@ -2183,26 +2232,26 @@ update_visitor::visit_null_statement (null_statement* s)
void
update_visitor::visit_expr_statement (expr_statement* s)
{
- s->value = require (s->value);
+ replace (s->value);
provide (s);
}
void
update_visitor::visit_if_statement (if_statement* s)
{
- s->condition = require (s->condition);
- s->thenblock = require (s->thenblock);
- s->elseblock = require (s->elseblock);
+ replace (s->condition);
+ replace (s->thenblock);
+ replace (s->elseblock);
provide (s);
}
void
update_visitor::visit_for_loop (for_loop* s)
{
- s->init = require (s->init);
- s->cond = require (s->cond);
- s->incr = require (s->incr);
- s->block = require (s->block);
+ replace (s->init);
+ replace (s->cond);
+ replace (s->incr);
+ replace (s->block);
provide (s);
}
@@ -2210,24 +2259,24 @@ void
update_visitor::visit_foreach_loop (foreach_loop* s)
{
for (unsigned i = 0; i < s->indexes.size(); ++i)
- s->indexes[i] = require (s->indexes[i]);
- s->base = require (s->base);
- s->limit = require (s->limit);
- s->block = require (s->block);
+ replace (s->indexes[i]);
+ replace (s->base);
+ replace (s->limit);
+ replace (s->block);
provide (s);
}
void
update_visitor::visit_return_statement (return_statement* s)
{
- s->value = require (s->value);
+ replace (s->value);
provide (s);
}
void
update_visitor::visit_delete_statement (delete_statement* s)
{
- s->value = require (s->value);
+ replace (s->value);
provide (s);
}
@@ -2264,29 +2313,29 @@ update_visitor::visit_literal_number (literal_number* e)
void
update_visitor::visit_binary_expression (binary_expression* e)
{
- e->left = require (e->left);
- e->right = require (e->right);
+ replace (e->left);
+ replace (e->right);
provide (e);
}
void
update_visitor::visit_unary_expression (unary_expression* e)
{
- e->operand = require (e->operand);
+ replace (e->operand);
provide (e);
}
void
update_visitor::visit_pre_crement (pre_crement* e)
{
- e->operand = require (e->operand);
+ replace (e->operand);
provide (e);
}
void
update_visitor::visit_post_crement (post_crement* e)
{
- e->operand = require (e->operand);
+ replace (e->operand);
provide (e);
}
@@ -2294,56 +2343,56 @@ update_visitor::visit_post_crement (post_crement* e)
void
update_visitor::visit_logical_or_expr (logical_or_expr* e)
{
- e->left = require (e->left);
- e->right = require (e->right);
+ replace (e->left);
+ replace (e->right);
provide (e);
}
void
update_visitor::visit_logical_and_expr (logical_and_expr* e)
{
- e->left = require (e->left);
- e->right = require (e->right);
+ replace (e->left);
+ replace (e->right);
provide (e);
}
void
update_visitor::visit_array_in (array_in* e)
{
- e->operand = require (e->operand);
+ replace (e->operand);
provide (e);
}
void
update_visitor::visit_comparison (comparison* e)
{
- e->left = require (e->left);
- e->right = require (e->right);
+ replace (e->left);
+ replace (e->right);
provide (e);
}
void
update_visitor::visit_concatenation (concatenation* e)
{
- e->left = require (e->left);
- e->right = require (e->right);
+ replace (e->left);
+ replace (e->right);
provide (e);
}
void
update_visitor::visit_ternary_expression (ternary_expression* e)
{
- e->cond = require (e->cond);
- e->truevalue = require (e->truevalue);
- e->falsevalue = require (e->falsevalue);
+ replace (e->cond);
+ replace (e->truevalue);
+ replace (e->falsevalue);
provide (e);
}
void
update_visitor::visit_assignment (assignment* e)
{
- e->left = require (e->left);
- e->right = require (e->right);
+ replace (e->left);
+ replace (e->right);
provide (e);
}
@@ -2356,22 +2405,24 @@ update_visitor::visit_symbol (symbol* e)
void
update_visitor::visit_target_symbol (target_symbol* e)
{
+ e->visit_components (this);
provide (e);
}
void
update_visitor::visit_cast_op (cast_op* e)
{
- e->operand = require (e->operand);
+ replace (e->operand);
+ e->visit_components (this);
provide (e);
}
void
update_visitor::visit_arrayindex (arrayindex* e)
{
- e->base = require (e->base);
+ replace (e->base);
for (unsigned i = 0; i < e->indexes.size(); ++i)
- e->indexes[i] = require (e->indexes[i]);
+ replace (e->indexes[i]);
provide (e);
}
@@ -2379,7 +2430,7 @@ void
update_visitor::visit_functioncall (functioncall* e)
{
for (unsigned i = 0; i < e->args.size(); ++i)
- e->args[i] = require (e->args[i]);
+ replace (e->args[i]);
provide (e);
}
@@ -2387,27 +2438,27 @@ void
update_visitor::visit_print_format (print_format* e)
{
for (unsigned i = 0; i < e->args.size(); ++i)
- e->args[i] = require (e->args[i]);
- e->hist = require (e->hist);
+ replace (e->args[i]);
+ replace (e->hist);
provide (e);
}
void
update_visitor::visit_stat_op (stat_op* e)
{
- e->stat = require (e->stat);
+ replace (e->stat);
provide (e);
}
void
update_visitor::visit_hist_op (hist_op* e)
{
- e->stat = require (e->stat);
+ replace (e->stat);
provide (e);
}
template <> indexable*
-update_visitor::require <indexable*> (indexable* src, bool clearok)
+update_visitor::require <indexable> (indexable* src, bool clearok)
{
indexable *dst = NULL;
if (src != NULL)
diff --git a/staptree.h b/staptree.h
index 6b62b0cb..f1d43403 100644
--- a/staptree.h
+++ b/staptree.h
@@ -60,6 +60,7 @@ std::ostream& operator << (std::ostream& o, const exp_type& e);
struct token;
struct visitor;
+struct update_visitor;
struct expression
{
@@ -229,18 +230,42 @@ struct target_symbol: public symbol
enum component_type
{
comp_struct_member,
- comp_literal_array_index
+ comp_literal_array_index,
+ comp_expression_array_index,
};
+
+ struct component
+ {
+ const token* tok;
+ component_type type;
+ std::string member; // comp_struct_member
+ int64_t num_index; // comp_literal_array_index
+ expression* expr_index; // comp_expression_array_index
+
+ component(const token* t, const std::string& m):
+ tok(t), type(comp_struct_member), member(m) {}
+ component(const token* t, int64_t n):
+ tok(t), type(comp_literal_array_index), num_index(n) {}
+ component(const token* t, expression* e):
+ tok(t), type(comp_expression_array_index), expr_index(e) {}
+ void print (std::ostream& o) const;
+ };
+
bool addressof;
std::string base_name;
- std::vector<std::pair<component_type, std::string> > components;
+ std::vector<component> components;
std::string probe_context_var;
semantic_error* saved_conversion_error;
target_symbol(): addressof(false), saved_conversion_error (0) {}
void print (std::ostream& o) const;
void visit (visitor* u);
+ void visit_components (visitor* u);
+ void visit_components (update_visitor* u);
+ void assert_no_components(const std::string& tapset);
};
+std::ostream& operator << (std::ostream& o, const target_symbol::component& c);
+
struct cast_op: public target_symbol
{
@@ -834,25 +859,30 @@ struct throwing_visitor: public visitor
struct update_visitor: public visitor
{
- template <typename T> T require (T src, bool clearok=false)
+ template <typename T> T* require (T* src, bool clearok=false)
{
- T dst = NULL;
+ T* dst = NULL;
if (src != NULL)
{
src->visit(this);
assert(!targets.empty());
- dst = static_cast<T>(targets.top());
+ dst = static_cast<T*>(targets.top());
targets.pop();
assert(clearok || dst);
}
return dst;
}
- template <typename T> void provide (T src)
+ template <typename T> void provide (T* src)
{
targets.push(static_cast<void*>(src));
}
+ template <typename T> void replace (T*& src, bool clearok=false)
+ {
+ src = require(src, clearok);
+ }
+
virtual ~update_visitor() { assert(targets.empty()); }
virtual void visit_block (block *s);
@@ -894,7 +924,7 @@ private:
};
template <> indexable*
-update_visitor::require <indexable*> (indexable* src, bool clearok);
+update_visitor::require <indexable> (indexable* src, bool clearok);
// A visitor which performs a deep copy of the root node it's applied
// to. NB: It does not copy any of the variable or function
@@ -904,7 +934,7 @@ update_visitor::require <indexable*> (indexable* src, bool clearok);
struct deep_copy_visitor: public update_visitor
{
- template <typename T> static T deep_copy (T e)
+ template <typename T> static T* deep_copy (T* e)
{
deep_copy_visitor v;
return v.require (e);
diff --git a/tapset-mark.cxx b/tapset-mark.cxx
index a358a20e..6b4f47c5 100644
--- a/tapset-mark.cxx
+++ b/tapset-mark.cxx
@@ -103,23 +103,7 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
if (is_active_lvalue (e))
throw semantic_error("write to marker parameter not permitted", e->tok);
- if (e->components.size() > 0)
- {
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("marker argument may not be used as array",
- e->tok);
- break;
- case target_symbol::comp_struct_member:
- throw semantic_error("marker argument may not be used as a structure",
- e->tok);
- break;
- default:
- throw semantic_error ("invalid marker argument use", e->tok);
- break;
- }
- }
+ e->assert_no_components("marker");
// Remember that we've seen a target variable.
target_symbol_seen = true;
@@ -138,23 +122,7 @@ mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
if (is_active_lvalue (e))
throw semantic_error("write to marker '" + sname + "' not permitted", e->tok);
- if (e->components.size() > 0)
- {
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("marker '" + sname + "' may not be used as array",
- e->tok);
- break;
- case target_symbol::comp_struct_member:
- throw semantic_error("marker '" + sname + "' may not be used as a structure",
- e->tok);
- break;
- default:
- throw semantic_error ("invalid marker '" + sname + "' use", e->tok);
- break;
- }
- }
+ e->assert_no_components("marker");
if (e->base_name == "$format" || e->base_name == "$name") {
string fname;
@@ -255,7 +223,7 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s,
// Now expand the local variables in the probe body
mark_var_expanding_visitor v (sess, name, mark_args);
- this->body = v.require (this->body);
+ v.replace (this->body);
target_symbol_seen = v.target_symbol_seen;
if (sess.verbose > 2)
diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx
index 0fb567f7..86806d61 100644
--- a/tapset-perfmon.cxx
+++ b/tapset-perfmon.cxx
@@ -67,24 +67,7 @@ perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e)
if (e->addressof)
throw semantic_error("cannot take address of perfmon variable", e->tok);
- if (e->components.size() > 0)
- {
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("perfmon probe '$counter' variable may not be used as array",
- e->tok);
- break;
- case target_symbol::comp_struct_member:
- throw semantic_error("perfmon probe '$counter' variable may not be used as a structure",
- e->tok);
- break;
- default:
- throw semantic_error ("invalid use of perfmon probe '$counter' variable",
- e->tok);
- break;
- }
- }
+ e->assert_no_components("perfmon");
ec->code = "THIS->__retvalue = _pfm_pmd_x[" +
lex_cast<string>(counter_number) + "].reg_num;";
@@ -170,7 +153,7 @@ perfmon_derived_probe::perfmon_derived_probe (probe* p, probe_point* l,
// Now expand the local variables in the probe body
perfmon_var_expanding_visitor v (sess, probes_allocated-1);
- this->body = v.require (this->body);
+ v.replace (this->body);
if (sess.verbose > 1)
clog << "perfmon-based probe" << endl;
diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx
index a996ee32..527b4486 100644
--- a/tapset-procfs.cxx
+++ b/tapset-procfs.cxx
@@ -94,7 +94,7 @@ procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p,
{
// Expand local variables in the probe body
procfs_var_expanding_visitor v (s, name, path, write);
- this->body = v.require (this->body);
+ v.replace (this->body);
target_symbol_seen = v.target_symbol_seen;
}
@@ -358,24 +358,7 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e)
throw semantic_error ("invalid target symbol for procfs probe, $value expected",
e->tok);
- if (e->components.size() > 0)
- {
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("procfs target variable '$value' may not be used as array",
- e->tok);
- break;
- case target_symbol::comp_struct_member:
- throw semantic_error("procfs target variable '$value' may not be used as a structure",
- e->tok);
- break;
- default:
- throw semantic_error ("invalid use of procfs target variable '$value'",
- e->tok);
- break;
- }
- }
+ e->assert_no_components("procfs");
bool lvalue = is_active_lvalue(e);
if (write_probe && lvalue)
diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx
index ec20282a..a07e08b8 100644
--- a/tapset-utrace.cxx
+++ b/tapset-utrace.cxx
@@ -120,7 +120,7 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s,
{
// Expand local variables in the probe body
utrace_var_expanding_visitor v (s, l, name, flags);
- this->body = v.require (this->body);
+ v.replace (this->body);
target_symbol_seen = v.target_symbol_seen;
// If during target-variable-expanding the probe, we added a new block
@@ -407,54 +407,80 @@ utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol* e)
void
utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
{
- string argnum_s = e->base_name.substr(4,e->base_name.length()-4);
- int argnum = lex_cast<int>(argnum_s);
-
if (flags != UDPF_SYSCALL)
- throw semantic_error ("only \"process(PATH_OR_PID).syscall\" support $argN.", e->tok);
+ throw semantic_error ("only \"process(PATH_OR_PID).syscall\" support $argN or $$parms.", e->tok);
- if (e->components.size() > 0)
+ if (e->base_name == "$$parms")
{
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("utrace target variable '$argN' may not be used as array",
- e->tok);
- break;
- case target_symbol::comp_struct_member:
- throw semantic_error("utrace target variable '$argN' may not be used as a structure",
- e->tok);
- break;
- default:
- throw semantic_error ("invalid use of utrace target variable '$argN'",
- e->tok);
- break;
- }
- }
-
- // FIXME: max argnument number should not be hardcoded.
- if (argnum < 1 || argnum > 6)
- throw semantic_error ("invalid syscall argument number (1-6)", e->tok);
-
- bool lvalue = is_active_lvalue(e);
- if (lvalue)
- throw semantic_error("utrace '$argN' variable is read-only", e->tok);
-
- // Remember that we've seen a target variable.
- target_symbol_seen = true;
-
- // We're going to substitute a synthesized '_utrace_syscall_arg'
- // function call for the '$argN' reference.
- functioncall* n = new functioncall;
- n->tok = e->tok;
- n->function = "_utrace_syscall_arg";
- n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
-
- literal_number *num = new literal_number(argnum - 1);
- num->tok = e->tok;
- n->args.push_back(num);
-
- provide (n);
+ // copy from tracepoint
+ print_format* pf = new print_format;
+ token* pf_tok = new token(*e->tok);
+ pf_tok->content = "sprintf";
+ pf->tok = pf_tok;
+ pf->print_to_stream = false;
+ pf->print_with_format = true;
+ pf->print_with_delim = false;
+ pf->print_with_newline = false;
+ pf->print_char = false;
+
+ target_symbol_seen = true;
+
+ for (unsigned i = 0; i < 6; ++i)
+ {
+ if (i > 0)
+ pf->raw_components += " ";
+ pf->raw_components += "$arg" + lex_cast<string>(i+1);
+ target_symbol *tsym = new target_symbol;
+ tsym->tok = e->tok;
+ tsym->base_name = "$arg" + lex_cast<string>(i+1);
+ tsym->saved_conversion_error = 0;
+ pf->raw_components += "=%#x"; //FIXME: missing type info
+
+ functioncall* n = new functioncall; //same as the following
+ n->tok = e->tok;
+ n->function = "_utrace_syscall_arg";
+ n->referent = 0;
+ literal_number *num = new literal_number(i);
+ num->tok = e->tok;
+ n->args.push_back(num);
+
+ pf->args.push_back(n);
+ }
+ pf->components = print_format::string_to_components(pf->raw_components);
+
+ provide (pf);
+ }
+ else // $argN
+ {
+ string argnum_s = e->base_name.substr(4,e->base_name.length()-4);
+ int argnum = lex_cast<int>(argnum_s);
+
+ e->assert_no_components("utrace");
+
+ // FIXME: max argnument number should not be hardcoded.
+ if (argnum < 1 || argnum > 6)
+ throw semantic_error ("invalid syscall argument number (1-6)", e->tok);
+
+ bool lvalue = is_active_lvalue(e);
+ if (lvalue)
+ throw semantic_error("utrace '$argN' variable is read-only", e->tok);
+
+ // Remember that we've seen a target variable.
+ target_symbol_seen = true;
+
+ // We're going to substitute a synthesized '_utrace_syscall_arg'
+ // function call for the '$argN' reference.
+ functioncall* n = new functioncall;
+ n->tok = e->tok;
+ n->function = "_utrace_syscall_arg";
+ n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
+
+ literal_number *num = new literal_number(argnum - 1);
+ num->tok = e->tok;
+ n->args.push_back(num);
+
+ provide (n);
+ }
}
void
@@ -462,24 +488,7 @@ utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
{
string sname = e->base_name;
- if (e->components.size() > 0)
- {
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("utrace target variable '" + sname + "' may not be used as array",
- e->tok);
- break;
- case target_symbol::comp_struct_member:
- throw semantic_error("utrace target variable '" + sname + "' may not be used as a structure",
- e->tok);
- break;
- default:
- throw semantic_error ("invalid use of utrace target variable '" + sname + "'",
- e->tok);
- break;
- }
- }
+ e->assert_no_components("utrace");
bool lvalue = is_active_lvalue(e);
if (lvalue)
@@ -542,12 +551,12 @@ utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e)
if (e->addressof)
throw semantic_error("cannot take address of utrace variable", e->tok);
- if (e->base_name.substr(0,4) == "$arg")
+ if (e->base_name.substr(0,4) == "$arg" || e->base_name == "$$parms")
visit_target_symbol_arg(e);
else if (e->base_name == "$syscall" || e->base_name == "$return")
visit_target_symbol_context(e);
else
- throw semantic_error ("invalid target symbol for utrace probe, $syscall, $return or $argN expected",
+ throw semantic_error ("invalid target symbol for utrace probe, $syscall, $return, $argN or $$parms expected",
e->tok);
}
diff --git a/tapset/stap_staticmarkers.stp b/tapset/stap_staticmarkers.stp
new file mode 100644
index 00000000..ff295771
--- /dev/null
+++ b/tapset/stap_staticmarkers.stp
@@ -0,0 +1,267 @@
+// stap/staprun/stapio static probes tapset
+//
+// Copyright (C) 2009 Red Hat Inc.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+/**
+ * probes stap.pass0, stap.pass0.end
+ * @session: the systemtap_session variable s
+ *
+ * pass0 fires after command line arguments have been parsed.
+ * pass0.end fires just before the gettimeofday() call for pass1.
+ */
+probe stap.pass0 = process("stap").mark("pass0__start") {
+ session = $arg1
+}
+probe stap.pass0.end = process("stap").mark("pass0__end") {
+ session = $arg1
+}
+
+/**
+ * probes stap.pass1a, stap.pass1b, stap.pass1.end
+ * @session: the systemtap_session variable s
+ *
+ * pass1a fires just after the call to gettimeofday(), before the
+ * user script is parsed.
+ * pass1b fires just before the library scripts are parsed.
+ * pass1.end fires just before the jump to cleanup if s.last_pass = 1.
+ */
+probe stap.pass1a = process("stap").mark("pass1a__start") {
+ session = $arg1
+}
+probe stap.pass1b = process("stap").mark("pass1b__start") {
+ session = $arg1
+}
+probe stap.pass1.end = process("stap").mark("pass1__end") {
+ session = $arg1
+}
+
+/**
+ * probes stap.pass2, stap.pass2.end
+ * @session: the systemtap_session variable s
+ *
+ * pass2 fires just after the call to gettimeofday(), just before the
+ * call to semantic_pass.
+ * pass2.end fires just before the jump to cleanup if s.last_pass = 2
+ */
+probe stap.pass2 = process("stap").mark("pass2__start") {
+ session = $arg1
+}
+probe stap.pass2.end = process("stap").mark("pass2__end") {
+ session = $arg1
+}
+
+/**
+ * probes stap.pass3, stap.pass3.end
+ * @session: the systemtap_session variable s
+ *
+ * pass3 fires just after the call to gettimeofday(), just before the
+ * call to translate_pass.
+ * pass3.end fires just before the jump to cleanup if s.last_pass = 3
+ */
+probe stap.pass3 = process("stap").mark("pass3__start") {
+ session = $arg1
+}
+probe stap.pass3.end = process("stap").mark("pass3__end") {
+ session = $arg1
+}
+
+/**
+ * probes stap.pass4, stap.pass4.end
+ * @session: the systemtap_session variable s
+ *
+ * pass4 fires just after the call to gettimeofday(), just before the
+ * call to compile_pass.
+ * pass4.end fires just before the jump to cleanup if s.last_pass = 4
+ */
+probe stap.pass4 = process("stap").mark("pass4__start") {
+ session = $arg1
+}
+probe stap.pass4.end = process("stap").mark("pass4__end") {
+ session = $arg1
+}
+
+/**
+ * probes stap.pass5, stap.pass5.end
+ * @session: the systemtap_session variable s
+ *
+ * pass5 fires just after the call to gettimeofday(), just before the
+ * call to run_pass.
+ * pass5.end fires just before the cleanup label
+ */
+probe stap.pass5 = process("stap").mark("pass5__start") {
+ session = $arg1
+}
+probe stap.pass5.end = process("stap").mark("pass5__end") {
+ session = $arg1
+}
+
+/**
+ * probes stap.pass6, stap.pass6.end
+ * @session: the systemtap_session variable s
+ *
+ * pass6 fires just after the cleanup label, essentially the same spot
+ * as pass5.end
+ * pass6.end fires just before main's return.
+ */
+probe stap.pass6 = process("stap").mark("pass6__start") {
+ session = $arg1
+}
+probe stap.pass6.end = process("stap").mark("pass6__end") {
+ session = $arg1
+}
+
+/**
+ * probe stap.cache_clean
+ * @path: the path to the .ko/.c file being removed
+ *
+ * Fires just before the call to unlink the module/source file.
+ */
+probe stap.cache_clean = process("stap").mark("cache__clean") {
+ path = user_string($arg1)
+}
+
+/**
+ * probe stap.cache_add_mod
+ * @source_path: the path the .ko file is coming from (incl filename)
+ * @dest_path: the path the .ko file is going to (incl filename)
+ *
+ * Fires just before the file is actually moved. Note: if moving fails,
+ * cache_add_src and cache_add_nss will not fire.
+ */
+probe stap.cache_add_mod = process("stap").mark("cache__add__module") {
+ source_path = user_string($arg1)
+ dest_path = user_string($arg2)
+}
+
+/**
+ * probe stap.cache_add_src
+ * @source_path: the path the .c file is coming from (incl filename)
+ * @dest_path: the path the .c file is going to (incl filename)
+ *
+ * Fires just before the file is actually moved. Note: if moving the
+ * kernel module fails, this probe will not fire.
+ */
+probe stap.cache_add_src = process("stap").mark("cache__add__source") {
+ source_path = user_string($arg1)
+ dest_path = user_string($arg2)
+}
+
+/**
+ * probe stap.cache_add_nss
+ * @source_path: the path the .sgn file is coming from (incl filename)
+ * @dest_path: the path the .sgn file is coming from (incl filename)
+ *
+ * Fires just before the file is actually moved. Note: stap must compiled
+ * with NSS support; if moving the kernel module fails, this probe will
+ * not fire.
+ */
+probe stap.cache_add_nss = process("stap").mark("cache__add__nss") ? {
+ source_path = user_string($arg1)
+ dest_path = user_string($arg2)
+}
+
+/**
+ * probe stap.cache_get
+ * @source_path: the path of the .c source file
+ * @module_path: the path of the .ko kernel module file
+ *
+ * Fires just before the return of get_from_cache, when the cache grab
+ * is successful.
+ */
+probe stap.cache_get = process("stap").mark("cache__get") {
+ source_path = user_string($arg1)
+ module_path = user_string($arg2)
+}
+
+/**
+ * probe stap.system
+ * @command: the command string to be run by posix_spawn (as sh -c <str>)
+ *
+ * Fires at the entry of the stap_system command.
+ */
+probe stap.system = process("stap").mark("stap_system__start") {
+ command = user_string($arg1)
+}
+
+/**
+ * probe stap.system.spawn
+ * @ret: the return value from posix_spawn
+ * @pid: the pid of the spawned process
+ *
+ * Fires just after the call to posix_spawn.
+ */
+probe stap.system.spawn = process("stap").mark("stap_system__spawn") {
+ /* posix_spawn(3p) for meaning of ret */
+ ret = $arg1
+ pid = $arg2
+}
+
+/**
+ * probe stap.system.return
+ * @ret: a return code associated with running waitpid on the spawned process;
+ * a non-zero value indicates error
+ *
+ * Fires just before the return of the stap_system function, after waitpid.
+ */
+probe stap.system.return = process("stap").mark("stap_system__complete") {
+ ret = $arg1
+}
+
+/**
+ * probe staprun.insert_module
+ * @path: the full path to the .ko kernel module about to be inserted
+ *
+ * Fires just before the call to insert the module.
+ */
+probe staprun.insert_module = process("staprun").mark("insert__module") {
+ path = user_string($arg1)
+}
+
+/**
+ * probe staprun.remove_module
+ * @name: the stap module name to be removed (without the .ko extension)
+ *
+ * Fires just before the call to remove the module.
+ */
+probe staprun.remove_module = process("staprun").mark("remove__module") {
+ name = user_string($arg1)
+}
+
+/**
+ * probe staprun.send_control_message
+ * @type: type of message being send; defined in runtime/transport/transport_msgs.h
+ * @data: a ptr to a binary blob of data sent as the control message
+ * @len: the length (in bytes) of the data blob
+ *
+ * Fires at the beginning of the send_request function.
+ */
+probe staprun.send_control_message = process("staprun").mark("send__ctlmsg") {
+ type = $arg1
+ data = $arg2
+ len = $arg3
+}
+
+/**
+ * probe stapio.receive_control_message
+ * @type: type of message being send; defined in runtime/transport/transport_msgs.h
+ * @data: a ptr to a binary blob of data sent as the control message
+ * @len: the length (in bytes) of the data blob
+ *
+ * Fires just after a message was receieved and before it's processed.
+ */
+/*
+ *** Due to stapio not being in a user's PATH and the build environment of ***
+ *** stap, there is no immediate 'good' way to insert the correct path here ***
+ *** so comment out this probe. Note however, the static marker is still ***
+ *** present in source. ***
+probe stapio.receive_control_message = process("@libexecdir@/systemtap/stapio").mark("recv__ctlmsg") {
+ type = $arg1
+ data = $arg2
+ len = $arg3
+}
+*/
diff --git a/tapsets.cxx b/tapsets.cxx
index c8bc4d35..b1ca2998 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -290,8 +290,10 @@ symbol_table
void add_symbol(const char *name, bool weak, Dwarf_Addr addr,
Dwarf_Addr *high_addr);
enum info_status read_symbols(FILE *f, const string& path);
- enum info_status read_from_elf_file(const string& path);
- enum info_status read_from_text_file(const string& path);
+ enum info_status read_from_elf_file(const string& path,
+ const systemtap_session &sess);
+ enum info_status read_from_text_file(const string& path,
+ const systemtap_session &sess);
enum info_status get_from_elf();
void prepare_section_rejection(Dwfl_Module *mod);
bool reject_section(GElf_Word section);
@@ -351,6 +353,10 @@ struct dwarf_derived_probe: public derived_probe
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.
static void register_statement_variants(match_node * root,
dwarf_builder * dw,
@@ -393,6 +399,10 @@ struct uprobe_derived_probe: public derived_probe
Dwarf_Addr addr,
bool return_p);
+ 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);
};
@@ -811,10 +821,11 @@ dwarf_query::query_module_symtab()
fi = sym_table->get_func_containing_address(addr);
if (!fi)
{
- cerr << "Warning: address "
- << hex << addr << dec
- << " out of range for module "
- << dw.module_name;
+ if (! sess.suppress_warnings)
+ cerr << "Warning: address "
+ << hex << addr << dec
+ << " out of range for module "
+ << dw.module_name;
return;
}
if (!null_die(&fi->die))
@@ -823,10 +834,11 @@ dwarf_query::query_module_symtab()
// the indicated function, but query_module_dwarf() didn't
// match addr to any compilation unit, so addr must be
// above that cu's address range.
- cerr << "Warning: address "
- << hex << addr << dec
- << " maps to no known compilation unit in module "
- << dw.module_name;
+ if (! sess.suppress_warnings)
+ cerr << "Warning: address "
+ << hex << addr << dec
+ << " maps to no known compilation unit in module "
+ << dw.module_name;
return;
}
query_func_info(fi->addr, *fi, this);
@@ -1408,6 +1420,9 @@ query_cu (Dwarf_Die * cudie, void * arg)
<< " does not match the beginning of a statement";
if (address_line)
msg << " (try 0x" << hex << lineaddr << ")";
+ else
+ msg << " (no line info found for '" << q->dw.cu_name
+ << "', in module '" << q->dw.module_name << "')";
if (! q->sess.guru_mode)
throw semantic_error(msg.str());
else if (! q->sess.suppress_warnings)
@@ -1699,6 +1714,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor
dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a):
q(q), scope_die(sd), addr(a), add_block(NULL), add_probe(NULL), visited(false) {}
+ void visit_target_symbol_saved_return (target_symbol* e);
+ void visit_target_symbol_context (target_symbol* e);
void visit_target_symbol (target_symbol* e);
void visit_cast_op (cast_op* e);
};
@@ -1758,415 +1775,432 @@ var_expanding_visitor::visit_assignment (assignment* e)
void
-dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
-{
- assert(e->base_name.size() > 0 && e->base_name[0] == '$');
- visited = true;
-
- bool lvalue = is_active_lvalue(e);
- if (lvalue && !q.sess.guru_mode)
- throw semantic_error("write to target variable not permitted", e->tok);
-
- // See if we need to generate a new probe to save/access function
- // parameters from a return probe. PR 1382.
- if (q.has_return
- && e->base_name != "$return" // not the special return-value variable handled below
- && e->base_name != "$$return") // nor the other special variable handled below
+dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e)
+{
+ // Get the full name of the target symbol.
+ stringstream ts_name_stream;
+ e->print(ts_name_stream);
+ string ts_name = ts_name_stream.str();
+
+ // Check and make sure we haven't already seen this target
+ // variable in this return probe. If we have, just return our
+ // last replacement.
+ map<string, symbol *>::iterator i = return_ts_map.find(ts_name);
+ if (i != return_ts_map.end())
{
- if (lvalue)
- throw semantic_error("write to target variable not permitted in .return probes", e->tok);
-
- // Get the full name of the target symbol.
- stringstream ts_name_stream;
- e->print(ts_name_stream);
- string ts_name = ts_name_stream.str();
-
- // Check and make sure we haven't already seen this target
- // variable in this return probe. If we have, just return our
- // last replacement.
- map<string, symbol *>::iterator i = return_ts_map.find(ts_name);
- if (i != return_ts_map.end())
- {
- provide (i->second);
- return;
- }
-
- // We've got to do several things here to handle target
- // variables in return probes.
+ provide (i->second);
+ return;
+ }
- // (1) Synthesize two global arrays. One is the cache of the
- // target variable and the other contains a thread specific
- // nesting level counter. The arrays will look like
- // this:
- //
- // _dwarf_tvar_{name}_{num}
- // _dwarf_tvar_{name}_{num}_ctr
+ // We've got to do several things here to handle target
+ // variables in return probes.
- string aname = (string("_dwarf_tvar_")
- + e->base_name.substr(1)
- + "_" + lex_cast<string>(tick++));
- vardecl* vd = new vardecl;
- vd->name = aname;
- vd->tok = e->tok;
- q.sess.globals.push_back (vd);
+ // (1) Synthesize two global arrays. One is the cache of the
+ // target variable and the other contains a thread specific
+ // nesting level counter. The arrays will look like
+ // this:
+ //
+ // _dwarf_tvar_{name}_{num}
+ // _dwarf_tvar_{name}_{num}_ctr
+
+ string aname = (string("_dwarf_tvar_")
+ + e->base_name.substr(1)
+ + "_" + lex_cast<string>(tick++));
+ vardecl* vd = new vardecl;
+ vd->name = aname;
+ vd->tok = e->tok;
+ q.sess.globals.push_back (vd);
+
+ string ctrname = aname + "_ctr";
+ vd = new vardecl;
+ vd->name = ctrname;
+ vd->tok = e->tok;
+ q.sess.globals.push_back (vd);
+
+ // (2) Create a new code block we're going to insert at the
+ // beginning of this probe to get the cached value into a
+ // temporary variable. We'll replace the target variable
+ // reference with the temporary variable reference. The code
+ // will look like this:
+ //
+ // _dwarf_tvar_tid = tid()
+ // _dwarf_tvar_{name}_{num}_tmp
+ // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+ // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
+ // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
+ // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
+
+ // (2a) Synthesize the tid temporary expression, which will look
+ // like this:
+ //
+ // _dwarf_tvar_tid = tid()
+ symbol* tidsym = new symbol;
+ tidsym->name = string("_dwarf_tvar_tid");
+ tidsym->tok = e->tok;
- string ctrname = aname + "_ctr";
- vd = new vardecl;
- vd->name = ctrname;
- vd->tok = e->tok;
- q.sess.globals.push_back (vd);
-
- // (2) Create a new code block we're going to insert at the
- // beginning of this probe to get the cached value into a
- // temporary variable. We'll replace the target variable
- // reference with the temporary variable reference. The code
- // will look like this:
- //
- // _dwarf_tvar_tid = tid()
- // _dwarf_tvar_{name}_{num}_tmp
- // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
- // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
- // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
- // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
-
- // (2a) Synthesize the tid temporary expression, which will look
- // like this:
- //
- // _dwarf_tvar_tid = tid()
- symbol* tidsym = new symbol;
- tidsym->name = string("_dwarf_tvar_tid");
- tidsym->tok = e->tok;
-
- if (add_block == NULL)
- {
- add_block = new block;
- add_block->tok = e->tok;
-
- // Synthesize a functioncall to grab the thread id.
- functioncall* fc = new functioncall;
- fc->tok = e->tok;
- fc->function = string("tid");
-
- // Assign the tid to '_dwarf_tvar_tid'.
- assignment* a = new assignment;
- a->tok = e->tok;
- a->op = "=";
- a->left = tidsym;
- a->right = fc;
-
- expr_statement* es = new expr_statement;
- es->tok = e->tok;
- es->value = a;
- add_block->statements.push_back (es);
- }
+ if (add_block == NULL)
+ {
+ add_block = new block;
+ add_block->tok = e->tok;
- // (2b) Synthesize an array reference and assign it to a
- // temporary variable (that we'll use as replacement for the
- // target variable reference). It will look like this:
- //
- // _dwarf_tvar_{name}_{num}_tmp
- // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
-
- arrayindex* ai_tvar_base = new arrayindex;
- ai_tvar_base->tok = e->tok;
-
- symbol* sym = new symbol;
- sym->name = aname;
- sym->tok = e->tok;
- ai_tvar_base->base = sym;
-
- ai_tvar_base->indexes.push_back(tidsym);
-
- // We need to create a copy of the array index in its current
- // state so we can have 2 variants of it (the original and one
- // that post-decrements the second index).
- arrayindex* ai_tvar = new arrayindex;
- arrayindex* ai_tvar_postdec = new arrayindex;
- *ai_tvar = *ai_tvar_base;
- *ai_tvar_postdec = *ai_tvar_base;
-
- // Synthesize the
- // "_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]" used as the
- // second index into the array.
- arrayindex* ai_ctr = new arrayindex;
- ai_ctr->tok = e->tok;
-
- sym = new symbol;
- sym->name = ctrname;
- sym->tok = e->tok;
- ai_ctr->base = sym;
- ai_ctr->indexes.push_back(tidsym);
- ai_tvar->indexes.push_back(ai_ctr);
-
- symbol* tmpsym = new symbol;
- tmpsym->name = aname + "_tmp";
- tmpsym->tok = e->tok;
+ // Synthesize a functioncall to grab the thread id.
+ functioncall* fc = new functioncall;
+ fc->tok = e->tok;
+ fc->function = string("tid");
+ // Assign the tid to '_dwarf_tvar_tid'.
assignment* a = new assignment;
a->tok = e->tok;
a->op = "=";
- a->left = tmpsym;
- a->right = ai_tvar;
+ a->left = tidsym;
+ a->right = fc;
expr_statement* es = new expr_statement;
es->tok = e->tok;
es->value = a;
-
add_block->statements.push_back (es);
+ }
- // (2c) Add a post-decrement to the second array index and
- // delete the array value. It will look like this:
- //
- // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
-
- post_crement* pc = new post_crement;
- pc->tok = e->tok;
- pc->op = "--";
- pc->operand = ai_ctr;
- ai_tvar_postdec->indexes.push_back(pc);
-
- delete_statement* ds = new delete_statement;
- ds->tok = e->tok;
- ds->value = ai_tvar_postdec;
-
- add_block->statements.push_back (ds);
-
- // (2d) Delete the counter value if it is 0. It will look like
- // this:
- // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
- // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
-
- ds = new delete_statement;
- ds->tok = e->tok;
- ds->value = ai_ctr;
-
- unary_expression *ue = new unary_expression;
- ue->tok = e->tok;
- ue->op = "!";
- ue->operand = ai_ctr;
-
- if_statement *ifs = new if_statement;
- ifs->tok = e->tok;
- ifs->condition = ue;
- ifs->thenblock = ds;
- ifs->elseblock = NULL;
-
- add_block->statements.push_back (ifs);
-
- // (3) We need an entry probe that saves the value for us in the
- // global array we created. Create the entry probe, which will
- // look like this:
- //
- // probe kernel.function("{function}") {
- // _dwarf_tvar_tid = tid()
- // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
- // = ${param}
- // }
-
- if (add_probe == NULL)
+ // (2b) Synthesize an array reference and assign it to a
+ // temporary variable (that we'll use as replacement for the
+ // target variable reference). It will look like this:
+ //
+ // _dwarf_tvar_{name}_{num}_tmp
+ // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+
+ arrayindex* ai_tvar_base = new arrayindex;
+ ai_tvar_base->tok = e->tok;
+
+ symbol* sym = new symbol;
+ sym->name = aname;
+ sym->tok = e->tok;
+ ai_tvar_base->base = sym;
+
+ ai_tvar_base->indexes.push_back(tidsym);
+
+ // We need to create a copy of the array index in its current
+ // state so we can have 2 variants of it (the original and one
+ // that post-decrements the second index).
+ arrayindex* ai_tvar = new arrayindex;
+ arrayindex* ai_tvar_postdec = new arrayindex;
+ *ai_tvar = *ai_tvar_base;
+ *ai_tvar_postdec = *ai_tvar_base;
+
+ // Synthesize the
+ // "_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]" used as the
+ // second index into the array.
+ arrayindex* ai_ctr = new arrayindex;
+ ai_ctr->tok = e->tok;
+
+ sym = new symbol;
+ sym->name = ctrname;
+ sym->tok = e->tok;
+ ai_ctr->base = sym;
+ ai_ctr->indexes.push_back(tidsym);
+ ai_tvar->indexes.push_back(ai_ctr);
+
+ symbol* tmpsym = new symbol;
+ tmpsym->name = aname + "_tmp";
+ tmpsym->tok = e->tok;
+
+ assignment* a = new assignment;
+ a->tok = e->tok;
+ a->op = "=";
+ a->left = tmpsym;
+ a->right = ai_tvar;
+
+ expr_statement* es = new expr_statement;
+ es->tok = e->tok;
+ es->value = a;
+
+ add_block->statements.push_back (es);
+
+ // (2c) Add a post-decrement to the second array index and
+ // delete the array value. It will look like this:
+ //
+ // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
+
+ post_crement* pc = new post_crement;
+ pc->tok = e->tok;
+ pc->op = "--";
+ pc->operand = ai_ctr;
+ ai_tvar_postdec->indexes.push_back(pc);
+
+ delete_statement* ds = new delete_statement;
+ ds->tok = e->tok;
+ ds->value = ai_tvar_postdec;
+
+ add_block->statements.push_back (ds);
+
+ // (2d) Delete the counter value if it is 0. It will look like
+ // this:
+ // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
+ // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
+
+ ds = new delete_statement;
+ ds->tok = e->tok;
+ ds->value = ai_ctr;
+
+ unary_expression *ue = new unary_expression;
+ ue->tok = e->tok;
+ ue->op = "!";
+ ue->operand = ai_ctr;
+
+ if_statement *ifs = new if_statement;
+ ifs->tok = e->tok;
+ ifs->condition = ue;
+ ifs->thenblock = ds;
+ ifs->elseblock = NULL;
+
+ add_block->statements.push_back (ifs);
+
+ // (3) We need an entry probe that saves the value for us in the
+ // global array we created. Create the entry probe, which will
+ // look like this:
+ //
+ // probe kernel.function("{function}") {
+ // _dwarf_tvar_tid = tid()
+ // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+ // = ${param}
+ // }
+
+ if (add_probe == NULL)
+ {
+ add_probe = new probe;
+ add_probe->tok = e->tok;
+
+ // We need the name of the current probe point, minus the
+ // ".return" (or anything after it, such as ".maxactive(N)").
+ // Create a new probe point, copying all the components,
+ // stopping when we see the ".return" component.
+ probe_point* pp = new probe_point;
+ for (unsigned c = 0; c < q.base_loc->components.size(); c++)
{
- add_probe = new probe;
- add_probe->tok = e->tok;
-
- // We need the name of the current probe point, minus the
- // ".return" (or anything after it, such as ".maxactive(N)").
- // Create a new probe point, copying all the components,
- // stopping when we see the ".return" component.
- probe_point* pp = new probe_point;
- for (unsigned c = 0; c < q.base_loc->components.size(); c++)
- {
- if (q.base_loc->components[c]->functor == "return")
- break;
- else
- pp->components.push_back(q.base_loc->components[c]);
- }
- pp->tok = e->tok;
- pp->optional = q.base_loc->optional;
- add_probe->locations.push_back(pp);
-
- add_probe->body = new block;
- add_probe->body->tok = e->tok;
-
- // Synthesize a functioncall to grab the thread id.
- functioncall* fc = new functioncall;
- fc->tok = e->tok;
- fc->function = string("tid");
-
- // Assign the tid to '_dwarf_tvar_tid'.
- assignment* a = new assignment;
- a->tok = e->tok;
- a->op = "=";
- a->left = tidsym;
- a->right = fc;
-
- expr_statement* es = new expr_statement;
- es->tok = e->tok;
- es->value = a;
- add_probe->body = new block(add_probe->body, es);
-
- vardecl* vd = new vardecl;
- vd->tok = e->tok;
- vd->name = tidsym->name;
- vd->type = pe_long;
- vd->set_arity(0);
- add_probe->locals.push_back(vd);
- }
+ if (q.base_loc->components[c]->functor == "return")
+ break;
+ else
+ pp->components.push_back(q.base_loc->components[c]);
+ }
+ pp->tok = e->tok;
+ pp->optional = q.base_loc->optional;
+ add_probe->locations.push_back(pp);
- // Save the value, like this:
- // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
- // = ${param}
- arrayindex* ai_tvar_preinc = new arrayindex;
- *ai_tvar_preinc = *ai_tvar_base;
+ add_probe->body = new block;
+ add_probe->body->tok = e->tok;
- pre_crement* preinc = new pre_crement;
- preinc->tok = e->tok;
- preinc->op = "++";
- preinc->operand = ai_ctr;
- ai_tvar_preinc->indexes.push_back(preinc);
+ // Synthesize a functioncall to grab the thread id.
+ functioncall* fc = new functioncall;
+ fc->tok = e->tok;
+ fc->function = string("tid");
- a = new assignment;
+ // Assign the tid to '_dwarf_tvar_tid'.
+ assignment* a = new assignment;
a->tok = e->tok;
a->op = "=";
- a->left = ai_tvar_preinc;
- a->right = e;
+ a->left = tidsym;
+ a->right = fc;
- es = new expr_statement;
+ expr_statement* es = new expr_statement;
es->tok = e->tok;
es->value = a;
-
add_probe->body = new block(add_probe->body, es);
- // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to
- // our parent so it can be used as a substitute for the target
- // symbol.
- provide (tmpsym);
-
- // (5) Remember this replacement since we might be able to reuse
- // it later if the same return probe references this target
- // symbol again.
- return_ts_map[ts_name] = tmpsym;
- return;
+ vardecl* vd = new vardecl;
+ vd->tok = e->tok;
+ vd->name = tidsym->name;
+ vd->type = pe_long;
+ vd->set_arity(0);
+ add_probe->locals.push_back(vd);
}
- if (e->base_name == "$$vars"
- || e->base_name == "$$parms"
- || e->base_name == "$$locals"
- || (q.has_return && (e->base_name == "$$return")))
- {
- Dwarf_Die *scopes;
- if (dwarf_getscopes_die (scope_die, &scopes) == 0)
- return;
-
- if (e->addressof)
- throw semantic_error("cannot take address of context variable", e->tok);
-
- target_symbol *tsym = new target_symbol;
- print_format* pf = new print_format;
-
- // Convert $$parms to sprintf of a list of parms and active local vars
- // which we recursively evaluate
-
- // NB: we synthesize a new token here rather than reusing
- // e->tok, because print_format::print likes to use
- // its tok->content.
- token* pf_tok = new token;
- pf_tok->location = e->tok->location;
- pf_tok->type = tok_identifier;
- pf_tok->content = "sprint";
+ // Save the value, like this:
+ // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+ // = ${param}
+ arrayindex* ai_tvar_preinc = new arrayindex;
+ *ai_tvar_preinc = *ai_tvar_base;
+
+ pre_crement* preinc = new pre_crement;
+ preinc->tok = e->tok;
+ preinc->op = "++";
+ preinc->operand = ai_ctr;
+ ai_tvar_preinc->indexes.push_back(preinc);
+
+ a = new assignment;
+ a->tok = e->tok;
+ a->op = "=";
+ a->left = ai_tvar_preinc;
+ a->right = e;
+
+ es = new expr_statement;
+ es->tok = e->tok;
+ es->value = a;
+
+ add_probe->body = new block(add_probe->body, es);
+
+ // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to
+ // our parent so it can be used as a substitute for the target
+ // symbol.
+ provide (tmpsym);
+
+ // (5) Remember this replacement since we might be able to reuse
+ // it later if the same return probe references this target
+ // symbol again.
+ return_ts_map[ts_name] = tmpsym;
+}
- pf->tok = pf_tok;
- pf->print_to_stream = false;
- pf->print_with_format = true;
- pf->print_with_delim = false;
- pf->print_with_newline = false;
- pf->print_char = false;
- if (q.has_return && (e->base_name == "$$return"))
+void
+dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
+{
+ Dwarf_Die *scopes;
+ if (dwarf_getscopes_die (scope_die, &scopes) == 0)
+ return;
+ auto_free free_scopes(scopes);
+
+ target_symbol *tsym = new target_symbol;
+ print_format* pf = new print_format;
+
+ // Convert $$parms to sprintf of a list of parms and active local vars
+ // which we recursively evaluate
+
+ // NB: we synthesize a new token here rather than reusing
+ // e->tok, because print_format::print likes to use
+ // its tok->content.
+ token* pf_tok = new token;
+ pf_tok->location = e->tok->location;
+ pf_tok->type = tok_identifier;
+ pf_tok->content = "sprint";
+
+ pf->tok = pf_tok;
+ pf->print_to_stream = false;
+ pf->print_with_format = true;
+ pf->print_with_delim = false;
+ pf->print_with_newline = false;
+ pf->print_char = false;
+
+ if (q.has_return && (e->base_name == "$$return"))
+ {
+ tsym->tok = e->tok;
+ tsym->base_name = "$return";
+
+ // Ignore any variable that isn't accessible.
+ tsym->saved_conversion_error = 0;
+ expression *texp = tsym;
+ replace (texp); // NB: throws nothing ...
+ if (tsym->saved_conversion_error) // ... but this is how we know it happened.
{
- tsym->tok = e->tok;
- tsym->base_name = "$return";
-
- // Ignore any variable that isn't accessible.
- tsym->saved_conversion_error = 0;
- expression *texp = tsym;
- texp = require (texp); // NB: throws nothing ...
- if (tsym->saved_conversion_error) // ... but this is how we know it happened.
- {
- }
- else
- {
- pf->raw_components += "return";
- pf->raw_components += "=%#x ";
- pf->args.push_back(texp);
- }
}
else
{
- // non-.return probe: support $$parms, $$vars, $$locals
- Dwarf_Die result;
- if (dwarf_child (&scopes[0], &result) == 0)
- do
+ pf->raw_components += "return";
+ pf->raw_components += "=%#x ";
+ pf->args.push_back(texp);
+ }
+ }
+ else
+ {
+ // non-.return probe: support $$parms, $$vars, $$locals
+ Dwarf_Die result;
+ if (dwarf_child (&scopes[0], &result) == 0)
+ do
+ {
+ switch (dwarf_tag (&result))
{
- switch (dwarf_tag (&result))
- {
- case DW_TAG_variable:
- if (e->base_name == "$$parms")
- continue;
- break;
- case DW_TAG_formal_parameter:
- if (e->base_name == "$$locals")
- continue;
- break;
-
- default:
- continue;
- }
+ case DW_TAG_variable:
+ if (e->base_name == "$$parms")
+ continue;
+ break;
+ case DW_TAG_formal_parameter:
+ if (e->base_name == "$$locals")
+ continue;
+ break;
+
+ default:
+ continue;
+ }
- const char *diename = dwarf_diename (&result);
- if (! diename) continue;
+ const char *diename = dwarf_diename (&result);
+ if (! diename) continue;
- tsym->tok = e->tok;
- tsym->base_name = "$";
- tsym->base_name += diename;
+ tsym->tok = e->tok;
+ tsym->base_name = "$";
+ tsym->base_name += diename;
- // Ignore any variable that isn't accessible.
- tsym->saved_conversion_error = 0;
- expression *texp = tsym;
- texp = require (texp); // NB: throws nothing ...
- if (tsym->saved_conversion_error) // ... but this is how we know it happened.
- {
- if (q.sess.verbose>2)
- {
- for (semantic_error *c = tsym->saved_conversion_error;
- c != 0;
- c = c->chain) {
- clog << "variable location problem: " << c->what() << endl;
- }
- }
-
- pf->raw_components += diename;
- pf->raw_components += "=? ";
- }
- else
+ // Ignore any variable that isn't accessible.
+ tsym->saved_conversion_error = 0;
+ expression *texp = tsym;
+ replace (texp); // NB: throws nothing ...
+ if (tsym->saved_conversion_error) // ... but this is how we know it happened.
+ {
+ if (q.sess.verbose>2)
{
- pf->raw_components += diename;
- pf->raw_components += "=%#x ";
- pf->args.push_back(texp);
+ for (semantic_error *c = tsym->saved_conversion_error;
+ c != 0;
+ c = c->chain) {
+ clog << "variable location problem: " << c->what() << endl;
+ }
}
+
+ pf->raw_components += diename;
+ pf->raw_components += "=? ";
}
- while (dwarf_siblingof (&result, &result) == 0);
- }
+ else
+ {
+ pf->raw_components += diename;
+ pf->raw_components += "=%#x ";
+ pf->args.push_back(texp);
+ }
+ }
+ while (dwarf_siblingof (&result, &result) == 0);
+ }
- pf->components = print_format::string_to_components(pf->raw_components);
- provide (pf);
+ pf->components = print_format::string_to_components(pf->raw_components);
+ provide (pf);
+}
+
+void
+dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
+{
+ assert(e->base_name.size() > 0 && e->base_name[0] == '$');
+ visited = true;
+
+ bool lvalue = is_active_lvalue(e);
+ if (lvalue && !q.sess.guru_mode)
+ throw semantic_error("write to target variable not permitted", e->tok);
+
+ // See if we need to generate a new probe to save/access function
+ // parameters from a return probe. PR 1382.
+ if (q.has_return
+ && e->base_name != "$return" // not the special return-value variable handled below
+ && e->base_name != "$$return") // nor the other special variable handled below
+ {
+ if (lvalue)
+ throw semantic_error("write to target variable not permitted in .return probes", e->tok);
+
+ visit_target_symbol_saved_return(e);
+ return;
+ }
+
+ if (e->base_name == "$$vars"
+ || e->base_name == "$$parms"
+ || e->base_name == "$$locals"
+ || (q.has_return && (e->base_name == "$$return")))
+ {
+ if (lvalue)
+ throw semantic_error("cannot write to context variable", e->tok);
+
+ if (e->addressof)
+ throw semantic_error("cannot take address of context variable", e->tok);
+
+ visit_target_symbol_context(e);
return;
}
@@ -2213,7 +2247,6 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
// quietly.
provide (e);
semantic_error* saveme = new semantic_error (er); // copy it
- saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines
// NB: we can have multiple errors, since a $target variable
// may be expanded in several different contexts:
// function ("*") { $var }
@@ -2238,6 +2271,18 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
fdecl->name = fname;
fdecl->body = ec;
+
+ // Any non-literal indexes need to be passed in too.
+ for (unsigned i = 0; i < e->components.size(); ++i)
+ if (e->components[i].type == target_symbol::comp_expression_array_index)
+ {
+ vardecl *v = new vardecl;
+ v->type = pe_long;
+ v->name = "index" + lex_cast<string>(i);
+ v->tok = e->tok;
+ fdecl->formal_args.push_back(v);
+ }
+
if (lvalue)
{
// Modify the fdecl so it carries a single pe_long formal
@@ -2262,6 +2307,11 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
n->function = fname;
n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
+ // Any non-literal indexes need to be passed in too.
+ for (unsigned i = 0; i < e->components.size(); ++i)
+ if (e->components[i].type == target_symbol::comp_expression_array_index)
+ n->args.push_back(require(e->components[i].expr_index));
+
if (lvalue)
{
// Provide the functioncall to our parent, so that it can be
@@ -2494,6 +2544,17 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
v1->tok = e->tok;
fdecl->formal_args.push_back(v1);
+ // Any non-literal indexes need to be passed in too.
+ for (unsigned i = 0; i < e->components.size(); ++i)
+ if (e->components[i].type == target_symbol::comp_expression_array_index)
+ {
+ vardecl *v = new vardecl;
+ v->type = pe_long;
+ v->name = "index" + lex_cast<string>(i);
+ v->tok = e->tok;
+ fdecl->formal_args.push_back(v);
+ }
+
if (lvalue)
{
// Modify the fdecl so it carries a second pe_long formal
@@ -2522,6 +2583,11 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
n->args.push_back(e->operand);
+ // Any non-literal indexes need to be passed in too.
+ for (unsigned i = 0; i < e->components.size(); ++i)
+ if (e->components[i].type == target_symbol::comp_expression_array_index)
+ n->args.push_back(require(e->components[i].expr_index));
+
if (lvalue)
{
// Provide the functioncall to our parent, so that it can be
@@ -2604,7 +2670,7 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
if (!null_die(scope_die))
{
dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr);
- this->body = v.require (this->body);
+ v.replace (this->body);
this->access_vars = v.visited;
// If during target-variable-expanding the probe, we added a new block
@@ -2622,6 +2688,10 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
}
// 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
@@ -2686,6 +2756,66 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
}
+static bool dwarf_type_name(Dwarf_Die& type_die, string& c_type);
+
+void
+dwarf_derived_probe::saveargs(Dwarf_Die* scope_die)
+{
+ 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_Attribute type_attr;
+ Dwarf_Die type_die;
+
+ if (has_return &&
+ dwarf_attr_integrate (scope_die, DW_AT_type, &type_attr) &&
+ dwarf_formref_die (&type_attr, &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_integrate (&arg, DW_AT_type, &type_attr) ||
+ !dwarf_formref_die (&type_attr, &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
+dwarf_derived_probe::printargs(std::ostream &o) const
+{
+ o << args;
+}
+
+
void
dwarf_derived_probe::register_statement_variants(match_node * root,
dwarf_builder * dw,
@@ -2896,7 +3026,18 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->line() << "];";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
+
+ // 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
+ 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() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";
@@ -2919,7 +3060,18 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
s.op->newline() << "c->pi = inst;"; // for assisting runtime's backtrace logic
+
+ // 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
+ 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() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";
@@ -3166,7 +3318,7 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e)
cast->type = probe_name + "_arg" + lex_cast<string>(argno);
cast->module = process_name;
- provide(cast);
+ cast->visit(this);
}
@@ -3247,7 +3399,7 @@ sdt_query::handle_query_module()
sdt_var_expanding_visitor svv (module_val, probe_name,
probe_arg, have_reg_args,
probe_type == utrace_type);
- new_base->body = svv.require (new_base->body);
+ svv.replace (new_base->body);
unsigned i = results.size();
@@ -3693,7 +3845,8 @@ symbol_table::read_symbols(FILE *f, const string& path)
// that gives us raw addresses -- which we need for modules -- whereas
// nm provides the address relative to the beginning of the section.
enum info_status
-symbol_table::read_from_elf_file(const string &path)
+symbol_table::read_from_elf_file(const string &path,
+ const systemtap_session &sess)
{
FILE *f;
string cmd = string("/usr/bin/nm -n --defined-only ") + path;
@@ -3708,7 +3861,7 @@ symbol_table::read_from_elf_file(const string &path)
enum info_status status = read_symbols(f, path);
if (pclose(f) != 0)
{
- if (status == info_present)
+ if (status == info_present && ! sess.suppress_warnings)
cerr << "Warning: nm cannot read symbol table from " << path;
return info_absent;
}
@@ -3716,13 +3869,15 @@ symbol_table::read_from_elf_file(const string &path)
}
enum info_status
-symbol_table::read_from_text_file(const string& path)
+symbol_table::read_from_text_file(const string& path,
+ const systemtap_session &sess)
{
FILE *f = fopen(path.c_str(), "r");
if (!f)
{
- cerr << "Warning: cannot read symbol table from "
- << path << " -- " << strerror (errno);
+ if (! sess.suppress_warnings)
+ cerr << "Warning: cannot read symbol table from "
+ << path << " -- " << strerror (errno);
return info_absent;
}
enum info_status status = read_symbols(f, path);
@@ -3870,12 +4025,13 @@ module_info::get_symtab(dwarf_query *q)
sym_table = new symbol_table(this);
if (!elf_path.empty())
{
- if (name == TOK_KERNEL && !sess.kernel_symtab_path.empty())
+ if (name == TOK_KERNEL && !sess.kernel_symtab_path.empty()
+ && ! sess.suppress_warnings)
cerr << "Warning: reading symbol table from "
<< elf_path
<< " -- ignoring "
<< sess.kernel_symtab_path
- << endl ;;
+ << endl;
symtab_status = sym_table->get_from_elf();
}
else
@@ -3891,7 +4047,7 @@ module_info::get_symtab(dwarf_query *q)
else
{
symtab_status =
- sym_table->read_from_text_file(sess.kernel_symtab_path);
+ sym_table->read_from_text_file(sess.kernel_symtab_path, sess);
if (symtab_status == info_present)
{
sess.sym_kprobes_text_start =
@@ -4000,7 +4156,7 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function,
if (!null_die(scope_die))
{
dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's!
- this->body = v.require (this->body);
+ 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.
@@ -4018,6 +4174,10 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function,
}
// 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
@@ -4092,6 +4252,67 @@ uprobe_derived_probe::uprobe_derived_probe (probe *base,
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_Attribute type_attr;
+ Dwarf_Die type_die;
+
+ if (return_p &&
+ dwarf_attr_integrate (scope_die, DW_AT_type, &type_attr) &&
+ dwarf_formref_die (&type_attr, &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_integrate (&arg, DW_AT_type, &type_attr) ||
+ !dwarf_formref_die (&type_attr, &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.
@@ -4222,7 +4443,18 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "if (sup->spec_index < 0 ||"
<< "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen
s.op->newline() << "c->regs = regs;";
+
+ // 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
+ 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() << "(*sups->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = uprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline(-1) << "}";
@@ -4234,7 +4466,18 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
<< "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen
// XXX: kretprobes saves "c->pi = inst;" too
s.op->newline() << "c->regs = regs;";
+
+ // 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
+ 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() << "(*sups->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = uprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline(-1) << "}";
@@ -4723,7 +4966,18 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->line() << "];";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
+
+ // 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
+ 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() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";
@@ -4746,7 +5000,18 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "sdp->pp");
s.op->newline() << "c->regs = regs;";
s.op->newline() << "c->pi = inst;"; // for assisting runtime's backtrace logic
+
+ // 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
+ 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() << "(*sdp->ph) (c);";
+ s.op->newline() << "REG_IP(regs) = kprobes_ip;";
+ s.op->newline(-1) << "}";
+
common_probe_entryfn_epilogue (s.op);
s.op->newline() << "return 0;";
s.op->newline(-1) << "}";
@@ -5037,19 +5302,8 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
}
// make sure we're not dereferencing base types
- if (!e->components.empty() && !arg->isptr)
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("tracepoint variable '" + e->base_name
- + "' may not be used as array", e->tok);
- case target_symbol::comp_struct_member:
- throw semantic_error("tracepoint variable '" + e->base_name
- + "' may not be used as a structure", e->tok);
- default:
- throw semantic_error("invalid use of tracepoint variable '"
- + e->base_name + "'", e->tok);
- }
+ if (!arg->isptr)
+ e->assert_no_components("tracepoint");
// we can only write to dereferenced fields, and only if guru mode is on
bool lvalue = is_active_lvalue(e);
@@ -5098,7 +5352,6 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
// up not being referenced after all, so it can be optimized out
// quietly.
semantic_error* saveme = new semantic_error (er); // copy it
- saveme->tok1 = e->tok; // XXX: token not passed to dw code generation routines
// NB: we can have multiple errors, since a target variable
// may be expanded in several different contexts:
// trace ("*") { $foo->bar }
@@ -5115,6 +5368,17 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
v1->tok = e->tok;
fdecl->formal_args.push_back(v1);
+ // Any non-literal indexes need to be passed in too.
+ for (unsigned i = 0; i < e->components.size(); ++i)
+ if (e->components[i].type == target_symbol::comp_expression_array_index)
+ {
+ vardecl *v = new vardecl;
+ v->type = pe_long;
+ v->name = "index" + lex_cast<string>(i);
+ v->tok = e->tok;
+ fdecl->formal_args.push_back(v);
+ }
+
if (lvalue)
{
// Modify the fdecl so it carries a pe_long formal
@@ -5142,10 +5406,16 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
n->function = fname;
n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
- // make the original a bare target symbol for the tracepoint value,
- // which will be passed into the dwarf dereferencing code
- e->components.clear();
- n->args.push_back(require(e));
+ // make a copy of the original as a bare target symbol for the tracepoint
+ // value, which will be passed into the dwarf dereferencing code
+ target_symbol* e2 = deep_copy_visitor::deep_copy(e);
+ e2->components.clear();
+ n->args.push_back(require(e2));
+
+ // Any non-literal indexes need to be passed in too.
+ for (unsigned i = 0; i < e->components.size(); ++i)
+ if (e->components[i].type == target_symbol::comp_expression_array_index)
+ n->args.push_back(require(e->components[i].expr_index));
if (lvalue)
{
@@ -5170,18 +5440,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
if (is_active_lvalue (e))
throw semantic_error("write to tracepoint '" + e->base_name + "' not permitted", e->tok);
- if (!e->components.empty())
- switch (e->components[0].first)
- {
- case target_symbol::comp_literal_array_index:
- throw semantic_error("tracepoint '" + e->base_name + "' may not be used as array",
- e->tok);
- case target_symbol::comp_struct_member:
- throw semantic_error("tracepoint '" + e->base_name + "' may not be used as a structure",
- e->tok);
- default:
- throw semantic_error("invalid tracepoint '" + e->base_name + "' use", e->tok);
- }
+ e->assert_no_components("tracepoint");
if (e->base_name == "$$name")
{
@@ -5287,7 +5546,7 @@ tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s,
// Now expand the local variables in the probe body
tracepoint_var_expanding_visitor v (dw, name, args);
- this->body = v.require (this->body);
+ v.replace (this->body);
if (sess.verbose > 2)
clog << "tracepoint-based " << name << " tracepoint='" << tracepoint_name
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 737849dc..7358bd2c 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -17,8 +18,9 @@
# Makefile.am --- automake input file for systemtap testsuite
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -42,6 +44,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DEJATOOL = $(PACKAGE)
ACLOCAL = @ACLOCAL@
@@ -141,15 +144,15 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
- cd $(srcdir) && $(AUTOMAKE) --foreign \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --foreign Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -165,9 +168,10 @@ $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENC
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(srcdir) && $(AUTOCONF)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
tags: TAGS
TAGS:
@@ -229,6 +233,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -248,6 +253,8 @@ dvi-am:
html: html-am
+html-am:
+
info: info-am
info-am:
@@ -256,18 +263,28 @@ install-data-am:
install-dvi: install-dvi-am
+install-dvi-am:
+
install-exec-am:
install-html: install-html-am
+install-html-am:
+
install-info: install-info-am
+install-info-am:
+
install-man:
install-pdf: install-pdf-am
+install-pdf-am:
+
install-ps: install-ps-am
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-am
@@ -290,7 +307,7 @@ ps-am:
uninstall-am:
-.MAKE: install-am install-strip
+.MAKE: check-am install-am install-strip
.PHONY: all all-am all-local am--refresh check check-DEJAGNU check-am \
check-local clean clean-generic clean-local distclean \
@@ -323,6 +340,7 @@ check-local:
installcheck: site.exp
-$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU RUNTESTFLAGS="$(RUNTESTFLAGS) --tool_opts \'install $(TOOL_OPTS)\'"
if test -n "$(DEJAZILLA)"; then mail $(DEJAZILLA) < systemtap.sum; fi
+
# 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/testsuite/aclocal.m4 b/testsuite/aclocal.m4
index a249a8e6..a237cb5a 100644
--- a/testsuite/aclocal.m4
+++ b/testsuite/aclocal.m4
@@ -1,7 +1,7 @@
-# generated automatically by aclocal 1.10.2 -*- Autoconf -*-
+# generated automatically by aclocal 1.11 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -31,10 +31,10 @@ To do so, use the procedure documented by the package, typically `autoreconf'.])
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.10'
+[am__api_version='1.11'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.10.2], [],
+m4_if([$1], [1.11], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -50,7 +50,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.10.2])dnl
+[AM_AUTOMAKE_VERSION([1.11])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@@ -110,14 +110,14 @@ am_aux_dir=`cd $ac_aux_dir && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
-# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 8
+# serial 9
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
@@ -130,6 +130,7 @@ AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
if $2; then
$1_TRUE=
$1_FALSE='#'
@@ -146,13 +147,13 @@ fi])])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2008 Free Software Foundation, Inc.
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 13
+# serial 16
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
@@ -169,7 +170,7 @@ fi])])
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_PREREQ([2.60])dnl
+[AC_PREREQ([2.62])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@@ -220,8 +221,8 @@ AM_MISSING_PROG(AUTOCONF, autoconf)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
AM_MISSING_PROG(AUTOHEADER, autoheader)
AM_MISSING_PROG(MAKEINFO, makeinfo)
-AM_PROG_INSTALL_SH
-AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
@@ -229,24 +230,37 @@ AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
- [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
- [_AM_PROG_TAR([v7])])])
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
- [_AM_DEPENDENCIES(CC)],
- [define([AC_PROG_CC],
- defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
- [_AM_DEPENDENCIES(CXX)],
- [define([AC_PROG_CXX],
- defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
- [_AM_DEPENDENCIES(OBJC)],
- [define([AC_PROG_OBJC],
- defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
])
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
@@ -269,7 +283,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -280,7 +294,14 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
AC_SUBST(install_sh)])
# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
@@ -307,27 +328,38 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
-# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 4
+# serial 5
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well. Anyway, the user
+# can override the default with the --enable/--disable switch.
AC_DEFUN([AM_MAINTAINER_MODE],
-[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
- dnl maintainer-mode is disabled by default
- AC_ARG_ENABLE(maintainer-mode,
-[ --enable-maintainer-mode enable make rules and dependencies not useful
+[m4_case(m4_default([$1], [disable]),
+ [enable], [m4_define([am_maintainer_other], [disable])],
+ [disable], [m4_define([am_maintainer_other], [enable])],
+ [m4_define([am_maintainer_other], [enable])
+ m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+ dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+ AC_ARG_ENABLE([maintainer-mode],
+[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
(and sometimes confusing) to the casual installer],
- USE_MAINTAINER_MODE=$enableval,
- USE_MAINTAINER_MODE=no)
+ [USE_MAINTAINER_MODE=$enableval],
+ [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
AC_MSG_RESULT([$USE_MAINTAINER_MODE])
- AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes])
+ AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
MAINT=$MAINTAINER_MODE_TRUE
- AC_SUBST(MAINT)dnl
+ AC_SUBST([MAINT])dnl
]
)
@@ -335,14 +367,14 @@ AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 5
+# serial 6
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
@@ -359,7 +391,14 @@ AC_SUBST($1)])
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
-test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
@@ -430,14 +469,14 @@ AC_DEFUN([_AM_IF_OPTION],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 4
+# serial 5
# AM_SANITY_CHECK
# ---------------
@@ -446,16 +485,29 @@ AC_DEFUN([AM_SANITY_CHECK],
# Just in case
sleep 1
echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
- set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$[*]" = "X"; then
# -L didn't work.
- set X `ls -t $srcdir/configure conftest.file`
+ set X `ls -t "$srcdir/configure" conftest.file`
fi
rm -f conftest.file
if test "$[*]" != "X $srcdir/configure conftest.file" \
@@ -508,18 +560,25 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 2
+
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
diff --git a/testsuite/configure b/testsuite/configure
index 09db931f..6199a3c9 100755
--- a/testsuite/configure
+++ b/testsuite/configure
@@ -1787,7 +1787,7 @@ ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-am__api_version='1.10'
+am__api_version='1.11'
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
@@ -1887,16 +1887,33 @@ $as_echo_n "checking whether build environment is sane... " >&6; }
# Just in case
sleep 1
echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ { { $as_echo "$as_me:$LINENO: error: unsafe absolute working directory name" >&5
+$as_echo "$as_me: error: unsafe absolute working directory name" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ { { $as_echo "$as_me:$LINENO: error: unsafe srcdir value: \`$srcdir'" >&5
+$as_echo "$as_me: error: unsafe srcdir value: \`$srcdir'" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
- set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$*" = "X"; then
# -L didn't work.
- set X `ls -t $srcdir/configure conftest.file`
+ set X `ls -t "$srcdir/configure" conftest.file`
fi
rm -f conftest.file
if test "$*" != "X $srcdir/configure conftest.file" \
@@ -1940,7 +1957,14 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
-test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
@@ -1950,6 +1974,115 @@ else
$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
fi
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
{ $as_echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
if test -z "$MKDIR_P"; then
@@ -2132,108 +2265,6 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
-install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
-
-# Installed binaries are usually stripped using `strip' when the user
-# run `make install-strip'. However `strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the `STRIP' environment variable to overrule this program.
-if test "$cross_compiling" != no; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_STRIP+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- if test -n "$STRIP"; then
- ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_STRIP="${ac_tool_prefix}strip"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
- { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
-$as_echo "$STRIP" >&6; }
-else
- { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_STRIP"; then
- ac_ct_STRIP=$STRIP
- # Extract the first word of "strip", so it can be a program name with args.
-set dummy strip; ac_word=$2
-{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_STRIP"; then
- ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_STRIP="strip"
- $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
-if test -n "$ac_ct_STRIP"; then
- { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
-$as_echo "$ac_ct_STRIP" >&6; }
-else
- { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_STRIP" = x; then
- STRIP=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- STRIP=$ac_ct_STRIP
- fi
-else
- STRIP="$ac_cv_prog_STRIP"
-fi
-
-fi
-INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
-
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
# Always define AMTAR for backward compatibility.
@@ -2246,6 +2277,7 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
{ $as_echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
# Check whether --enable-maintainer-mode was given.
@@ -2420,6 +2452,7 @@ LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
+
if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
{ { $as_echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
diff --git a/testsuite/semok/bz10475.stp b/testsuite/semok/bz10475.stp
new file mode 100755
index 00000000..ee79b07d
--- /dev/null
+++ b/testsuite/semok/bz10475.stp
@@ -0,0 +1,10 @@
+#! 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")
+{
+ // check array access on a "complex" pointer type
+ println($pathname[0])
+}
diff --git a/testsuite/systemtap.base/bz6905.c b/testsuite/systemtap.base/bz6905.c
new file mode 100644
index 00000000..bb3f524e
--- /dev/null
+++ b/testsuite/systemtap.base/bz6905.c
@@ -0,0 +1,7 @@
+int main()
+{
+ int a;
+
+ a = a + 1;
+ return 0;
+}
diff --git a/testsuite/systemtap.base/bz6905.exp b/testsuite/systemtap.base/bz6905.exp
new file mode 100644
index 00000000..8119159e
--- /dev/null
+++ b/testsuite/systemtap.base/bz6905.exp
@@ -0,0 +1,25 @@
+set test bz6905
+
+catch {exec gcc -g -o $test $srcdir/$subdir/$test.c} err
+if {$err == "" && [file exists $test]} then { pass "$test compile" } else { fail "$test compile" }
+
+if {![utrace_p]} {
+ catch {exec rm -f $test}
+ untested "$test -p2"
+ return
+}
+
+set stapexe [exec /usr/bin/which stap]
+spawn sudo $stapexe -p2 $srcdir/$subdir/$test.stp
+set hint 0
+set probes 0
+expect {
+ -timeout 60
+ -re "# probes" { incr hint; exp_continue }
+ -re {process.*statement.*} { incr probes; exp_continue }
+ timeout { fail "$test (timeout)" }
+ eof { }
+}
+wait
+if { $hint == 1 && $probes > 0 } then { pass "$test -p2" } else { fail "$test -p2 ($probes)" }
+exec rm -f $test
diff --git a/testsuite/systemtap.base/bz6905.stp b/testsuite/systemtap.base/bz6905.stp
new file mode 100644
index 00000000..73c7d50c
--- /dev/null
+++ b/testsuite/systemtap.base/bz6905.stp
@@ -0,0 +1,4 @@
+#! stap -p2
+probe process("./bz6905").statement("main@bz6905.c:*") {
+ printf("ok")
+}
diff --git a/testsuite/systemtap.base/cmd_parse.exp b/testsuite/systemtap.base/cmd_parse.exp
index c6b098a4..b97d9448 100644
--- a/testsuite/systemtap.base/cmd_parse.exp
+++ b/testsuite/systemtap.base/cmd_parse.exp
@@ -116,7 +116,7 @@ wait;close
spawn stap -L syscall.a*
expect {
-timeout 60
- -re {(syscall\.a[_a-zA-Z0-9]*(\ [_a-zA-Z0-9\$]+:(string|long|unknown|stats))*\r\n)+} { pass "cmd_parse13" }
+ -re {(syscall\.a[_a-zA-Z0-9]*(\ [_a-zA-Z0-9\$]+:[^:]+?)+\r\n)+} { pass "cmd_parse13" }
timeout {fail "cmd_parse13: unexpected timeout"}
eof {fail "cmd_parse13: unexpected EOF"}
}
diff --git a/testsuite/systemtap.base/crash.exp b/testsuite/systemtap.base/crash.exp
index 9c3e5e05..59c8dadd 100644
--- a/testsuite/systemtap.base/crash.exp
+++ b/testsuite/systemtap.base/crash.exp
@@ -5,7 +5,7 @@ if {![installtest_p]} { untested $test; return }
if {![file exists $env(CRASH_LIBDIR)/staplog.so]} { untested "$test - no staplog.so"; return }
# Load a test script
-spawn stap $srcdir/$subdir/testlog.stp -m testlog
+spawn stap -e {probe begin {print("HelloWorld\n")}} -m testlog
expect {
-timeout 120
"HelloWorld\r\n" {
diff --git a/testsuite/systemtap.base/pointer_array.stp b/testsuite/systemtap.base/pointer_array.stp
index 1d15ebf4..cd420604 100644
--- a/testsuite/systemtap.base/pointer_array.stp
+++ b/testsuite/systemtap.base/pointer_array.stp
@@ -2,15 +2,8 @@ probe syscall.execve
{
if (pid() == target()) {
println(user_string($argv[0]))
- printf("%c\n", $argv[0][0])
- printf("%c\n", $argv[0][1])
- printf("%c\n", $argv[0][2])
- printf("%c\n", $argv[0][3])
- printf("%c\n", $argv[0][4])
- printf("%c\n", $argv[0][5])
- printf("%c\n", $argv[0][6])
- printf("%c\n", $argv[0][7])
- printf("%c\n", $argv[0][8])
+ for (i=0; i<9; ++i)
+ printf("%c\n", $argv[0][i])
println($argv[0][9])
}
}
diff --git a/testsuite/systemtap.base/utrace_p4.exp b/testsuite/systemtap.base/utrace_p4.exp
index 8d323a8a..c76503cb 100644
--- a/testsuite/systemtap.base/utrace_p4.exp
+++ b/testsuite/systemtap.base/utrace_p4.exp
@@ -10,6 +10,7 @@
set begin_script {"probe process(\"/bin/ls\").begin { print(\"ls begin\") }"}
set end_script {"probe process(\"/bin/ls\").end { print(\"ls end\") }"}
set syscall_script {"probe process(\"/bin/ls\").syscall { printf(\"|%d\", \$syscall) }"}
+set syscall_parms_script {"probe process(\"/bin/ls\").syscall { printf(\"|%s\", \$\$parms) }"}
set syscall_return_script {"probe process(\"/bin/ls\").syscall.return { printf(\"|%d\", \$syscall) }"}
set thread_begin_script {"probe process(\"/bin/ls\").thread.begin { print(\"ls thread.begin\") }"}
set thread_end_script {"probe process(\"/bin/ls\").thread.end { print(\"ls thread.end\") }"}
@@ -18,6 +19,7 @@ set all_begin_script {"probe process.begin { print(\"begin\") }"}
set pid_begin_script {"probe process(123).begin { print(\"123 begin\") }"}
set pid_end_script {"probe process(123).end { print(\"123 end\") }"}
set pid_syscall_script {"probe process(123).syscall { printf(\"|%d\", \$syscall) }"}
+set pid_parms_script {"probe process(123).syscall { printf(\"|%s\", \$\$parms) }"}
set pid_syscall_return_script {"probe process(123).syscall.return { printf(\"|%d\", \$syscall) }"}
set pid_thread_begin_script {"probe process(123).thread.begin { print(\"123 thread.begin\") }"}
set pid_thread_end_script {"probe process(123).thread.end { print(\"123 thread.end\") }"}
@@ -129,3 +131,20 @@ if {![utrace_p]} {
# Try compiling an system-wide begin script
stap_compile $TEST_NAME 1 $all_begin_script
}
+
+set TEST_NAME "UTRACE_P4_08"
+if {![utrace_p]} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling a syscall parms script using a path
+ stap_compile $TEST_NAME 1 $syscall_parms_script
+}
+
+set TEST_NAME "UTRACE_P4_09"
+if {![utrace_p]} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling a syscall parms script using a pid
+ stap_compile $TEST_NAME 1 $pid_parms_script
+}
+
diff --git a/testsuite/systemtap.base/utrace_p5.exp b/testsuite/systemtap.base/utrace_p5.exp
index 3d432dc3..7062bc0d 100644
--- a/testsuite/systemtap.base/utrace_p5.exp
+++ b/testsuite/systemtap.base/utrace_p5.exp
@@ -89,6 +89,18 @@ set bz6841_script {
}
set bz6841_script_output ".+ issues syscall \\d+ times\r\n"
+set syscall_parms_script {
+ global syscall_parms_string
+ probe begin { printf("systemtap starting probe\n") }
+ probe process.syscall { syscall_parms_string = $$parms exit() }
+ probe end { printf("systemtap ending probe\n")
+ printf("%s\n",syscall_parms_string)
+ delete syscall_parms_string
+ }
+}
+set syscall_parms_script_output "(.+arg\[1-6\]=0x\[0-9a-f\]+)+\r\n"
+
+
# Set up our own copy of /bin/cat, to make testing for a particular
# executable easy. We can't use 'ln' here, since we might be creating
# a cross-device link. We can't use 'ln -s' here, since the kernel
@@ -202,5 +214,15 @@ if {![utrace_p]} {
-e $bz6841_script
}
+set TEST_NAME "UTRACE_P5_08"
+if {![utrace_p]} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} elseif {![installtest_p]} {
+ untested "$TEST_NAME"
+} else {
+ set script [format $syscall_parms_script "%s"]
+ stap_run $TEST_NAME no_load $syscall_parms_script_output -e $script
+}
+
# Cleanup
exec rm -f $exepath $multi_exepath
diff --git a/testsuite/systemtap.context/uprobe_stmt_num.c b/testsuite/systemtap.context/uprobe_stmt_num.c
new file mode 100644
index 00000000..887e572a
--- /dev/null
+++ b/testsuite/systemtap.context/uprobe_stmt_num.c
@@ -0,0 +1,20 @@
+static int
+func2 (int x, int y)
+{
+ return x + y;
+}
+
+static int
+func (int arg)
+{
+ int x = 16;
+ int y = arg - x;
+ int z = func2(x, y);
+ return x + y + z;
+}
+
+int
+main (int argc, char *argv[], char *envp[])
+{
+ return func(42);
+}
diff --git a/testsuite/systemtap.context/uprobe_stmt_num.exp b/testsuite/systemtap.context/uprobe_stmt_num.exp
new file mode 100644
index 00000000..fbb1126a
--- /dev/null
+++ b/testsuite/systemtap.context/uprobe_stmt_num.exp
@@ -0,0 +1,78 @@
+# Tests whether we can put statement probes on all lines of a function,
+# even without debuginfo around (in guru mode currently). PR10454.
+
+set test "uprobe_stmt_num"
+
+# Only run on make installcheck and utrace present.
+if {! [installtest_p]} { untested "$test"; return }
+if {! [utrace_p]} { untested "$test"; return }
+
+set testpath "$srcdir/$subdir"
+set testsrc "$testpath/$test.c"
+set testexe "[pwd]/$test"
+# We want debug info and no optimization (every line counts).
+set testflags "additional_flags=-g additional_flags=-O0"
+set teststp "$testpath/$test.stp"
+
+set res [target_compile $testsrc $testexe executable $testflags]
+if { $res != "" } {
+ verbose "target_compile failed: $res" 2
+ fail "unable to compile $testsrc"
+ return
+}
+
+set cmd [concat stap -c $testexe $teststp]
+send_log "cmd: $cmd\n"
+catch {eval exec $cmd} output
+send_log "cmd output: $output\n"
+
+# There should be at least 6 lines probes
+# Function entry, 4 actual source lines and function exit.
+set output_lines [split $output "\n"]
+set lines [llength $output_lines]
+if { $lines >= 6 } {
+ pass "$test-run-one"
+} else {
+ fail "$test-run-one ($lines)"
+}
+
+# Expect the same output for next runs
+set ::result_string $output
+
+# Sanity check, just run again...
+stap_run3 $test-run-two $testpath/$test.stp -c $testexe
+
+# create a script based on the given statements,
+# probe all of them individually.
+set fp [open $test-run-statements.stp "w"]
+foreach line $output_lines {
+ puts $fp "probe process(\"uprobe_stmt_num\").statement($line)"
+ puts $fp "{"
+ puts $fp " printf(\"0x%x\\n\", uaddr());"
+ puts $fp "}"
+}
+close $fp
+stap_run3 $test-run-statements $test-run-statements.stp -c $testexe
+
+# Now strip away the line info and try again (with -g).
+set strip_cmd [list "objcopy" "-R" ".debug_line"]
+lappend strip_cmd "$testexe"
+send_log "Executing: $strip_cmd\n"
+eval exec $strip_cmd
+
+stap_run3 $test-run-statements-nolines -w -g $test-run-statements.stp -c $testexe
+
+# XXX Last test still fails. PR10454.
+return
+
+# Now strip away all debuginfo. Since the script doesn't need any it
+# should still work.
+set strip_cmd [list "strip" "-g"]
+lappend strip_cmd "$testexe"
+send_log "Executing: $strip_cmd\n"
+eval exec $strip_cmd
+
+stap_run3 $test-run-statements-nodebuginfo -w -g $test-run-statements.stp -c $testexe
+
+# cleanup
+eval exec rm $testexe $test-run-statements.stp
diff --git a/testsuite/systemtap.context/uprobe_stmt_num.stp b/testsuite/systemtap.context/uprobe_stmt_num.stp
new file mode 100644
index 00000000..c2e8d5ba
--- /dev/null
+++ b/testsuite/systemtap.context/uprobe_stmt_num.stp
@@ -0,0 +1,4 @@
+probe process("uprobe_stmt_num").statement("func@uprobe_stmt_num.c:*")
+{
+ printf("0x%x\n", uaddr());
+}
diff --git a/testsuite/systemtap.examples/general/grapher.stp b/testsuite/systemtap.examples/general/grapher.stp
index 4f326ec1..9079cb40 100755..100644
--- a/testsuite/systemtap.examples/general/grapher.stp
+++ b/testsuite/systemtap.examples/general/grapher.stp
@@ -2,11 +2,13 @@
probe begin
{
-printf ("%%Title:CPU utilization\n");
-printf ("%%XAxisTitle:Time");
-printf ("%%YAxisTitle:Percent");
-printf ("%%DataSet:cpu 100 00ff00 bar");
-printf ("%%DataSet:kbd 100 ff0000 dot");
+printf ("%%DataSet:cpu 100 00ff00 bar\n");
+printf ("%%DataSet:kbd 75 ff0000 discreet\n");
+printf ("%%DataSet:pty 50 0000ff discreet\n");
+printf ("cpu %%Title:CPU utilization\n");
+printf ("cpu %%XAxisTitle:Time\n");
+printf ("cpu %%YAxisTitle:Percent\n");
+
}
# CPU utilization
@@ -28,5 +30,14 @@ probe timer.ms(100) { # collect utilization percentages frequently
}
probe kernel.function("kbd_event") {
- printf("kbd %d %d\n", gettimeofday_ms(), 75)
+ if ($event_type == 1 && $value)
+ printf("kbd %d %d\n", gettimeofday_ms(), $event_code)
+}
+
+probe kernel.function("pty_write") {
+ if (count > 0)
+ printf("pty %d %.5s\n", gettimeofday_ms(), buf)
}
+
+
+
diff --git a/testsuite/systemtap.exelib/ustack.tcl b/testsuite/systemtap.exelib/ustack.tcl
index b70b8334..a670213a 100644
--- a/testsuite/systemtap.exelib/ustack.tcl
+++ b/testsuite/systemtap.exelib/ustack.tcl
@@ -1,12 +1,3 @@
-set ::result_string {exe: main=main
-exe: main_func=main_func
-exe: main_func=main_func
-exe: main_func=main_func
-lib: lib_main=lib_main
-lib: lib_func=lib_func
-lib: lib_func=lib_func
- lib: lib_func=lib_func}
-
# Only run on make installcheck
if {! [installtest_p]} { untested "ustack-$testname"; return }
if {! [utrace_p]} { untested "ustack-$testname"; return }
diff --git a/translate.cxx b/translate.cxx
index ddd96938..4a6a10b5 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -3516,7 +3516,7 @@ c_unparser::visit_target_symbol (target_symbol* e)
if (!e->probe_context_var.empty())
o->line() << "l->" << e->probe_context_var;
else
- throw semantic_error("cannot translate general cast expression", e->tok);
+ throw semantic_error("cannot translate general target expression", e->tok);
}
@@ -4780,7 +4780,7 @@ dump_unwindsyms (Dwfl_Module *m,
// likely can't do anything about this; backtraces for the
// affected module would just get all icky heuristicy.
// So only report in verbose mode.
- if (c->session.verbose > 2)
+ if (c->session.verbose > 2 && ! c->session.suppress_warnings)
c->session.print_warning ("No unwind data for " + modname
+ ", " + dwfl_errmsg (-1));
}
@@ -5081,12 +5081,12 @@ emit_symbol_data_done (unwindsym_dump_context *ctx, systemtap_session& s)
<< ";\n";
// Some nonexistent modules may have been identified with "-d". Note them.
- for (set<string>::iterator it = ctx->undone_unwindsym_modules.begin();
- it != ctx->undone_unwindsym_modules.end();
- it ++)
- {
- s.print_warning ("missing unwind/symbol data for module '" + (*it) + "'");
- }
+ if (! s.suppress_warnings)
+ for (set<string>::iterator it = ctx->undone_unwindsym_modules.begin();
+ it != ctx->undone_unwindsym_modules.end();
+ it ++)
+ s.print_warning ("missing unwind/symbol data for module '"
+ + (*it) + "'");
}
diff --git a/util.cxx b/util.cxx
index a258bf72..495d2f5a 100644
--- a/util.cxx
+++ b/util.cxx
@@ -16,6 +16,7 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "util.h"
+#include "sys/sdt.h"
#include <stdexcept>
#include <cerrno>
@@ -327,12 +328,14 @@ static pid_t spawned_pid = 0;
int
stap_system(const char *command)
{
+ STAP_PROBE1(stap, stap_system__start, command);
const char * argv[] = { "sh", "-c", command, NULL };
int ret, status;
spawned_pid = 0;
ret = posix_spawn(&spawned_pid, "/bin/sh", NULL, NULL,
const_cast<char **>(argv), environ);
+ STAP_PROBE2(stap, stap_system__spawn, ret, spawned_pid);
if (ret == 0)
{
if (waitpid(spawned_pid, &status, 0) == spawned_pid)
@@ -340,6 +343,7 @@ stap_system(const char *command)
else
ret = errno;
}
+ STAP_PROBE1(stap, stap_system__complete, ret);
spawned_pid = 0;
return ret;
}