summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-04-27 11:56:15 -0400
committerDave Brolley <brolley@redhat.com>2009-04-27 11:56:15 -0400
commite84f20287ae21b31c3505dfd0a81176687ad1ec5 (patch)
tree956005556406fc93e4444ee0d425aafed8e241d0
parentfb6d28283bd7ea63364a008d32c53687a694642f (diff)
parent097e4a5b397b9e826453e01caa1f8169886128c5 (diff)
downloadsystemtap-steved-e84f20287ae21b31c3505dfd0a81176687ad1ec5.tar.gz
systemtap-steved-e84f20287ae21b31c3505dfd0a81176687ad1ec5.tar.xz
systemtap-steved-e84f20287ae21b31c3505dfd0a81176687ad1ec5.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
Conflicts: configure testsuite/configure
-rw-r--r--AUTHORS2
-rw-r--r--NEWS3
-rwxr-xr-xconfigure20
-rw-r--r--configure.ac2
-rw-r--r--doc/SystemTap_Tapset_Reference/.gitignore3
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.am4
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.in4
-rwxr-xr-xgit_version.sh4
-rw-r--r--grapher/.gitignore1
-rw-r--r--includes/sys/sdt.h28
-rw-r--r--main.cxx80
-rw-r--r--runtime/sym.c51
-rw-r--r--runtime/task_finder.c137
-rw-r--r--runtime/task_finder_map.c191
-rw-r--r--runtime/uprobes/uprobes_i386.c24
-rw-r--r--runtime/vsprintf.c31
-rw-r--r--stap.1.in2
-rw-r--r--systemtap.spec5
-rw-r--r--tapset/string.stp12
-rw-r--r--tapset/syscalls.stp8
-rw-r--r--tapsets.cxx175
-rwxr-xr-xtestsuite/buildok/thirtyone.stp4
-rwxr-xr-xtestsuite/configure20
-rw-r--r--testsuite/configure.ac2
-rw-r--r--testsuite/systemtap.base/badkprobe.exp32
-rw-r--r--testsuite/systemtap.printf/char1.exp2
-rw-r--r--testsuite/systemtap.printf/char1.stp1
-rw-r--r--testsuite/systemtap.printf/memory1.stp14
28 files changed, 592 insertions, 270 deletions
diff --git a/AUTHORS b/AUTHORS
index a6e54c7b..4a9182f9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,12 +35,14 @@ Mike Mason
Nobuhiro Tachino
Phil Muldoon
Prerna Saxena
+Przemyslaw Pawelczyk
Rajan Arora
Roland McGrath
Shaohua Li
Srikar Dronamraju
Srinivasa DS
Stan Cox
+Sunzen Wang
Thang Nguyen
Theodore Ts'o
Tim Moore
diff --git a/NEWS b/NEWS
index 88076db3..6cfd7158 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
* What's new
+
+* What's new in version 0.9.7
+
- @cast can now determine its type information using an explicit header
specification. For example:
@cast(tv, "timeval", "<sys/time.h>")->tv_sec
diff --git a/configure b/configure
index a9887761..73a4e3f4 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for systemtap 0.9.5.
+# Generated by GNU Autoconf 2.61 for systemtap 0.9.7.
#
# Report bugs to <systemtap@sources.redhat.com>.
#
@@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='systemtap'
PACKAGE_TARNAME='systemtap'
-PACKAGE_VERSION='0.9.5'
-PACKAGE_STRING='systemtap 0.9.5'
+PACKAGE_VERSION='0.9.7'
+PACKAGE_STRING='systemtap 0.9.7'
PACKAGE_BUGREPORT='systemtap@sources.redhat.com'
# Factoring default headers for most tests.
@@ -1262,7 +1262,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures systemtap 0.9.5 to adapt to many kinds of systems.
+\`configure' configures systemtap 0.9.7 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1328,7 +1328,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of systemtap 0.9.5:";;
+ short | recursive ) echo "Configuration of systemtap 0.9.7:";;
esac
cat <<\_ACEOF
@@ -1450,7 +1450,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-systemtap configure 0.9.5
+systemtap configure 0.9.7
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1464,7 +1464,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by systemtap $as_me 0.9.5, which was
+It was created by systemtap $as_me 0.9.7, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2156,7 +2156,7 @@ fi
# Define the identity of the package.
PACKAGE='systemtap'
- VERSION='0.9.5'
+ VERSION='0.9.7'
cat >>confdefs.h <<_ACEOF
@@ -8586,7 +8586,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by systemtap $as_me 0.9.5, which was
+This file was extended by systemtap $as_me 0.9.7, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8639,7 +8639,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-systemtap config.status 0.9.5
+systemtap config.status 0.9.7
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.ac b/configure.ac
index 36e87e3d..129583e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl configure.ac --- autoconf input file for systemtap
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([systemtap], 0.9.5, systemtap@sources.redhat.com, systemtap)
+AC_INIT([systemtap], 0.9.7, systemtap@sources.redhat.com, systemtap)
dnl ^^^^^ see also NEWS, systemtap.spec, testsuite/configure.ac
AC_PREREQ(2.59)
diff --git a/doc/SystemTap_Tapset_Reference/.gitignore b/doc/SystemTap_Tapset_Reference/.gitignore
index af43f913..3b7d1c17 100644
--- a/doc/SystemTap_Tapset_Reference/.gitignore
+++ b/doc/SystemTap_Tapset_Reference/.gitignore
@@ -1 +1,4 @@
/docproc
+stamp-*
+tapsets/
+tapsets.xml
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.am b/doc/SystemTap_Tapset_Reference/Makefile.am
index 087ca887..7903b12b 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.am
+++ b/doc/SystemTap_Tapset_Reference/Makefile.am
@@ -34,9 +34,7 @@ stamp-htmldocs: tapsets.xml
# bump up the allocated space so "xmlto pdf" works
tapsets.pdf: tapsets.xml
- export pool_size=2000000
- export hash_size=120000
- xmlto pdf tapsets.xml
+ env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml
stamp-mandocs: tapsets.xml
xmlto man -o man3 tapsets.xml
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in
index bdd7ff20..de4683a3 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.in
+++ b/doc/SystemTap_Tapset_Reference/Makefile.in
@@ -431,9 +431,7 @@ uninstall-am:
# bump up the allocated space so "xmlto pdf" works
@BUILD_REFDOCS_TRUE@tapsets.pdf: tapsets.xml
-@BUILD_REFDOCS_TRUE@ export pool_size=2000000
-@BUILD_REFDOCS_TRUE@ export hash_size=120000
-@BUILD_REFDOCS_TRUE@ xmlto pdf tapsets.xml
+@BUILD_REFDOCS_TRUE@ env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml
@BUILD_REFDOCS_TRUE@stamp-mandocs: tapsets.xml
@BUILD_REFDOCS_TRUE@ xmlto man -o man3 tapsets.xml
diff --git a/git_version.sh b/git_version.sh
index d39d96c9..c9d3dff7 100755
--- a/git_version.sh
+++ b/git_version.sh
@@ -180,7 +180,7 @@ fi
# Detect git tools (should work with old and new git versions)
git_found=yes
-for git_tool in git-symbolic-ref git-rev-parse git-diff-files git-diff-index git
+for git_tool in git-symbolic-ref git-rev-parse git-diff-files git-diff-index git git-describe
do
if [ x`which $git_tool 2>/dev/null` = "x" ]; then
git_found="'$git_tool' not found"
@@ -207,7 +207,7 @@ if [ "x$git_repo_dir" != "x" ] && [ "x${abs_repo_dir}" = "x${abs_srcdir}/.git" ]
git_repo=yes
if [ "x$git_found" = "xyes" ]; then
# git-1.4 and probably earlier understand "git-rev-parse HEAD"
- git_shaid=`git-rev-parse HEAD | $SED -n 's/^\(.\{8\}\).*/\1/p'`
+ git_shaid=`git-describe --long 2>/dev/null || git-describe 2>/dev/null || git-rev-parse HEAD`
if [ "x$git_shaid" = "x" ]; then
git_errors="${git_errors+${git_errors}; }error running 'git-rev-parse HEAD'"
fi
diff --git a/grapher/.gitignore b/grapher/.gitignore
new file mode 100644
index 00000000..2ce2a624
--- /dev/null
+++ b/grapher/.gitignore
@@ -0,0 +1 @@
+grapher
diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h
index c2242303..f89b736a 100644
--- a/includes/sys/sdt.h
+++ b/includes/sys/sdt.h
@@ -58,11 +58,17 @@
#define STAP_UNINLINE_LABEL(label) \
__extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label
+#if defined(__x86_64__) || defined(__i386__)
+#define STAP_NOP "\tnop "
+#else
+#define STAP_NOP "\tnop 0 "
+#endif
+
#define STAP_PROBE_(probe) \
do { \
STAP_PROBE_DATA(probe); \
__asm__ volatile ("2:\n" \
- "\tnop 0"); \
+ STAP_NOP); \
} while (0)
#define STAP_PROBE1_(probe,label,parm1) \
@@ -73,7 +79,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 */" :: "g"(arg1)); \
+ STAP_NOP "/* %0 */" :: "g"(arg1)); \
} while (0)
#define STAP_PROBE2_(probe,label,parm1,parm2) \
@@ -85,7 +91,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 */" :: "g"(arg1), "g"(arg2)); \
+ STAP_NOP "/* %0 %1 */" :: "g"(arg1), "g"(arg2)); \
} while (0)
#define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \
@@ -98,7 +104,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 */" :: "g"(arg1), "g"(arg2), "g"(arg3)); \
+ STAP_NOP "/* %0 %1 %2 */" :: "g"(arg1), "g"(arg2), "g"(arg3)); \
} while (0)
#define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \
@@ -112,7 +118,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 %3 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4)); \
+ STAP_NOP "/* %0 %1 %2 %3 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4)); \
} while (0)
#define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \
@@ -127,7 +133,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 %3 %4 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5)); \
+ STAP_NOP "/* %0 %1 %2 %3 %4 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5)); \
} while (0)
#define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \
@@ -143,7 +149,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 %3 %4 %5 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6)); \
+ STAP_NOP "/* %0 %1 %2 %3 %4 %5 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6)); \
} while (0)
#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \
@@ -160,7 +166,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7)); \
+ STAP_NOP "/* %0 %1 %2 %3 %4 %5 %6 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7)); \
} while (0)
#define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \
@@ -178,7 +184,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8)); \
+ STAP_NOP "/* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8)); \
} while (0)
#define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \
@@ -197,7 +203,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9)); \
+ STAP_NOP "/* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9)); \
} while (0)
#define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \
@@ -217,7 +223,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9), "g"(arg10)); \
+ STAP_NOP "/* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9), "g"(arg10)); \
} while (0)
#define STAP_PROBE(provider,probe) \
diff --git a/main.cxx b/main.cxx
index 745d81e5..aecb2341 100644
--- a/main.cxx
+++ b/main.cxx
@@ -328,6 +328,34 @@ setup_signals (sighandler_t handler)
sigaction (SIGTERM, &sa, NULL);
}
+void
+setup_kernel_release (systemtap_session &s, const char* kstr) {
+ if (kstr[0] == '/') // fully specified path
+ {
+ s.kernel_build_tree = kstr;
+ 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 (kstr);
+ s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build";
+ }
+}
int
main (int argc, char * const argv [])
@@ -439,31 +467,7 @@ main (int argc, char * const argv [])
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";
- }
+ setup_kernel_release(s, s_kr);
}
@@ -605,31 +609,7 @@ main (int argc, char * const argv [])
break;
case 'r':
- if (optarg[0] == '/') // fully specified path
- {
- s.kernel_build_tree = optarg;
- 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;
- usage (s, 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 (optarg);
- s.kernel_build_tree = "/lib/modules/" + s.kernel_release + "/build";
- }
+ setup_kernel_release(s, optarg);
break;
case 'k':
diff --git a/runtime/sym.c b/runtime/sym.c
index 013edd0c..63dad1af 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -271,34 +271,29 @@ static int _stp_module_check(void)
dwfl_module_build_id was not intended to return the end address. */
notes_addr -= m->build_id_len;
- if (notes_addr > base_addr) {
- for (j = 0; j < m->build_id_len; j++)
- {
- unsigned char theory, practice;
- theory = m->build_id_bits [j];
- practice = ((unsigned char*) notes_addr) [j];
- /* XXX: consider using kread() instead of above. */
- if (theory != practice)
- {
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
- _stp_error ("%s: inconsistent %s build-id byte #%d "
- "(0x%x [actual] vs. 0x%x [debuginfo])\n",
- THIS_MODULE->name, m->name, j,
- practice, theory);
- return 1;
- #else
- /* This branch is a surrogate for
- kernels affected by Fedora bug
- #465873. */
- printk(KERN_WARNING
- "%s: inconsistent %s build-id byte #%d "
- "(0x%x [actual] vs. 0x%x [debuginfo])\n",
- THIS_MODULE->name, m->name, j,
- practice, theory);
- break; /* Note just the first mismatch. */
- #endif
- }
- }
+ if (notes_addr <= base_addr) /* shouldn't happen */
+ continue;
+ if (memcmp(m->build_id_bits, (unsigned char*) notes_addr, m->build_id_len)) {
+ const char *basename;
+
+ basename = strrchr(m->path, '/');
+ if (basename)
+ basename++;
+ else
+ basename = m->path;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ _stp_error ("Build-id mismatch: \"%s\" %.*M"
+ " vs. \"%s\" %.*M\n",
+ m->name, m->build_id_len, notes_addr,
+ basename, m->build_id_len, m->build_id_bits);
+ return 1;
+#else
+ /* This branch is a surrogate for kernels
+ * affected by Fedora bug #465873. */
+ printk(KERN_WARNING
+ "Build-id mismatch: \"%s\" vs. \"%s\"\n",
+ m->name, basename);
+#endif
}
} /* end checking */
} /* end loop */
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 93b89cb9..f5e059ca 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -19,6 +19,7 @@ struct stap_task_finder_target { };
#include "syscall.h"
#include "utrace_compatibility.h"
+#include "task_finder_map.c"
static LIST_HEAD(__stp_task_finder_list);
@@ -129,6 +130,19 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action,
#ifdef UTRACE_ORIG_VERSION
static u32
+__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs);
+#else
+static u32
+__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
+ struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs);
+#endif
+
+#ifdef UTRACE_ORIG_VERSION
+static u32
__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
struct task_struct *tsk,
struct pt_regs *regs);
@@ -166,6 +180,8 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt)
memset(&new_tgt->ops, 0, sizeof(new_tgt->ops));
new_tgt->ops.report_death = &__stp_utrace_task_finder_target_death;
new_tgt->ops.report_quiesce = &__stp_utrace_task_finder_target_quiesce;
+ new_tgt->ops.report_syscall_entry = \
+ &__stp_utrace_task_finder_target_syscall_entry;
new_tgt->ops.report_syscall_exit = \
&__stp_utrace_task_finder_target_syscall_exit;
@@ -394,6 +410,7 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
#define __STP_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH))
#define __STP_TASK_VM_BASE_EVENTS (__STP_TASK_BASE_EVENTS \
+ | UTRACE_EVENT(SYSCALL_ENTRY)\
| UTRACE_EVENT(SYSCALL_EXIT))
/*
@@ -1053,24 +1070,21 @@ __stp_find_file_based_vma(struct mm_struct *mm, unsigned long addr)
#ifdef UTRACE_ORIG_VERSION
static u32
-__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
+__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs)
#else
static u32
-__stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
- struct utrace_attached_engine *engine,
- struct task_struct *tsk,
- struct pt_regs *regs)
+__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
+ struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs)
#endif
{
struct stap_task_finder_target *tgt = engine->data;
long syscall_no;
- unsigned long rv;
- unsigned long args[3];
+ unsigned long args[3] = { 0L };
int rc;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
debug_task_finder_detach();
@@ -1100,37 +1114,92 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
&& tgt->munmap_events == 0))
return UTRACE_RESUME;
+ __stp_tf_handler_start();
+ if (syscall_no == MUNMAP_SYSCALL_NO(tsk)) {
+ // We need 2 arguments
+ syscall_get_arguments(tsk, regs, 0, 2, args);
+ }
+ else if (syscall_no == MMAP_SYSCALL_NO(tsk)
+ || syscall_no == MMAP2_SYSCALL_NO(tsk)) {
+ // For mmap, we really just need the return value, so
+ // there is no need to save arguments
+ }
+ else { // mprotect()
+ // We need 3 arguments
+ syscall_get_arguments(tsk, regs, 0, 3, args);
+ }
+
+ // Remember the syscall information
+ rc = __stp_tf_add_map(tsk, syscall_no, args[0], args[1], args[2]);
+ if (rc != 0)
+ _stp_error("__stp_tf_add_map returned error %d on pid %d",
+ rc, tsk->pid);
+ __stp_tf_handler_end();
+ return UTRACE_RESUME;
+}
+
+#ifdef UTRACE_ORIG_VERSION
+static u32
+__stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs)
+#else
+static u32
+__stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
+ struct utrace_attached_engine *engine,
+ struct task_struct *tsk,
+ struct pt_regs *regs)
+#endif
+{
+ struct stap_task_finder_target *tgt = engine->data;
+ unsigned long rv;
+ struct __stp_tf_map_entry *entry;
+
+ if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
+ debug_task_finder_detach();
+ return UTRACE_DETACH;
+ }
+
+ if (tgt == NULL)
+ return UTRACE_RESUME;
+
+ // See if we can find saved syscall info. If we can, it must
+ // be one of the syscalls we are interested in (and we must
+ // have callbacks to call for it).
+ entry = __stp_tf_get_map_entry(tsk);
+ if (entry == NULL)
+ return UTRACE_RESUME;
+
// Get return value
+ __stp_tf_handler_start();
rv = syscall_get_return_value(tsk, regs);
- // We need the first syscall argument to see what address we
- // were operating on.
- syscall_get_arguments(tsk, regs, 0, 1, args);
-
#ifdef DEBUG_TASK_FINDER_VMA
_stp_dbug(__FUNCTION__, __LINE__,
"tsk %d found %s(0x%lx), returned 0x%lx\n",
tsk->pid,
- ((syscall_no == MMAP_SYSCALL_NO(tsk)) ? "mmap"
- : ((syscall_no == MMAP2_SYSCALL_NO(tsk)) ? "mmap2"
- : ((syscall_no == MPROTECT_SYSCALL_NO(tsk)) ? "mprotect"
- : ((syscall_no == MUNMAP_SYSCALL_NO(tsk)) ? "munmap"
+ ((entry->syscall_no == MMAP_SYSCALL_NO(tsk)) ? "mmap"
+ : ((entry->syscall_no == MMAP2_SYSCALL_NO(tsk)) ? "mmap2"
+ : ((entry->syscall_no == MPROTECT_SYSCALL_NO(tsk))
+ ? "mprotect"
+ : ((entry->syscall_no == MUNMAP_SYSCALL_NO(tsk))
+ ? "munmap"
: "UNKNOWN")))),
- args[0], rv);
+ entry->arg0, rv);
#endif
- __stp_tf_handler_start();
- if (syscall_no == MUNMAP_SYSCALL_NO(tsk)) {
- // We need the 2nd syscall argument for the length.
- syscall_get_arguments(tsk, regs, 1, 1, &args[1]);
+ if (entry->syscall_no == MUNMAP_SYSCALL_NO(tsk)) {
// Call the callbacks
- __stp_call_munmap_callbacks(tgt, tsk, args[0], args[1]);
+ __stp_call_munmap_callbacks(tgt, tsk, entry->arg0, entry->arg1);
}
- else if (syscall_no == MMAP_SYSCALL_NO(tsk)
- || syscall_no == MMAP2_SYSCALL_NO(tsk)) {
+ else if (entry->syscall_no == MMAP_SYSCALL_NO(tsk)
+ || entry->syscall_no == MMAP2_SYSCALL_NO(tsk)) {
+ struct mm_struct *mm;
mm = get_task_mm(tsk);
if (mm) {
+ struct vm_area_struct *vma;
+
down_read(&mm->mmap_sem);
vma = __stp_find_file_based_vma(mm, rv);
@@ -1144,18 +1213,14 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
mmput(mm);
}
}
- else {
- // We need the 2nd syscall argument for the length and
- // the 3rd argument for the protection.
- syscall_get_arguments(tsk, regs, 1, 2, &args[1]);
-
+ else { // mprotect
// Call the callbacks
- __stp_call_mprotect_callbacks(tgt, tsk, args[0], args[1],
- args[2]);
+ __stp_call_mprotect_callbacks(tgt, tsk, entry->arg0,
+ entry->arg1, entry->arg2);
}
-syscall_exit_done:
__stp_tf_handler_end();
+ __stp_tf_remove_map_entry(entry);
return UTRACE_RESUME;
}
@@ -1179,6 +1244,8 @@ stap_start_task_finder(void)
return ENOMEM;
}
+ __stp_tf_map_initialize();
+
atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING);
rcu_read_lock();
diff --git a/runtime/task_finder_map.c b/runtime/task_finder_map.c
new file mode 100644
index 00000000..b770dd0e
--- /dev/null
+++ b/runtime/task_finder_map.c
@@ -0,0 +1,191 @@
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/spinlock.h>
+
+// When handling mmap()/munmap()/mprotect() syscall tracing to notice
+// memory map changes, we need to cache syscall entry parameter values
+// for processing at syscall exit.
+
+// __stp_tf_map_lock protects the hash table.
+// Documentation/spinlocks.txt suggest we can be a bit more clever
+// if we guarantee that in interrupt context we only read, not write
+// the datastructures. We should never change the hash table or the
+// contents in interrupt context (which should only ever call
+// stap_find_map_map_info for getting stored info). So we might
+// want to look into that if this seems a bottleneck.
+static DEFINE_RWLOCK(__stp_tf_map_lock);
+
+#define __STP_TF_HASH_BITS 4
+#define __STP_TF_TABLE_SIZE (1 << __STP_TF_HASH_BITS)
+
+#ifndef TASK_FINDER_MAP_ENTRY_ITEMS
+#define TASK_FINDER_MAP_ENTRY_ITEMS 100
+#endif
+
+struct __stp_tf_map_entry {
+/* private: */
+ struct hlist_node hlist;
+ int usage;
+
+/* public: */
+ pid_t pid;
+ long syscall_no;
+ unsigned long arg0;
+ unsigned long arg1;
+ unsigned long arg2;
+};
+
+static struct __stp_tf_map_entry
+__stp_tf_map_free_list_items[TASK_FINDER_MAP_ENTRY_ITEMS];
+
+static struct hlist_head __stp_tf_map_free_list[1];
+
+static struct hlist_head __stp_tf_map_table[__STP_TF_TABLE_SIZE];
+
+// __stp_tf_map_initialize(): Initialize the free list. Grabs the
+// lock.
+static void
+__stp_tf_map_initialize(void)
+{
+ int i;
+ struct hlist_head *head = &__stp_tf_map_free_list[0];
+
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_map_lock, flags);
+ for (i = 0; i < TASK_FINDER_MAP_ENTRY_ITEMS; i++) {
+ hlist_add_head(&__stp_tf_map_free_list_items[i].hlist, head);
+ }
+ write_unlock_irqrestore(&__stp_tf_map_lock, flags);
+}
+
+
+// __stp_tf_map_get_free_entry(): Returns an entry from the free list
+// or NULL. The __stp_tf_map_lock must be write locked before calling this
+// function.
+static struct __stp_tf_map_entry *
+__stp_tf_map_get_free_entry(void)
+{
+ struct hlist_head *head = &__stp_tf_map_free_list[0];
+ struct hlist_node *node;
+ struct __stp_tf_map_entry *entry = NULL;
+
+ if (hlist_empty(head))
+ return NULL;
+ hlist_for_each_entry(entry, node, head, hlist) {
+ break;
+ }
+ if (entry != NULL)
+ hlist_del(&entry->hlist);
+ return entry;
+}
+
+
+// __stp_tf_map_put_free_entry(): Puts an entry back on the free
+// list. The __stp_tf_map_lock must be write locked before calling this
+// function.
+static void
+__stp_tf_map_put_free_entry(struct __stp_tf_map_entry *entry)
+{
+ struct hlist_head *head = &__stp_tf_map_free_list[0];
+ hlist_add_head(&entry->hlist, head);
+}
+
+
+// __stp_tf_map_hash(): Compute the map hash.
+static inline u32
+__stp_tf_map_hash(struct task_struct *tsk)
+{
+ return (jhash_1word(tsk->pid, 0) & (__STP_TF_TABLE_SIZE - 1));
+}
+
+
+// Get map_entry if the map is present in the map hash table.
+// Returns NULL if not present. Takes a read lock on __stp_tf_map_lock.
+static struct __stp_tf_map_entry *
+__stp_tf_get_map_entry(struct task_struct *tsk)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct __stp_tf_map_entry *entry;
+
+ unsigned long flags;
+ read_lock_irqsave(&__stp_tf_map_lock, flags);
+ head = &__stp_tf_map_table[__stp_tf_map_hash(tsk)];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ if (tsk->pid == entry->pid) {
+ read_unlock_irqrestore(&__stp_tf_map_lock, flags);
+ return entry;
+ }
+ }
+ read_unlock_irqrestore(&__stp_tf_map_lock, flags);
+ return NULL;
+}
+
+
+// Add the map info to the map hash table. Takes a write lock on
+// __stp_tf_map_lock.
+static int
+__stp_tf_add_map(struct task_struct *tsk, long syscall_no, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct __stp_tf_map_entry *entry;
+ unsigned long flags;
+
+ write_lock_irqsave(&__stp_tf_map_lock, flags);
+ head = &__stp_tf_map_table[__stp_tf_map_hash(tsk)];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ // If we find an existing entry, just increment the
+ // usage count.
+ if (tsk->pid == entry->pid) {
+ entry->usage++;
+ write_unlock_irqrestore(&__stp_tf_map_lock, flags);
+ return 0;
+ }
+ }
+
+ // Get an element from the free list.
+ entry = __stp_tf_map_get_free_entry();
+ if (!entry) {
+ write_unlock_irqrestore(&__stp_tf_map_lock, flags);
+ return -ENOMEM;
+ }
+ entry->usage = 1;
+ entry->pid = tsk->pid;
+ entry->syscall_no = syscall_no;
+ entry->arg0 = arg0;
+ entry->arg1 = arg1;
+ entry->arg2 = arg2;
+ hlist_add_head(&entry->hlist, head);
+ write_unlock_irqrestore(&__stp_tf_map_lock, flags);
+ return 0;
+}
+
+
+// Remove the map entry from the map hash table. Takes a write lock on
+// __stp_tf_map_lock.
+static int
+__stp_tf_remove_map_entry(struct __stp_tf_map_entry *entry)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ int found = 0;
+
+ if (entry != NULL) {
+ unsigned long flags;
+ write_lock_irqsave(&__stp_tf_map_lock, flags);
+
+ // Decrement the usage count.
+ entry->usage--;
+
+ // If the entry is unused, put it back on the free
+ // list.
+ if (entry->usage == 0) {
+ hlist_del(&entry->hlist);
+ __stp_tf_map_put_free_entry(entry);
+ }
+ write_unlock_irqrestore(&__stp_tf_map_lock, flags);
+ }
+ return 0;
+}
diff --git a/runtime/uprobes/uprobes_i386.c b/runtime/uprobes/uprobes_i386.c
index 7743f400..008f32de 100644
--- a/runtime/uprobes/uprobes_i386.c
+++ b/runtime/uprobes/uprobes_i386.c
@@ -58,22 +58,22 @@
static const unsigned long good_2byte_insns[256 / 32] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ------------------------------- */
- W(0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 00 */
- W(0x10, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 10 */
- W(0x20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 20 */
- W(0x30, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 30 */
- W(0x40, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 40 */
- W(0x50, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 50 */
- W(0x60, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 60 */
- W(0x70, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 70 */
+ W(0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1)| /* 00 */
+ W(0x10, 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1), /* 10 */
+ W(0x20, 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1)| /* 20 */
+ W(0x30, 0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0), /* 30 */
+ W(0x40, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 40 */
+ W(0x50, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* 50 */
+ W(0x60, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 60 */
+ W(0x70, 1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1), /* 70 */
W(0x80, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 80 */
W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* 90 */
W(0xa0, 1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,1)| /* a0 */
W(0xb0, 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1), /* b0 */
- W(0xc0, 1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1)| /* c0 */
- W(0xd0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* d0 */
- W(0xe0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* e0 */
- W(0xf0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) /* f0 */
+ W(0xc0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* c0 */
+ W(0xd0, 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* d0 */
+ W(0xe0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* e0 */
+ W(0xf0, 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0) /* f0 */
/* ------------------------------- */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
diff --git a/runtime/vsprintf.c b/runtime/vsprintf.c
index 38ab0e2d..23810e75 100644
--- a/runtime/vsprintf.c
+++ b/runtime/vsprintf.c
@@ -361,18 +361,16 @@ static int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
else
len = 1;
+ if (*fmt_copy == 'M')
+ len = len * 2; /* hex dump print size */
+
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;
- }
+
+ num_bytes += len;
while (len < field_width--) {
num_bytes++;
@@ -636,16 +634,25 @@ static int _stp_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
len = 1;
if (!(flags & STP_LEFT)) {
- while (len < field_width--) {
+ int actlen = len;
+ if (*fmt == 'M')
+ actlen = len * 2;
+ while (actlen < field_width--) {
if (str <= end)
*str = ' ';
++str;
}
}
- if (*fmt == 'M') {
- str = number(str, str + len - 1 < end ? str + len - 1 : end,
- (unsigned long) *(uint64_t *) s,
- 16, field_width, len, flags);
+ if (*fmt == 'M') { /* stolen from kernel: trace_seq_putmem_hex() */
+ const char _stp_hex_asc[] = "0123456789abcdef";
+ int j;
+ for (i = 0, j = 0; i < len; i++) {
+ *str = _stp_hex_asc[((*s) & 0xf0) >> 4];
+ str++;
+ *str = _stp_hex_asc[((*s) & 0x0f)];
+ str++; s++;
+ }
+ len = len * 2; /* the actual length */
}
else {
for (i = 0; i < len; ++i) {
diff --git a/stap.1.in b/stap.1.in
index aed473d7..a8609d6f 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -674,7 +674,7 @@ Signed decimal.
Safely reads kernel memory at the given address, outputs its content. The precision specifier determines the number of bytes to read. Default is 1 byte.
.TP
%M
-Same as %m, but outputs in hexadecimal. The precision specifier determines the number of hexadecimal digits to output. Default is 1 digit.
+Same as %m, but outputs in hexadecimal. The minimal size of output is double the precision specifier.
.TP
%o
Unsigned octal.
diff --git a/systemtap.spec b/systemtap.spec
index 3ef7485b..a28940b9 100644
--- a/systemtap.spec
+++ b/systemtap.spec
@@ -6,7 +6,7 @@
%{!?pie_supported: %define pie_supported 1}
Name: systemtap
-Version: 0.9.5
+Version: 0.9.7
Release: 1%{?dist}
# for version, see also configure.ac
Summary: Instrumentation System
@@ -328,6 +328,9 @@ exit 0
%changelog
+* Thu Apr 23 2009 Josh Stone <jistone@redhat.com> - 0.9.7-1
+- Upstream release.
+
* Fri Mar 27 2009 Josh Stone <jistone@redhat.com> - 0.9.5-1
- Upstream release.
diff --git a/tapset/string.stp b/tapset/string.stp
index 2f43aecc..35ee9fa2 100644
--- a/tapset/string.stp
+++ b/tapset/string.stp
@@ -25,6 +25,18 @@ function substr:string(str:string,start:long, length:long) %{ /* pure */
strlcpy(THIS->__retvalue, THIS->str + THIS->start, length);
%}
+/** @addtogroup library
+* @code function stringat:string(str:string, pos:long) @endcode
+* @param str string
+* @param pos the given position. 0 = start of the string
+* @return Returns the char in given position of string.
+*/
+function stringat:long(str:string, pos:long) %{ /* pure */
+ if (THIS->pos >= 0 && THIS->pos < strlen(THIS->str))
+ THIS->__retvalue = THIS->str[THIS->pos];
+ else
+ THIS->__retvalue = 0;
+%}
/** @addtogroup library
* @code isinstr:long(s1:string,s2:string) @endcode
diff --git a/tapset/syscalls.stp b/tapset/syscalls.stp
index 256174d3..a215dc12 100644
--- a/tapset/syscalls.stp
+++ b/tapset/syscalls.stp
@@ -733,7 +733,7 @@ probe syscall.faccessat.return = kernel.function("SyS_faccessat").return !,
probe syscall.fadvise64 = kernel.function("SyS_fadvise64") !,
kernel.function("sys_fadvise64") ? {
name = "fadvise64"
- fs = $fd
+ fd = $fd
offset = $offset
len = $len
advice = $advice
@@ -751,7 +751,7 @@ probe syscall.fadvise64.return = kernel.function("SyS_fadvise64").return !,
probe syscall.fadvise64_64 = kernel.function("SyS_fadvise64_64") !,
kernel.function("sys_fadvise64_64") ? {
name = "fadvise64_64"
- fs = $fd
+ fd = $fd
offset = $offset
len = $len
advice = $advice
@@ -771,7 +771,7 @@ probe syscall.fadvise64_64.return = kernel.function("SyS_fadvise64_64").return !
probe syscall.fadvise64 = kernel.function("SyS_fadvise64") !,
kernel.function("sys_fadvise64") {
name = "fadvise64"
- fs = 0
+ fd = 0
offset = 0
len = 0
advice = 0
@@ -789,7 +789,7 @@ probe syscall.fadvise64.return = kernel.function("SyS_fadvise64").return !,
probe syscall.fadvise64_64 = kernel.function("SyS_fadvise64_64") !,
kernel.function("sys_fadvise64_64") {
name = "fadvise64_64"
- fs = 0
+ fd = 0
offset = 0
len = 0
advice = 0
diff --git a/tapsets.cxx b/tapsets.cxx
index fd991787..01b2a45b 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2638,7 +2638,9 @@ struct kprobe_derived_probe: public derived_probe
const string& name,
int64_t stmt_addr,
bool has_return,
- bool has_statement
+ bool has_statement,
+ bool has_maxactive,
+ long maxactive_val
);
string symbol_name;
Dwarf_Addr addr;
@@ -8339,14 +8341,17 @@ static string TOK_KPROBE("kprobe");
kprobe_derived_probe::kprobe_derived_probe (probe *base,
probe_point *location,
- const string& name,
+ const string& name,
int64_t stmt_addr,
- bool if_return,
- bool if_statement
-):
+ bool has_return,
+ bool has_statement,
+ bool has_maxactive,
+ long maxactive_val
+ ):
derived_probe (base, location),
symbol_name (name), addr (stmt_addr),
- has_return (if_return), has_statement (if_statement)
+ has_return (has_return), has_statement (has_statement),
+ has_maxactive (has_maxactive), maxactive_val (maxactive_val)
{
this->tok = base->tok;
this->access_var = false;
@@ -8355,11 +8360,35 @@ kprobe_derived_probe::kprobe_derived_probe (probe *base,
#define USHRT_MAX 32767
#endif
- // Expansion of $target variables in the probe body produces an error during translate phase
+ // Expansion of $target variables in the probe body produces an error during
+ // translate phase, since we're not using debuginfo
+
vector<probe_point::component*> comps;
+ comps.push_back (new probe_point::component(TOK_KPROBE));
+
+ if (has_statement)
+ {
+ comps.push_back (new probe_point::component(TOK_STATEMENT, new literal_number(addr)));
+ comps.push_back (new probe_point::component(TOK_ABSOLUTE));
+ }
+ else
+ {
+ size_t pos = name.find(':');
+ if (pos != string::npos)
+ {
+ string module = name.substr(0, pos);
+ string function = name.substr(pos + 1);
+ comps.push_back (new probe_point::component(TOK_MODULE, new literal_string(module)));
+ comps.push_back (new probe_point::component(TOK_FUNCTION, new literal_string(function)));
+ }
+ else
+ comps.push_back (new probe_point::component(TOK_FUNCTION, new literal_string(name)));
+ }
if (has_return)
- comps.push_back (new probe_point::component(TOK_RETURN));
+ comps.push_back (new probe_point::component(TOK_RETURN));
+ if (has_maxactive)
+ comps.push_back (new probe_point::component(TOK_MAXACTIVE, new literal_number(maxactive_val)));
this->sole_location()->components = comps;
}
@@ -8400,9 +8429,9 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline();
// Forward declare the master entry functions
- s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,";
+ s.op->newline() << "static int enter_kprobe2_probe (struct kprobe *inst,";
s.op->line() << " struct pt_regs *regs);";
- s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,";
+ s.op->newline() << "static int enter_kretprobe2_probe (struct kretprobe_instance *inst,";
s.op->line() << " struct pt_regs *regs);";
// Emit an array of kprobe/kretprobe pointers
@@ -8423,7 +8452,6 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "static struct stap_dwarfless_probe {";
s.op->newline(1) << "const unsigned return_p:1;";
s.op->newline() << "const unsigned maxactive_p:1;";
- s.op->newline() << "const unsigned statement_p:1;";
s.op->newline() << "unsigned registered_p:1;";
s.op->newline() << "const unsigned short maxactive_val;";
@@ -8469,17 +8497,11 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
assert (p->maxactive_val >= 0 && p->maxactive_val <= USHRT_MAX);
s.op->line() << " .maxactive_val=" << p->maxactive_val << ",";
}
+
if (p->has_statement)
- {
- s.op->line() << " .statement_p=1,";
- s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
- s.op->line() << " .symbol_string=\"" << "\",";
- }
+ s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
else
- {
- s.op->line() << " .address=(unsigned long)0x" << hex << 0 << dec << "ULL,";
- s.op->line() << " .symbol_string=\"" << p->symbol_name << "\",";
- }
+ s.op->line() << " .symbol_string=\"" << p->symbol_name << "\",";
s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
s.op->line() << " .ph=&" << p->name;
@@ -8490,7 +8512,7 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// Emit the kprobes callback function
s.op->newline();
- s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,";
+ s.op->newline() << "static int enter_kprobe2_probe (struct kprobe *inst,";
s.op->line() << " struct pt_regs *regs) {";
// NB: as of PR5673, the kprobe|kretprobe union struct is in BSS
s.op->newline(1) << "int kprobe_idx = ((uintptr_t)inst-(uintptr_t)stap_dwarfless_kprobes)/sizeof(struct stap_dwarfless_kprobe);";
@@ -8509,7 +8531,7 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
// Same for kretprobes
s.op->newline();
- s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,";
+ s.op->newline() << "static int enter_kretprobe2_probe (struct kretprobe_instance *inst,";
s.op->line() << " struct pt_regs *regs) {";
s.op->newline(1) << "struct kretprobe *krp = inst->rp;";
@@ -8535,32 +8557,26 @@ kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
void
kprobe_derived_probe_group::emit_module_init (systemtap_session& s)
{
-#define CHECK_STMT(var) \
- s.op->newline() << "if (sdp->statement_p) {"; \
- s.op->newline() << var << ".symbol_name = NULL;"; \
- s.op->newline() << "} else {"; \
- s.op->newline() << var << ".symbol_name = sdp->symbol_string;"; \
- s.op->newline() << "}";
-
s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
- s.op->newline() << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
+ s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
- s.op->newline() << "unsigned long relocated_addr = sdp->address;";
+ s.op->newline() << "void *addr = (void *) sdp->address;";
+ s.op->newline() << "const char *symbol_name = addr ? NULL : sdp->symbol_string;";
s.op->newline() << "probe_point = sdp->pp;"; // for error messages
s.op->newline() << "if (sdp->return_p) {";
- s.op->newline(1) << "kp->u.krp.kp.addr = (void *) relocated_addr;";
- CHECK_STMT("kp->u.krp.kp");
+ s.op->newline(1) << "kp->u.krp.kp.addr = addr;";
+ s.op->newline() << "kp->u.krp.kp.symbol_name = (char *) symbol_name;";
s.op->newline() << "if (sdp->maxactive_p) {";
s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;";
s.op->newline(-1) << "} else {";
s.op->newline(1) << "kp->u.krp.maxactive = max(10, 4*NR_CPUS);";
s.op->newline(-1) << "}";
- s.op->newline() << "kp->u.krp.handler = &enter_kretprobe_probe;";
+ s.op->newline() << "kp->u.krp.handler = &enter_kretprobe2_probe;";
// to ensure safeness of bspcache, always use aggr_kprobe on ia64
s.op->newline() << "#ifdef __ia64__";
- s.op->newline() << "kp->dummy.pre_handler = NULL;";
s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;";
- CHECK_STMT("kp->dummy");
+ s.op->newline() << "kp->dummy.symbol_name = kp->u.krp.kp.symbol_name;";
+ s.op->newline() << "kp->dummy.pre_handler = NULL;";
s.op->newline() << "rc = register_kprobe (& kp->dummy);";
s.op->newline() << "if (rc == 0) {";
s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);";
@@ -8572,13 +8588,13 @@ kprobe_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline() << "#endif";
s.op->newline(-1) << "} else {";
// to ensure safeness of bspcache, always use aggr_kprobe on ia64
- s.op->newline(1) << "kp->u.kp.addr = (void *) relocated_addr;";
- CHECK_STMT("kp->u.kp");
- s.op->newline(1) << "kp->u.kp.pre_handler = &enter_kprobe_probe;";
+ s.op->newline(1) << "kp->u.kp.addr = addr;";
+ s.op->newline() << "kp->u.kp.symbol_name = (char *) symbol_name;";
+ s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe2_probe;";
s.op->newline() << "#ifdef __ia64__";
- s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;";
s.op->newline() << "kp->dummy.pre_handler = NULL;";
- CHECK_STMT("kp->dummy");
+ s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;";
+ s.op->newline() << "kp->dummy.symbol_name = kp->u.kp.symbol_name;";
s.op->newline() << "rc = register_kprobe (& kp->dummy);";
s.op->newline() << "if (rc == 0) {";
s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);";
@@ -8591,21 +8607,13 @@ kprobe_derived_probe_group::emit_module_init (systemtap_session& s)
s.op->newline(-1) << "}";
s.op->newline() << "if (rc) {"; // PR6749: tolerate a failed register_*probe.
s.op->newline(1) << "sdp->registered_p = 0;";
- s.op->newline() << "if (rc == -EINVAL)";
- s.op->newline() << "{";
- s.op->newline() << " _stp_error (\"Error registering kprobe,possibly an incorrect name %s OR addr = %p, rc = %d \", sdp->symbol_string, sdp->address, rc);";
- s.op->newline() << " atomic_set (&session_state, STAP_SESSION_ERROR);";
- s.op->newline() << " goto out;";
- s.op->newline() << "}";
- s.op->newline() << "else";
- s.op->newline() << "_stp_warn (\"probe %s for %s registration error (rc %d)\", probe_point, sdp->pp, rc);";
+ s.op->newline() << "_stp_warn (\"probe %s registration error (rc %d)\", probe_point, rc);";
s.op->newline() << "rc = 0;"; // continue with other probes
// XXX: shall we increment numskipped?
s.op->newline(-1) << "}";
s.op->newline() << "else sdp->registered_p = 1;";
s.op->newline(-1) << "}"; // for loop
-#undef CHECK_STMT
}
void
@@ -8697,36 +8705,46 @@ kprobe_builder::build(systemtap_session & sess,
vector<derived_probe *> & finished_results)
{
string function_string_val, module_string_val;
- int64_t statement_num_val = 0;
- bool has_function_str, has_module_str, has_statement_num, has_absolute, has_return;
+ int64_t statement_num_val = 0, maxactive_val = 0;
+ bool has_function_str, has_module_str, has_statement_num;
+ bool has_absolute, has_return, has_maxactive;
- has_function_str = this->get_param(parameters, TOK_FUNCTION, function_string_val);
- has_module_str = this->get_param(parameters, TOK_MODULE, module_string_val);
- has_return = this->has_null_param (parameters, TOK_RETURN);
- has_statement_num = this->get_param(parameters, TOK_STATEMENT, statement_num_val);
- has_absolute = this->has_null_param (parameters, TOK_ABSOLUTE);
+ has_function_str = get_param(parameters, TOK_FUNCTION, function_string_val);
+ has_module_str = get_param(parameters, TOK_MODULE, module_string_val);
+ has_return = has_null_param (parameters, TOK_RETURN);
+ has_maxactive = get_param(parameters, TOK_MAXACTIVE, maxactive_val);
+ has_statement_num = get_param(parameters, TOK_STATEMENT, statement_num_val);
+ has_absolute = has_null_param (parameters, TOK_ABSOLUTE);
- if ( has_function_str )
- {
- if ( has_module_str )
- function_string_val = module_string_val + ":" + function_string_val;
- finished_results.push_back ( new kprobe_derived_probe ( base,
- location, function_string_val,
- 0, has_return,
- has_statement_num) );
- }
+ if (has_function_str)
+ {
+ if (has_module_str)
+ function_string_val = module_string_val + ":" + function_string_val;
+
+ finished_results.push_back (new kprobe_derived_probe (base,
+ location, function_string_val,
+ 0, has_return,
+ has_statement_num,
+ has_maxactive,
+ maxactive_val));
+ }
else
- {
- // assert guru mode for absolute probes
- if ( has_statement_num && has_absolute && !base->privileged )
- throw semantic_error ("absolute statement probe in unprivileged script", base->tok);
-
- finished_results.push_back(new kprobe_derived_probe ( base,
- location,"",
- statement_num_val, has_return,
- has_statement_num));
- }
+ {
+ // assert guru mode for absolute probes
+ if ( has_statement_num && has_absolute && !base->privileged )
+ throw semantic_error ("absolute statement probe in unprivileged script", base->tok);
+
+ finished_results.push_back (new kprobe_derived_probe (base,
+ location, "",
+ statement_num_val,
+ has_return,
+ has_statement_num,
+ has_maxactive,
+ maxactive_val));
+ }
}
+
+
// ------------------------------------------------------------------------
// timer derived probes
// ------------------------------------------------------------------------
@@ -11884,8 +11902,13 @@ register_standard_tapsets(systemtap_session & s)
->bind_str(TOK_FUNCTION)->bind(new kprobe_builder());
s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)
->bind(new kprobe_builder());
+ s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)
+ ->bind_num(TOK_MAXACTIVE)->bind(new kprobe_builder());
s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)->bind(new kprobe_builder());
+ s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
+ ->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)
+ ->bind_num(TOK_MAXACTIVE)->bind(new kprobe_builder());
s.pattern_root->bind(TOK_KPROBE)->bind_num(TOK_STATEMENT)
->bind(TOK_ABSOLUTE)->bind(new kprobe_builder());
}
diff --git a/testsuite/buildok/thirtyone.stp b/testsuite/buildok/thirtyone.stp
new file mode 100755
index 00000000..8a97d84f
--- /dev/null
+++ b/testsuite/buildok/thirtyone.stp
@@ -0,0 +1,4 @@
+#! stap -p4
+
+probe kprobe.function("sys_open") {}
+probe kernel.function("sys_close") {}
diff --git a/testsuite/configure b/testsuite/configure
index 828f8006..cc73571a 100755
--- a/testsuite/configure
+++ b/testsuite/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for systemtap 0.9.5.
+# Generated by GNU Autoconf 2.61 for systemtap 0.9.7.
#
# Report bugs to <systemtap@sources.redhat.com>.
#
@@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='systemtap'
PACKAGE_TARNAME='systemtap'
-PACKAGE_VERSION='0.9.5'
-PACKAGE_STRING='systemtap 0.9.5'
+PACKAGE_VERSION='0.9.7'
+PACKAGE_STRING='systemtap 0.9.7'
PACKAGE_BUGREPORT='systemtap@sources.redhat.com'
ac_subst_vars='SHELL
@@ -1149,7 +1149,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures systemtap 0.9.5 to adapt to many kinds of systems.
+\`configure' configures systemtap 0.9.7 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1215,7 +1215,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of systemtap 0.9.5:";;
+ short | recursive ) echo "Configuration of systemtap 0.9.7:";;
esac
cat <<\_ACEOF
@@ -1291,7 +1291,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-systemtap configure 0.9.5
+systemtap configure 0.9.7
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1305,7 +1305,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by systemtap $as_me 0.9.5, which was
+It was created by systemtap $as_me 0.9.7, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -1997,7 +1997,7 @@ fi
# Define the identity of the package.
PACKAGE='systemtap'
- VERSION='0.9.5'
+ VERSION='0.9.7'
cat >>confdefs.h <<_ACEOF
@@ -2617,7 +2617,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by systemtap $as_me 0.9.5, which was
+This file was extended by systemtap $as_me 0.9.7, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -2660,7 +2660,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-systemtap config.status 0.9.5
+systemtap config.status 0.9.7
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/testsuite/configure.ac b/testsuite/configure.ac
index 03ce3f61..1a82fe36 100644
--- a/testsuite/configure.ac
+++ b/testsuite/configure.ac
@@ -1,7 +1,7 @@
dnl configure.ac --- autoconf input file for systemtap testsuite
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([systemtap], 0.9.5, systemtap@sources.redhat.com, systemtap)
+AC_INIT([systemtap], 0.9.7, systemtap@sources.redhat.com, systemtap)
AC_PREREQ(2.59)
AC_CONFIG_AUX_DIR(..)
diff --git a/testsuite/systemtap.base/badkprobe.exp b/testsuite/systemtap.base/badkprobe.exp
index efc06695..c0815fbe 100644
--- a/testsuite/systemtap.base/badkprobe.exp
+++ b/testsuite/systemtap.base/badkprobe.exp
@@ -1,14 +1,28 @@
-set script "probe kernel.statement(-1).absolute {} probe timer.s(1) { exit() }"
set test "bad kprobe registration"
+set script {
+ probe $1 {}
+ probe timer.s(1) { exit() }
+ probe end { println("cleanup ok") }
+}
if {! [installtest_p]} { untested $test; return }
-spawn stap -g -w -e "$script"
-expect {
- -timeout 60
- -re "^WARNING: probe .*registration error.*" { pass $test }
- eof { fail "$test (eof)" }
- timeout { fail "$test (timeout)" }
+set bad_kprobes {
+ kernel.statement(-1).absolute
+ kprobe.statement(-1).absolute
+ kprobe.function("no_such_function")
+ kprobe.function("no_such_function").return
+}
+
+foreach bk $bad_kprobes {
+ set test "bad kprobe registration: $bk"
+ spawn stap -g -w -e "$script" "$bk"
+ expect {
+ -timeout 60
+ -re "^WARNING: probe .*registration error.*\r\ncleanup ok" { pass $test }
+ eof { fail "$test (eof)" }
+ timeout { fail "$test (timeout)" }
+ }
+ catch {close}
+ catch {wait}
}
-catch {close}
-catch {wait}
diff --git a/testsuite/systemtap.printf/char1.exp b/testsuite/systemtap.printf/char1.exp
index 35aa479f..f9343c0e 100644
--- a/testsuite/systemtap.printf/char1.exp
+++ b/testsuite/systemtap.printf/char1.exp
@@ -1,3 +1,3 @@
set test "char1"
-set ::result_string {stap}
+set ::result_string {stapok}
stap_run2 $srcdir/$subdir/$test.stp
diff --git a/testsuite/systemtap.printf/char1.stp b/testsuite/systemtap.printf/char1.stp
index 207d1bc5..564c416b 100644
--- a/testsuite/systemtap.printf/char1.stp
+++ b/testsuite/systemtap.printf/char1.stp
@@ -3,6 +3,7 @@ probe begin
printf("%c", 115)
printf("%c", 116)
printf("%c%c", 97, 112)
+ printf("%c%c", stringat("ok", 0), stringat("ok", 1))
print("\n")
exit()
}
diff --git a/testsuite/systemtap.printf/memory1.stp b/testsuite/systemtap.printf/memory1.stp
index f9cbf60b..15aa565b 100644
--- a/testsuite/systemtap.printf/memory1.stp
+++ b/testsuite/systemtap.printf/memory1.stp
@@ -113,6 +113,20 @@ probe syscall.open {
success = 0;
}
+ expected_16_actual = sprintf (" %02x%02x%02x%02x%02x%02x",
+ stringat(filename, 0),
+ stringat(filename, 1),
+ stringat(filename, 2),
+ stringat(filename, 3),
+ stringat(filename, 4),
+ stringat(filename, 5));
+ testName = "%M dynamic width larger than dynamic precision";
+ result = sprintf ("%*.*M", 14, 6, $filename);
+ if (result != expected_16_actual) {
+ printf ("Test %s failed\n", testName);
+ success = 0;
+ }
+
if (success)
print ("Test passed\n");