summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Smith <dsmith@redhat.com>2009-04-20 13:55:45 -0500
committerDavid Smith <dsmith@redhat.com>2009-04-20 13:55:45 -0500
commitd1b6c2866b35575219fb36fa2307c9f87e876750 (patch)
tree4cc6d22bb879f302259074da840c279ee0b3c185
parentcfee927fb9fc96fa06c55219abce6349a15d47e6 (diff)
parent555b11c26094bafa5e450d8ad70b72a8fcbea10f (diff)
downloadsystemtap-steved-d1b6c2866b35575219fb36fa2307c9f87e876750.tar.gz
systemtap-steved-d1b6c2866b35575219fb36fa2307c9f87e876750.tar.xz
systemtap-steved-d1b6c2866b35575219fb36fa2307c9f87e876750.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in5
-rw-r--r--README4
-rw-r--r--aclocal.m4156
-rw-r--r--buildrun.cxx5
-rwxr-xr-xconfigure225
-rw-r--r--configure.ac11
-rw-r--r--doc/Makefile.in3
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.in3
-rw-r--r--grapher/CairoWidget.cxx42
-rw-r--r--grapher/CairoWidget.hxx42
-rw-r--r--grapher/GraphData.hxx44
-rw-r--r--grapher/GraphWidget.cxx323
-rw-r--r--grapher/GraphWidget.hxx62
-rw-r--r--grapher/Makefile.am7
-rw-r--r--grapher/Makefile.in489
-rw-r--r--grapher/grapher.cxx127
-rw-r--r--main.cxx30
-rw-r--r--runtime/print.c28
-rw-r--r--runtime/vsprintf.c355
-rw-r--r--stap.1.in9
-rw-r--r--testsuite/systemtap.examples/general/grapher.stp32
-rw-r--r--testsuite/systemtap.examples/index.html3
-rw-r--r--testsuite/systemtap.examples/index.txt7
-rw-r--r--testsuite/systemtap.examples/keyword-index.html23
-rw-r--r--testsuite/systemtap.examples/keyword-index.txt34
-rw-r--r--testsuite/systemtap.examples/network/dropwatch.meta13
-rwxr-xr-xtestsuite/systemtap.examples/network/dropwatch.stp30
-rw-r--r--testsuite/systemtap.printf/basic6.exp3
-rw-r--r--testsuite/systemtap.printf/basic6.stp5
-rw-r--r--translate.cxx33
32 files changed, 2102 insertions, 54 deletions
diff --git a/.gitignore b/.gitignore
index cd63142e..5869f401 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ config.status
.deps
loc2c-test
run-stap
+run-staprun
stamp-h1
stap
staprun
diff --git a/Makefile.am b/Makefile.am
index f5fedae1..33563719 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -265,7 +265,7 @@ uninstall-local:
rm -rf $(DESTDIR)$(sysconfdir)/systemtap
# XXX: leaves behind man pages
-SUBDIRS = doc
+SUBDIRS = doc grapher
DIST_SUBDIRS = testsuite $(SUBDIRS)
check-local:
diff --git a/Makefile.in b/Makefile.in
index a953be51..9c80e321 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -205,6 +205,8 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
+GRAPHER_CFLAGS = @GRAPHER_CFLAGS@
+GRAPHER_LIBS = @GRAPHER_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -230,6 +232,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
PIECFLAGS = @PIECFLAGS@
PIECXXFLAGS = @PIECXXFLAGS@
PIELDFLAGS = @PIELDFLAGS@
+PKG_CONFIG = @PKG_CONFIG@
PROCFLAGS = @PROCFLAGS@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
@@ -371,7 +374,7 @@ EXAMPLE_SOURCE_DIR = $(srcdir)/testsuite/systemtap.examples
EXAMPLE_META_FILES = $(EXAMPLE_SOURCE_DIR)/*/*.meta
TEST_COV_DIR = coverage
# XXX: leaves behind man pages
-SUBDIRS = doc
+SUBDIRS = doc grapher
DIST_SUBDIRS = testsuite $(SUBDIRS)
# Any extra flags, such as:
diff --git a/README b/README
index 7c1ab412..ac6f0a97 100644
--- a/README
+++ b/README
@@ -106,3 +106,7 @@ Building a kernel.org kernel:
- Or else, if you wish to install the kernel build/debuginfo data into
a place where systemtap will find it without the "-r" option:
% ln -s /path/to/kernel/build/tree /lib/modules/RELEASE/build
+
+- Instead of using the "-r" option, you can also use the environment
+ variable SYSTEMTAP_RELEASE to direct systemtap to the kernel data.
+
diff --git a/aclocal.m4 b/aclocal.m4
index 5ff7e05a..e726a5cc 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -19,6 +19,162 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
+
# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
diff --git a/buildrun.cxx b/buildrun.cxx
index aac0c356..e0f22f29 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -377,7 +377,6 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_
// create our source file
string source(dir + "/tracequery.c");
ofstream osrc(source.c_str());
- osrc << "#include <linux/module.h>" << endl;
osrc << "#ifdef CONFIG_TRACEPOINTS" << endl;
osrc << "#include <linux/tracepoint.h>" << endl;
@@ -434,10 +433,6 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_
// finish up the module source
osrc << "#endif /* CONFIG_TRACEPOINTS */" << endl;
- osrc << "int init_module(void) { return 0; }" << endl;
- osrc << "void cleanup_module(void) {}" << endl;
- osrc << "MODULE_DESCRIPTION(\"tracepoint query\");" << endl;
- osrc << "MODULE_LICENSE(\"GPL\");" << endl;
osrc.close();
// make the module
diff --git a/configure b/configure
index 852dc786..9576d7e6 100755
--- a/configure
+++ b/configure
@@ -647,6 +647,11 @@ stap_LIBS
elfutils_abs_srcdir
BUILD_ELFUTILS_FALSE
BUILD_ELFUTILS_TRUE
+BUILD_GRAPHER_FALSE
+BUILD_GRAPHER_TRUE
+GRAPHER_LIBS
+GRAPHER_CFLAGS
+PKG_CONFIG
BUILD_SERVER_FALSE
BUILD_SERVER_TRUE
nspr_CFLAGS
@@ -773,6 +778,7 @@ enable_crash
enable_docs
enable_refdocs
enable_server
+enable_grapher
with_elfutils
'
ac_precious_vars='build_alias
@@ -787,6 +793,9 @@ CXX
CXXFLAGS
CCC
CPP
+PKG_CONFIG
+GRAPHER_CFLAGS
+GRAPHER_LIBS
CXXCPP'
ac_subdirs_all='testsuite'
@@ -1438,6 +1447,8 @@ Optional Features:
if xmlto etc. found and other documentation built).
--enable-server enable building of stap-server/client (default on if
nss etc. found).
+ --enable-grapher enable building of grapher (default on if gtkmm is
+ found).
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1456,6 +1467,11 @@ Some influential environment variables:
CXX C++ compiler command
CXXFLAGS C++ compiler flags
CPP C preprocessor
+ PKG_CONFIG path to pkg-config utility
+ GRAPHER_CFLAGS
+ C compiler flags for GRAPHER, overriding pkg-config
+ GRAPHER_LIBS
+ linker flags for GRAPHER, overriding pkg-config
CXXCPP C++ preprocessor
Use these variables to override the choices made by `configure' or to help
@@ -7104,6 +7120,205 @@ else
fi
+# Check whether --enable-grapher was given.
+if test "${enable_grapher+set}" = set; then
+ enableval=$enable_grapher; enable_grapher=$enableval
+else
+ enable_grapher="check"
+fi
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; 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_path_PKG_CONFIG+set}" = set; then
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ 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_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; 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_path_ac_pt_PKG_CONFIG+set}" = set; then
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ 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_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ 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
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:$LINENO: checking for GRAPHER" >&5
+$as_echo_n "checking for GRAPHER... " >&6; }
+
+if test -n "$GRAPHER_CFLAGS"; then
+ pkg_cv_GRAPHER_CFLAGS="$GRAPHER_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { ($as_echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"gtkmm-2.4 >= 2.8.0\"") >&5
+ ($PKG_CONFIG --exists --print-errors "gtkmm-2.4 >= 2.8.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ pkg_cv_GRAPHER_CFLAGS=`$PKG_CONFIG --cflags "gtkmm-2.4 >= 2.8.0" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GRAPHER_LIBS"; then
+ pkg_cv_GRAPHER_LIBS="$GRAPHER_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { ($as_echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"gtkmm-2.4 >= 2.8.0\"") >&5
+ ($PKG_CONFIG --exists --print-errors "gtkmm-2.4 >= 2.8.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ pkg_cv_GRAPHER_LIBS=`$PKG_CONFIG --libs "gtkmm-2.4 >= 2.8.0" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GRAPHER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gtkmm-2.4 >= 2.8.0" 2>&1`
+ else
+ GRAPHER_PKG_ERRORS=`$PKG_CONFIG --print-errors "gtkmm-2.4 >= 2.8.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GRAPHER_PKG_ERRORS" >&5
+
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+ have_gtkmm=no
+elif test $pkg_failed = untried; then
+ have_gtkmm=no
+else
+ GRAPHER_CFLAGS=$pkg_cv_GRAPHER_CFLAGS
+ GRAPHER_LIBS=$pkg_cv_GRAPHER_LIBS
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+ have_gtkmm=yes
+fi
+ if test "x${have_gtkmm}" == "xyes" -a x"$enable_grapher" != "xno"; then
+ BUILD_GRAPHER_TRUE=
+ BUILD_GRAPHER_FALSE='#'
+else
+ BUILD_GRAPHER_TRUE='#'
+ BUILD_GRAPHER_FALSE=
+fi
+
+
build_elfutils=no
# Check whether --with-elfutils was given.
@@ -8074,7 +8289,7 @@ _ACEOF
ac_config_headers="$ac_config_headers config.h:config.in"
-ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.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 initscript/systemtap"
@@ -8244,6 +8459,13 @@ $as_echo "$as_me: error: conditional \"BUILD_SERVER\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
+if test -z "${BUILD_GRAPHER_TRUE}" && test -z "${BUILD_GRAPHER_FALSE}"; then
+ { { $as_echo "$as_me:$LINENO: error: conditional \"BUILD_GRAPHER\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"BUILD_GRAPHER\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
if test -z "${BUILD_ELFUTILS_TRUE}" && test -z "${BUILD_ELFUTILS_FALSE}"; then
{ { $as_echo "$as_me:$LINENO: error: conditional \"BUILD_ELFUTILS\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
@@ -8764,6 +8986,7 @@ do
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
"doc/SystemTap_Tapset_Reference/Makefile") CONFIG_FILES="$CONFIG_FILES doc/SystemTap_Tapset_Reference/Makefile" ;;
+ "grapher/Makefile") CONFIG_FILES="$CONFIG_FILES grapher/Makefile" ;;
"stap.1") CONFIG_FILES="$CONFIG_FILES stap.1" ;;
"stapprobes.3stap") CONFIG_FILES="$CONFIG_FILES stapprobes.3stap" ;;
"stapfuncs.3stap") CONFIG_FILES="$CONFIG_FILES stapfuncs.3stap" ;;
diff --git a/configure.ac b/configure.ac
index a953e156..125626f8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -253,6 +253,15 @@ if test "x${have_nss_includes}${have_nss_libs}" != "xyesyes"; then
fi
AM_CONDITIONAL([BUILD_SERVER], [test "x${have_nss_includes}${have_nss_libs}" == "xyesyes" -a "$enable_server" != "no"])
+dnl Handle the optional grapher
+AC_ARG_ENABLE([grapher],
+ AS_HELP_STRING([--enable-grapher],
+ [enable building of grapher (default on if gtkmm is found).]),
+ [enable_grapher=$enableval],
+ [enable_grapher="check"])
+PKG_CHECK_MODULES([GRAPHER], [gtkmm-2.4 >= 2.8.0],have_gtkmm=yes,have_gtkmm=no)
+AM_CONDITIONAL([BUILD_GRAPHER], [test "x${have_gtkmm}" == "xyes" -a x"$enable_grapher" != "xno"])
+
dnl Handle elfutils. If '--with-elfutils=DIR' wasn't specified, used
dnl the system's elfutils.
build_elfutils=no
@@ -356,7 +365,7 @@ dnl Don't use this directly (when not given it is set to NONE).
AC_DEFINE_UNQUOTED(STAP_PREFIX, "$prefix", [configure prefix location])
AC_CONFIG_HEADERS([config.h:config.in])
-AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.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(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_SUBDIRS(testsuite)
AC_CONFIG_FILES([run-stap], [chmod +x run-stap])
AC_CONFIG_FILES([run-staprun], [chmod +x run-staprun])
diff --git a/doc/Makefile.in b/doc/Makefile.in
index e23a6699..2818ae52 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -79,6 +79,8 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
+GRAPHER_CFLAGS = @GRAPHER_CFLAGS@
+GRAPHER_LIBS = @GRAPHER_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -104,6 +106,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
PIECFLAGS = @PIECFLAGS@
PIECXXFLAGS = @PIECXXFLAGS@
PIELDFLAGS = @PIELDFLAGS@
+PKG_CONFIG = @PKG_CONFIG@
PROCFLAGS = @PROCFLAGS@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in
index 6fe6bab2..2ea897c6 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.in
+++ b/doc/SystemTap_Tapset_Reference/Makefile.in
@@ -82,6 +82,8 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
+GRAPHER_CFLAGS = @GRAPHER_CFLAGS@
+GRAPHER_LIBS = @GRAPHER_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -107,6 +109,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
PIECFLAGS = @PIECFLAGS@
PIECXXFLAGS = @PIECXXFLAGS@
PIELDFLAGS = @PIELDFLAGS@
+PKG_CONFIG = @PKG_CONFIG@
PROCFLAGS = @PROCFLAGS@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
diff --git a/grapher/CairoWidget.cxx b/grapher/CairoWidget.cxx
new file mode 100644
index 00000000..86498a4f
--- /dev/null
+++ b/grapher/CairoWidget.cxx
@@ -0,0 +1,42 @@
+#include "CairoWidget.hxx"
+
+#include <math.h>
+
+namespace systemtap
+{
+ void CairoPlayButton::draw(Cairo::RefPtr<Cairo::Context> cr)
+ {
+ if (!_visible)
+ return;
+ cr->save();
+ cr->set_line_width(1.0);
+ // square with rounded corners
+ cr->move_to(_x0, _y0 + _radius);
+ cr->arc(_x0 + _radius, _y0 + _radius, _radius, M_PI, -M_PI_2);
+ cr->line_to(_x0 + _size - _radius, _y0);
+ cr->arc(_x0 + _size - _radius, _y0 + _radius, _radius, -M_PI_2, 0.0);
+ cr->line_to(_x0 + _size, _y0 + _size - _radius);
+ cr->arc(_x0 + _size - _radius, _y0 + _size - _radius, _radius, 0.0, M_PI_2);
+ cr->line_to(_x0 + _radius, _y0 + _size);
+ cr->arc(_x0 + _radius, _y0 + _size - _radius, _radius, M_PI_2, M_PI);
+ cr->close_path();
+ //cr->rectangle(_x0, _y0, 50.0, 50.0);
+ cr->set_source_rgba(1.0, 1.0, 1.0, .8);
+ cr->stroke();
+ // play equalateral triangle
+ cr->move_to(_x0 + .25 * _size, _y0 + (.5 - 1.0 / (sqrt(3.0) * 2.0)) * _size);
+ cr->line_to(_x0 + .75 * _size, _y0 + .5 * _size);
+ cr->line_to(_x0 + .25 * _size, _y0 + (.5 + 1.0 / (sqrt(3.0) * 2.0)) * _size);
+ cr->close_path();
+ cr->fill();
+ cr->restore();
+ }
+
+ bool CairoPlayButton::containsPoint(double x, double y)
+ {
+ if (x >= _x0 && (x < (_x0 + 50.0)) && (y >= _y0) && (y < (_y0 + 50)))
+ return true;
+ else
+ return false;
+ }
+}
diff --git a/grapher/CairoWidget.hxx b/grapher/CairoWidget.hxx
new file mode 100644
index 00000000..077a4c7a
--- /dev/null
+++ b/grapher/CairoWidget.hxx
@@ -0,0 +1,42 @@
+#ifndef SYSTEMTAP_CAIROWIDGET_H
+#define SYSTEMTAP_CAIROWIDGET_H 1
+
+#include <cairomm/context.h>
+namespace systemtap
+{
+ class CairoWidget
+ {
+ public:
+ CairoWidget(bool visible = false)
+ : _visible(visible), _size(50.0), _radius(5)
+ {}
+ bool isVisible() const { return _visible; }
+ void setVisible(bool visible) { _visible = visible; }
+ void getOrigin(double &x, double &y) const
+ {
+ x = _x0;
+ y = _y0;
+ }
+ void setOrigin(double x, double y)
+ {
+ _x0 = x;
+ _y0 = y;
+ }
+ virtual void draw(Cairo::RefPtr<Cairo::Context> cr) = 0;
+ virtual bool containsPoint(double x, double y) { return false; }
+ protected:
+ bool _visible;
+ double _x0;
+ double _y0;
+ double _size;
+ double _radius;
+ };
+
+ class CairoPlayButton : public CairoWidget
+ {
+ public:
+ virtual void draw(Cairo::RefPtr<Cairo::Context> cr);
+ virtual bool containsPoint(double x, double y);
+ };
+}
+#endif
diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx
new file mode 100644
index 00000000..0f3b0b31
--- /dev/null
+++ b/grapher/GraphData.hxx
@@ -0,0 +1,44 @@
+#ifndef SYSTEMTAP_GRAPHDATA_HXX
+#define SYSTEMTAP_GRAPHDATA_HXX 1
+
+#include <utility>
+#include <vector>
+
+namespace systemtap
+{
+ struct GraphData
+ {
+ public:
+ enum Style
+ { BAR,
+ DOT
+ };
+ GraphData() : 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;
+ // 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;
+ }
+ };
+ };
+}
+#endif
diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx
new file mode 100644
index 00000000..a82a8bb6
--- /dev/null
+++ b/grapher/GraphWidget.cxx
@@ -0,0 +1,323 @@
+#include <algorithm>
+#include <ctime>
+#include <math.h>
+#include <sstream>
+#include <iomanip>
+#include <cairomm/context.h>
+#include "GraphWidget.hxx"
+#include "CairoWidget.hxx"
+
+namespace systemtap
+{
+ 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)
+ {
+ add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK
+ | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK);
+ Glib::signal_timeout()
+ .connect(sigc::mem_fun(*this, &GraphWidget::on_timeout), 1000);
+ signal_expose_event()
+ .connect(sigc::mem_fun(*this, &GraphWidget::on_expose_event), false);
+ signal_button_press_event()
+ .connect(sigc::mem_fun(*this, &GraphWidget::on_button_press_event),
+ false);
+ signal_button_release_event()
+ .connect(sigc::mem_fun(*this, &GraphWidget::on_button_release_event),
+ false);
+ signal_motion_notify_event()
+ .connect(sigc::mem_fun(*this, &GraphWidget::on_motion_notify_event),
+ false);
+ signal_scroll_event()
+ .connect(sigc::mem_fun(*this, &GraphWidget::on_scroll_event), false);
+ }
+
+ 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)
+ {
+ _datasets.push_back(data);
+ }
+
+ bool GraphWidget::on_expose_event(GdkEventExpose* event)
+ {
+ // This is where we draw on the window
+ Glib::RefPtr<Gdk::Window> window = get_window();
+ if(!window)
+ return true;
+
+ Gtk::Allocation allocation = get_allocation();
+
+ const int graphWidth = allocation.get_width();
+ const int graphHeight = allocation.get_height();
+ const int width = graphWidth - 20;
+ const int height = graphHeight - 20;
+
+ Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+ if(event && !_autoScaling)
+ {
+ // clip to the area indicated by the expose event so that we only
+ // redraw the portion of the window that needs to be redrawn
+ cr->rectangle(event->area.x, event->area.y,
+ 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);
+ 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)
+ {
+ 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->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))
+ {
+ _autoScaling = true;
+ _autoScrolling = true;
+ queue_draw();
+ }
+ else
+ {
+ _trackingDrag = true;
+ _autoScaling = false;
+ _autoScrolling = false;
+ _dragOriginX = event->x;
+ _dragOriginY = event->y;
+ _dragOrigLeft = _left;
+ _dragOrigRight = _right;
+ }
+ return true;
+ }
+
+ bool GraphWidget::on_button_release_event(GdkEventButton* event)
+ {
+ _trackingDrag = false;
+ return true;
+ }
+
+ bool GraphWidget::on_motion_notify_event(GdkEventMotion* event)
+ {
+ Glib::RefPtr<Gdk::Window> win = get_window();
+ if(!win)
+ return true;
+ double x;
+ double y;
+ // XXX Hint
+ if (event->is_hint)
+ {
+ }
+ else
+ {
+ x = event->x;
+ y = event->y;
+ }
+ if (_trackingDrag)
+ {
+ 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;
+ queue_draw();
+ }
+ return true;
+ }
+
+ 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();
+ return true;
+ }
+
+ bool GraphWidget::on_timeout()
+ {
+ queue_draw();
+ return true;
+ }
+}
diff --git a/grapher/GraphWidget.hxx b/grapher/GraphWidget.hxx
new file mode 100644
index 00000000..46075b78
--- /dev/null
+++ b/grapher/GraphWidget.hxx
@@ -0,0 +1,62 @@
+#ifndef SYSTEMTAP_GRAPHWIDGET_H
+#define SYSTEMTAP_GRAPHWIDGET_H
+
+#include <string>
+#include <vector>
+#include <tr1/memory>
+
+#include <gtkmm/drawingarea.h>
+#include "GraphData.hxx"
+
+namespace systemtap
+{
+ class CairoPlayButton;
+
+ class GraphWidget : public Gtk::DrawingArea
+ {
+ 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; }
+ protected:
+ //Override default signal handler:
+ virtual bool on_expose_event(GdkEventExpose* event);
+ virtual bool on_motion_notify_event(GdkEventMotion* event);
+ virtual bool on_button_press_event(GdkEventButton* event);
+ 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
new file mode 100644
index 00000000..fdb52ef7
--- /dev/null
+++ b/grapher/Makefile.am
@@ -0,0 +1,7 @@
+if BUILD_GRAPHER
+bin_PROGRAMS = grapher
+
+grapher_CXXFLAGS = $(GRAPHER_CFLAGS)
+grapher_SOURCES = grapher.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
new file mode 100644
index 00000000..020d9c01
--- /dev/null
+++ b/grapher/Makefile.in
@@ -0,0 +1,489 @@
+# Makefile.in generated by automake 1.10.1 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.
+# 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.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+@BUILD_GRAPHER_TRUE@bin_PROGRAMS = grapher$(EXEEXT)
+subdir = grapher
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am__grapher_SOURCES_DIST = grapher.cxx GraphWidget.cxx CairoWidget.cxx
+@BUILD_GRAPHER_TRUE@am_grapher_OBJECTS = grapher-grapher.$(OBJEXT) \
+@BUILD_GRAPHER_TRUE@ grapher-GraphWidget.$(OBJEXT) \
+@BUILD_GRAPHER_TRUE@ grapher-CairoWidget.$(OBJEXT)
+grapher_OBJECTS = $(am_grapher_OBJECTS)
+am__DEPENDENCIES_1 =
+@BUILD_GRAPHER_TRUE@grapher_DEPENDENCIES = $(am__DEPENDENCIES_1)
+grapher_LINK = $(CXXLD) $(grapher_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(grapher_SOURCES)
+DIST_SOURCES = $(am__grapher_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATE = @DATE@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GRAPHER_CFLAGS = @GRAPHER_CFLAGS@
+GRAPHER_LIBS = @GRAPHER_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PIECFLAGS = @PIECFLAGS@
+PIECXXFLAGS = @PIECXXFLAGS@
+PIELDFLAGS = @PIELDFLAGS@
+PKG_CONFIG = @PKG_CONFIG@
+PROCFLAGS = @PROCFLAGS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+U = @U@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+elfutils_abs_srcdir = @elfutils_abs_srcdir@
+exec_prefix = @exec_prefix@
+have_dvips = @have_dvips@
+have_latex = @have_latex@
+have_latex2html = @have_latex2html@
+have_ps2pdf = @have_ps2pdf@
+have_xmlto = @have_xmlto@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nspr_CFLAGS = @nspr_CFLAGS@
+nss_CFLAGS = @nss_CFLAGS@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sqlite3_LIBS = @sqlite3_LIBS@
+srcdir = @srcdir@
+stap_LIBS = @stap_LIBS@
+staplog_CPPFLAGS = @staplog_CPPFLAGS@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+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_LDADD = $(GRAPHER_LIBS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cxx .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu grapher/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu grapher/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(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
+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
+
+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
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+grapher$(EXEEXT): $(grapher_OBJECTS) $(grapher_DEPENDENCIES)
+ @rm -f grapher$(EXEEXT)
+ $(grapher_LINK) $(grapher_OBJECTS) $(grapher_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+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-GraphWidget.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
+@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
+@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
+@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
+@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-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
+@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
+@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
+@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
+@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`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ 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; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ 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; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ 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" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ 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 $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am 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/grapher.cxx b/grapher/grapher.cxx
new file mode 100644
index 00000000..46182178
--- /dev/null
+++ b/grapher/grapher.cxx
@@ -0,0 +1,127 @@
+#include "GraphWidget.hxx"
+
+#include <cmath>
+#include <sstream>
+#include <string>
+#include <map>
+
+#include <gtkmm/main.h>
+#include <gtkmm/window.h>
+#include <unistd.h>
+#include <poll.h>
+
+using namespace systemtap;
+
+class StapParser
+{
+ 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;
+ }
+};
+
+int main(int argc, char** argv)
+{
+ Gtk::Main app(argc, argv);
+
+ Gtk::Window win;
+
+ 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, w);
+ Glib::signal_io().connect(sigc::mem_fun(stapParser,
+ &StapParser::ioCallback),
+ 0,
+ Glib::IO_IN);
+ win.add(w);
+ w.show();
+
+ Gtk::Main::run(win);
+
+ return 0;
+}
diff --git a/main.cxx b/main.cxx
index 794a5891..37c5b135 100644
--- a/main.cxx
+++ b/main.cxx
@@ -425,6 +425,36 @@ main (int argc, char * const argv [])
if (s_tc != NULL)
s.tapset_compile_coverage = true;
+ const char* s_kr = getenv ("SYSTEMTAP_RELEASE");
+ if (s_kr != NULL) {
+ if (s_kr[0] == '/') // fully specified path
+ {
+ s.kernel_build_tree = s_kr;
+ string version_file_name = s.kernel_build_tree + "/include/config/kernel.release";
+ // The file include/config/kernel.release within the
+ // build tree is used to pull out the version information
+ ifstream version_file (version_file_name.c_str());
+ if (version_file.fail ())
+ {
+ cerr << "Missing " << version_file_name << endl;
+ exit(1);
+ }
+ else
+ {
+ char c;
+ s.kernel_release = "";
+ while (version_file.get(c) && c != '\n')
+ s.kernel_release.push_back(c);
+ }
+ }
+ else
+ {
+ s.kernel_release = string (s_kr);
+ s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build";
+ }
+ }
+
+
while (true)
{
int long_opt;
diff --git a/runtime/print.c b/runtime/print.c
index 2c84d3c9..964a73c2 100644
--- a/runtime/print.c
+++ b/runtime/print.c
@@ -13,8 +13,8 @@
#include "string.h"
-#include "vsprintf.c"
#include "transport/transport.c"
+#include "vsprintf.c"
/** @file print.c
* Printing Functions.
@@ -173,34 +173,10 @@ static void _stp_print_binary (int num, ...)
*/
static void _stp_printf (const char *fmt, ...)
{
- int num;
va_list args;
- _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id());
- char *buf = pb->buf + pb->len;
- int size = STP_BUFFER_SIZE - pb->len;
-
va_start(args, fmt);
- num = _stp_vsnprintf(buf, size, fmt, args);
+ _stp_vsnprintf(NULL, 0, fmt, args);
va_end(args);
- if (unlikely(num >= size)) {
- /* overflowed the buffer */
- if (pb->len == 0) {
- /* A single print request exceeded the buffer size. */
- /* Should not be possible with Systemtap-generated code. */
- pb->len = STP_BUFFER_SIZE;
- _stp_print_flush();
- num = 0;
- } else {
- /* Need more space. Flush the previous contents */
- _stp_print_flush();
-
- /* try again */
- va_start(args, fmt);
- num = _stp_vsnprintf(pb->buf, STP_BUFFER_SIZE, fmt, args);
- va_end(args);
- }
- }
- pb->len += num;
}
/** Write a string into the print buffer.
diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c
index bd58d760..38ab0e2d 100644
--- a/runtime/vsprintf.c
+++ b/runtime/vsprintf.c
@@ -12,6 +12,9 @@
#ifndef _VSPRINTF_C_
#define _VSPRINTF_C_
+//forward declaration for _stp_vsnprintf
+static void * _stp_reserve_bytes (int);
+
static int skip_atoi(const char **s)
{
int i=0;
@@ -22,6 +25,10 @@ static int skip_atoi(const char **s)
enum print_flag {STP_ZEROPAD=1, STP_SIGN=2, STP_PLUS=4, STP_SPACE=8, STP_LEFT=16, STP_SPECIAL=32, STP_LARGE=64};
+/*
+ * Changes to number() will require a corresponding change to number_size below,
+ * to ensure proper buffer allocation for _stp_printf.
+ */
static char * number(char * buf, char * end, uint64_t num, int base, int size, int precision, enum print_flag type)
{
char c,sign,tmp[66];
@@ -115,6 +122,85 @@ static char * number(char * buf, char * end, uint64_t num, int base, int size, i
return buf;
}
+/*
+ * Calculates the number of bytes required to print the paramater num. A change to
+ * number() requires a corresponding change here, and vice versa, to ensure the
+ * calculated size and printed size match.
+ */
+static int number_size(uint64_t num, int base, int size, int precision, enum print_flag type) {
+ char c,sign,tmp[66];
+ const char *digits;
+ static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i, num_bytes = 0;
+
+ digits = (type & STP_LARGE) ? large_digits : small_digits;
+ if (type & STP_LEFT)
+ type &= ~STP_ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & STP_ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & STP_SIGN) {
+ if ((int64_t) num < 0) {
+ sign = '-';
+ num = - (int64_t) num;
+ size--;
+ } else if (type & STP_PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & STP_SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & STP_SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(STP_ZEROPAD+STP_LEFT))) {
+ while(size-->0) {
+ num_bytes++;
+ }
+ }
+ if (sign) {
+ num_bytes++;
+ }
+ if (type & STP_SPECIAL) {
+ if (base==8) {
+ num_bytes++;
+ } else if (base==16) {
+ num_bytes+=2;
+ }
+ }
+ if (!(type & STP_LEFT)) {
+ while (size-- > 0) {
+ num_bytes++;
+ }
+ }
+ while (i < precision--) {
+ num_bytes++;
+ }
+ while (i-- > 0) {
+ num_bytes++;
+ }
+ while (size-- > 0) {
+ num_bytes++;
+ }
+ return num_bytes;
+
+}
+
static int check_binary_precision (int precision) {
/* precision can be unspecified (-1) or one of 1, 2, 4 or 8. */
switch (precision) {
@@ -148,9 +234,262 @@ static int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
if (unlikely((int) size < 0))
return 0;
- str = buf;
- end = buf + size - 1;
+ /*
+ * buf will be NULL when this function is called from _stp_printf.
+ * This branch calculates the exact size print buffer required for
+ * the string and allocates it with _stp_reserve_bytes. A change
+ * to this branch requires a corresponding change to the same
+ * section of code below.
+ */
+ if (buf == NULL) {
+ const char* fmt_copy = fmt;
+ int num_bytes = 0;
+ va_list args_copy;
+
+ va_copy(args_copy, args);
+
+ for (; *fmt_copy ; ++fmt_copy) {
+ if (*fmt_copy != '%') {
+ num_bytes++;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat_copy:
+ ++fmt_copy; /* this also skips first '%' */
+ switch (*fmt_copy) {
+ case '-': flags |= STP_LEFT; goto repeat_copy;
+ case '+': flags |= STP_PLUS; goto repeat_copy;
+ case ' ': flags |= STP_SPACE; goto repeat_copy;
+ case '#': flags |= STP_SPECIAL; goto repeat_copy;
+ case '0': flags |= STP_ZEROPAD; goto repeat_copy;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt_copy))
+ field_width = skip_atoi(&fmt_copy);
+ else if (*fmt_copy == '*') {
+ ++fmt_copy;
+ /* it's the next argument */
+ field_width = va_arg(args_copy, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= STP_LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt_copy == '.') {
+ ++fmt_copy;
+ if (isdigit(*fmt_copy))
+ precision = skip_atoi(&fmt_copy);
+ else if (*fmt_copy == '*') {
+ ++fmt_copy;
+ /* it's the next argument */
+ precision = va_arg(args_copy, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt_copy == 'h' || *fmt_copy == 'l' || *fmt_copy == 'L') {
+ qualifier = *fmt_copy;
+ ++fmt_copy;
+ if (qualifier == 'l' && *fmt_copy == 'l') {
+ qualifier = 'L';
+ ++fmt_copy;
+ }
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt_copy) {
+ case 'b':
+ num = va_arg(args_copy, int64_t);
+
+ /* Only certain values are valid for the precision. */
+ precision = check_binary_precision (precision);
+
+ /* Unspecified field width defaults to the specified
+ precision and vice versa. If neither is specified,
+ then both default to 8. */
+ if (field_width == -1) {
+ if (precision == -1) {
+ field_width = 8;
+ precision = 8;
+ }
+ else
+ field_width = precision;
+ }
+ else if (precision == -1) {
+ precision = check_binary_precision (field_width);
+ if (precision == -1)
+ precision = 8;
+ }
+
+ len = precision;
+ if (!(flags & STP_LEFT)) {
+ while (len < field_width--) {
+ num_bytes++;
+ }
+ }
+
+ num_bytes += precision;
+
+ while (len < field_width--)
+ num_bytes++;
+
+ continue;
+
+ case 's':
+ case 'M':
+ case 'm':
+ s = va_arg(args_copy, char *);
+ if ((unsigned long)s < PAGE_SIZE)
+ s = "<NULL>";
+
+ if (*fmt_copy == 's')
+ len = strnlen(s, precision);
+ else if (precision > 0)
+ len = precision;
+ else
+ len = 1;
+
+ if (!(flags & STP_LEFT)) {
+ while (len < field_width--) {
+ num_bytes++;
+ }
+ }
+ if (*fmt_copy == 'M') {
+ num_bytes += number_size((unsigned long) *(uint64_t *) s,
+ 16, field_width, len, flags);
+ }
+ else {
+ num_bytes += len;
+ }
+
+ while (len < field_width--) {
+ num_bytes++;
+ }
+ if(flags & STP_ZEROPAD) {
+ num_bytes++;
+ }
+ continue;
+ case 'X':
+ flags |= STP_LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= STP_SIGN;
+ case 'u':
+ break;
+
+ case 'p':
+ /* Note that %p takes an int64_t argument. */
+ len = 2*sizeof(void *) + 2;
+ flags |= STP_ZEROPAD;
+
+ if (field_width == -1)
+ field_width = len;
+
+ if (!(flags & STP_LEFT)) {
+ while (len < field_width) {
+ field_width--;
+ num_bytes++;
+ }
+ }
+
+ //account for "0x"
+ num_bytes+=2;
+ field_width-=2;
+
+ num_bytes += number_size((unsigned long) va_arg(args_copy, int64_t),
+ 16, field_width, field_width, flags);
+ continue;
+
+ case '%':
+ num_bytes++;
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'c':
+ if (!(flags & STP_LEFT)) {
+ while (--field_width > 0) {
+ num_bytes++;
+ }
+ }
+ c = (unsigned char) va_arg(args_copy, int);
+ num_bytes++;
+ while (--field_width > 0) {
+ num_bytes++;
+ }
+ continue;
+
+ default:
+ num_bytes++;
+ if (*fmt_copy) {
+ num_bytes++;
+ } else {
+ --fmt_copy;
+ }
+ continue;
+ }
+
+ if (qualifier == 'L')
+ num = va_arg(args_copy, int64_t);
+ else if (qualifier == 'l') {
+ num = va_arg(args_copy, unsigned long);
+ if (flags & STP_SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args_copy, int);
+ if (flags & STP_SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args_copy, unsigned int);
+ if (flags & STP_SIGN)
+ num = (signed int) num;
+ }
+ num_bytes += number_size(num, base, field_width, precision, flags);
+ }
+
+ va_end(args_copy);
+
+ if (num_bytes == 0)
+ return 0;
+
+ //max print buffer size
+ if (num_bytes > STP_BUFFER_SIZE) {
+ num_bytes = STP_BUFFER_SIZE;
+ }
+
+ str = (char*)_stp_reserve_bytes(num_bytes);
+ size = num_bytes;
+ end = str + size - 1;
+
+ } else {
+ str = buf;
+ end = buf + size - 1;
+ }
+ /*
+ * Note that a change to code below requires a corresponding
+ * change in the code above to properly calculate the bytes
+ * required in the output buffer.
+ */
for (; *fmt ; ++fmt) {
if (*fmt != '%') {
if (str <= end)
@@ -433,11 +772,13 @@ static int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
field_width, precision, flags);
}
- if (likely(str <= end))
- *str = '\0';
- else if (size > 0)
- /* don't write out a null byte if the buf size is zero */
- *end = '\0';
+ if (buf != NULL) {
+ if (likely(str <= end))
+ *str = '\0';
+ else if (size > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
+ }
return str-buf;
}
diff --git a/stap.1.in b/stap.1.in
index c664962c..a5a8ab84 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -157,11 +157,16 @@ be used to override limit parameters described below.
Look for the systemtap runtime sources in the given directory.
.TP
.BI \-r " /DIR"
-Build for kernel in given build tree.
+Build for kernel in given build tree. Can also be set with the
+.I SYSTEMTAP_RELEASE
+environment variable.
.TP
.BI \-r " RELEASE"
Build for kernel in build tree
-.BR /lib/modules/RELEASE/build .
+.BR /lib/modules/RELEASE/build .
+Can also be set with the
+.I SYSTEMTAP_RELEASE
+environment variable.
.TP
.BI \-m " MODULE"
Use the given name for the generated kernel object module, instead
diff --git a/testsuite/systemtap.examples/general/grapher.stp b/testsuite/systemtap.examples/general/grapher.stp
new file mode 100644
index 00000000..4f326ec1
--- /dev/null
+++ b/testsuite/systemtap.examples/general/grapher.stp
@@ -0,0 +1,32 @@
+#! /usr/bin/stap
+
+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");
+}
+
+# CPU utilization
+probe begin { qnames["cpu"] ++; qsq_start ("cpu") }
+probe scheduler.cpu_on { if (!idle) {qs_wait ("cpu") qs_run ("cpu") }}
+probe scheduler.cpu_off { if (!idle) qs_done ("cpu") }
+
+global qnames
+
+function qsq_util_reset(q) {
+ u=qsq_utilization (q, 100)
+ qsq_start (q)
+ return u
+}
+
+probe timer.ms(100) { # collect utilization percentages frequently
+ foreach (q in qnames)
+ printf("cpu %d %d\n", gettimeofday_ms(), qsq_util_reset(q))
+}
+
+probe kernel.function("kbd_event") {
+ printf("kbd %d %d\n", gettimeofday_ms(), 75)
+}
diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html
index a03b8dcc..a2dc7d5c 100644
--- a/testsuite/systemtap.examples/index.html
+++ b/testsuite/systemtap.examples/index.html
@@ -88,6 +88,9 @@ keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br>
<li><a href="memory/pfaults.stp">memory/pfaults.stp</a> - Generate Log of Major and Minor Page Faults<br>
keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br>
<p>The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occuring.</p></li>
+<li><a href="network/dropwatch.stp">network/dropwatch.stp</a> - Watch Where Socket Buffers are Freed in the Kernel<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#FREE">FREE</a> <br>
+<p>Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.</p></li>
<li><a href="network/nettop.stp">network/nettop.stp</a> - Periodic Listing of Processes Using Network Interfaces<br>
keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <a href="keyword-index.html#PER-PROCESS">PER-PROCESS</a> <br>
<p>Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.</p></li>
diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt
index d24232e7..2f85628a 100644
--- a/testsuite/systemtap.examples/index.txt
+++ b/testsuite/systemtap.examples/index.txt
@@ -152,6 +152,13 @@ keywords: memory
determine where the page faults are occuring.
+network/dropwatch.stp - Watch Where Socket Buffers are Freed in the Kernel
+keywords: network tracepoint buffer free
+
+ Every five seconds the dropwatch.stp script lists the number of
+ socket buffers freed at locations in the kernel.
+
+
network/nettop.stp - Periodic Listing of Processes Using Network Interfaces
keywords: network traffic per-process
diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html
index e65ed19d..473c0091 100644
--- a/testsuite/systemtap.examples/keyword-index.html
+++ b/testsuite/systemtap.examples/keyword-index.html
@@ -39,7 +39,7 @@
</ul>
<h2>Examples by Keyword</h2>
-<p><tt><a href="#BACKTRACE">BACKTRACE</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DISK">DISK</a> <a href="#FORMAT">FORMAT</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#NETWORK">NETWORK</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROCESS">PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
+<p><tt><a href="#BACKTRACE">BACKTRACE</a> <a href="#BUFFER">BUFFER</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DISK">DISK</a> <a href="#FORMAT">FORMAT</a> <a href="#FREE">FREE</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#NETWORK">NETWORK</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROCESS">PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRACEPOINT">TRACEPOINT</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
<h3><a name="BACKTRACE">BACKTRACE</a></h3>
<ul>
<li><a href="interrupt/scf.stp">interrupt/scf.stp</a> - Tally Backtraces for Inter-Processor Interrupt (IPI)<br>
@@ -52,6 +52,12 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#BAC
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#SCHEDULER">SCHEDULER</a> <a href="keyword-index.html#BACKTRACE">BACKTRACE</a> <br>
<p>The script monitors the time that threads spend waiting for IO operations (in "D" state) in the wait_for_completion function. If a thread spends over 10ms, its name and backtrace is printed, and later so is the total delay.</p></li>
</ul>
+<h3><a name="BUFFER">BUFFER</a></h3>
+<ul>
+<li><a href="network/dropwatch.stp">network/dropwatch.stp</a> - Watch Where Socket Buffers are Freed in the Kernel<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#FREE">FREE</a> <br>
+<p>Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.</p></li>
+</ul>
<h3><a name="CALLGRAPH">CALLGRAPH</a></h3>
<ul>
<li><a href="general/para-callgraph.stp">general/para-callgraph.stp</a> - Callgraph tracing with arguments<br>
@@ -82,6 +88,12 @@ keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br>
keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br>
<p>The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset.</p></li>
</ul>
+<h3><a name="FREE">FREE</a></h3>
+<ul>
+<li><a href="network/dropwatch.stp">network/dropwatch.stp</a> - Watch Where Socket Buffers are Freed in the Kernel<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#FREE">FREE</a> <br>
+<p>Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.</p></li>
+</ul>
<h3><a name="FUNCTIONS">FUNCTIONS</a></h3>
<ul>
<li><a href="profiling/functioncallcount.stp">profiling/functioncallcount.stp</a> - Count Times Functions Called<br>
@@ -150,6 +162,9 @@ keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br>
</ul>
<h3><a name="NETWORK">NETWORK</a></h3>
<ul>
+<li><a href="network/dropwatch.stp">network/dropwatch.stp</a> - Watch Where Socket Buffers are Freed in the Kernel<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#FREE">FREE</a> <br>
+<p>Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.</p></li>
<li><a href="network/nettop.stp">network/nettop.stp</a> - Periodic Listing of Processes Using Network Interfaces<br>
keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <a href="keyword-index.html#PER-PROCESS">PER-PROCESS</a> <br>
<p>Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.</p></li>
@@ -286,6 +301,12 @@ keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-inde
keywords: <a href="keyword-index.html#TRACE">TRACE</a> <a href="keyword-index.html#CALLGRAPH">CALLGRAPH</a> <br>
<p>Print a timed per-thread callgraph, complete with function parameters and return values. The first parameter names the function probe points to trace. The optional second parameter names the probe points for trigger functions, which acts to enable tracing for only those functions that occur while the current thread is nested within the trigger.</p></li>
</ul>
+<h3><a name="TRACEPOINT">TRACEPOINT</a></h3>
+<ul>
+<li><a href="network/dropwatch.stp">network/dropwatch.stp</a> - Watch Where Socket Buffers are Freed in the Kernel<br>
+keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#FREE">FREE</a> <br>
+<p>Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.</p></li>
+</ul>
<h3><a name="TRAFFIC">TRAFFIC</a></h3>
<ul>
<li><a href="network/nettop.stp">network/nettop.stp</a> - Periodic Listing of Processes Using Network Interfaces<br>
diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt
index 40b5276f..1d5add5f 100644
--- a/testsuite/systemtap.examples/keyword-index.txt
+++ b/testsuite/systemtap.examples/keyword-index.txt
@@ -30,6 +30,15 @@ keywords: io scheduler backtrace
so is the total delay.
+= BUFFER =
+
+network/dropwatch.stp - Watch Where Socket Buffers are Freed in the Kernel
+keywords: network tracepoint buffer free
+
+ Every five seconds the dropwatch.stp script lists the number of
+ socket buffers freed at locations in the kernel.
+
+
= CALLGRAPH =
general/para-callgraph.stp - Callgraph tracing with arguments
@@ -88,6 +97,15 @@ keywords: format
ans_set_color3() function in the ansi.stp tapset.
+= FREE =
+
+network/dropwatch.stp - Watch Where Socket Buffers are Freed in the Kernel
+keywords: network tracepoint buffer free
+
+ Every five seconds the dropwatch.stp script lists the number of
+ socket buffers freed at locations in the kernel.
+
+
= FUNCTIONS =
profiling/functioncallcount.stp - Count Times Functions Called
@@ -251,6 +269,13 @@ keywords: memory
= NETWORK =
+network/dropwatch.stp - Watch Where Socket Buffers are Freed in the Kernel
+keywords: network tracepoint buffer free
+
+ Every five seconds the dropwatch.stp script lists the number of
+ socket buffers freed at locations in the kernel.
+
+
network/nettop.stp - Periodic Listing of Processes Using Network Interfaces
keywords: network traffic per-process
@@ -594,6 +619,15 @@ keywords: trace callgraph
the trigger.
+= TRACEPOINT =
+
+network/dropwatch.stp - Watch Where Socket Buffers are Freed in the Kernel
+keywords: network tracepoint buffer free
+
+ Every five seconds the dropwatch.stp script lists the number of
+ socket buffers freed at locations in the kernel.
+
+
= TRAFFIC =
network/nettop.stp - Periodic Listing of Processes Using Network Interfaces
diff --git a/testsuite/systemtap.examples/network/dropwatch.meta b/testsuite/systemtap.examples/network/dropwatch.meta
new file mode 100644
index 00000000..176ba236
--- /dev/null
+++ b/testsuite/systemtap.examples/network/dropwatch.meta
@@ -0,0 +1,13 @@
+title: Watch Where Socket Buffers are Freed in the Kernel
+name: dropwatch.stp
+version: 1.0
+author: Neil Horman
+keywords: network tracepoint buffer free
+subsystem: network
+status: production
+exit: user-controlled
+output: timed
+scope: system-wide
+description: Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.
+test_check: stap -p4 dropwatch.stp
+test_installcheck: stap dropwatch.stp -c "sleep 1"
diff --git a/testsuite/systemtap.examples/network/dropwatch.stp b/testsuite/systemtap.examples/network/dropwatch.stp
new file mode 100755
index 00000000..79d50a4e
--- /dev/null
+++ b/testsuite/systemtap.examples/network/dropwatch.stp
@@ -0,0 +1,30 @@
+#! /usr/bin/env stap
+
+############################################################
+# Dropwatch.stp
+# Author: Neil Horman <nhorman@redhat.com>
+# An example script to mimic the behavior of the dropwatch utility
+# http://fedorahosted.org/dropwatch
+############################################################
+
+# Array to hold the list of drop points we find
+global locations
+
+# Note when we turn the monitor on and off
+probe begin { printf("Monitoring for dropped packets\n") }
+probe end { printf("Stopping dropped packet monitor\n") }
+
+# increment a drop counter for every location we drop at
+probe kernel.trace("kfree_skb") { locations[$location] <<< 1 }
+
+# Every 5 seconds report our drop locations
+probe timer.sec(5)
+{
+ printf("\n")
+ foreach (l in locations-) {
+ printf("%d packets dropped at location %p\n",
+ @count(locations[l]), l)
+ }
+ delete locations
+}
+
diff --git a/testsuite/systemtap.printf/basic6.exp b/testsuite/systemtap.printf/basic6.exp
new file mode 100644
index 00000000..72bf8f57
--- /dev/null
+++ b/testsuite/systemtap.printf/basic6.exp
@@ -0,0 +1,3 @@
+set test "basic6"
+set ::result_string {Hello%World}
+stap_run2 $srcdir/$subdir/$test.stp
diff --git a/testsuite/systemtap.printf/basic6.stp b/testsuite/systemtap.printf/basic6.stp
new file mode 100644
index 00000000..69721188
--- /dev/null
+++ b/testsuite/systemtap.printf/basic6.stp
@@ -0,0 +1,5 @@
+probe begin
+{
+ printf("Hello%%World");
+ exit()
+}
diff --git a/translate.cxx b/translate.cxx
index d81287ee..f7868ceb 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4172,7 +4172,8 @@ c_unparser::visit_print_format (print_format* e)
int use_print = 0;
string format_string = print_format::components_to_string(components);
- if (tmp.size() == 0 || (tmp.size() == 1 && format_string == "%s"))
+ if ((tmp.size() == 0 && format_string.find("%%") == std::string::npos)
+ || (tmp.size() == 1 && format_string == "%s"))
use_print = 1;
else if (tmp.size() == 1
&& e->args[0]->tok->type == tok_string
@@ -4818,6 +4819,7 @@ dump_unwindsyms (Dwfl_Module *m,
// Emit symbol table & unwind data, plus any calls needed to register
// them with the runtime.
+void emit_symbol_data_done (unwindsym_dump_context*, systemtap_session&);
void
emit_symbol_data (systemtap_session& s)
@@ -4830,6 +4832,14 @@ emit_symbol_data (systemtap_session& s)
unwindsym_dump_context ctx = { s, kallsyms_out, 0, s.unwindsym_modules };
+ // Micro optimization, mainly to speed up tiny regression tests
+ // using just begin probe.
+ if (s.unwindsym_modules.size () == 0)
+ {
+ emit_symbol_data_done(&ctx, s);
+ return;
+ }
+
// XXX: copied from tapsets.cxx dwflpp::, sadly
static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:build";
static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH");
@@ -4922,20 +4932,25 @@ emit_symbol_data (systemtap_session& s)
dwfl_end(dwfl);
}
+ emit_symbol_data_done (&ctx, s);
+}
+void
+emit_symbol_data_done (unwindsym_dump_context *ctx, systemtap_session& s)
+{
// Print out a definition of the runtime's _stp_modules[] globals.
- kallsyms_out << "\n";
- kallsyms_out << "static struct _stp_module *_stp_modules [] = {\n";
- for (unsigned i=0; i<ctx.stp_module_index; i++)
+ ctx->output << "\n";
+ ctx->output << "static struct _stp_module *_stp_modules [] = {\n";
+ for (unsigned i=0; i<ctx->stp_module_index; i++)
{
- kallsyms_out << "& _stp_module_" << i << ",\n";
+ ctx->output << "& _stp_module_" << i << ",\n";
}
- kallsyms_out << "};\n";
- kallsyms_out << "static unsigned _stp_num_modules = " << ctx.stp_module_index << ";\n";
+ ctx->output << "};\n";
+ ctx->output << "static unsigned _stp_num_modules = " << ctx->stp_module_index << ";\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();
+ 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) + "'");