summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-06-27 21:45:37 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-06-27 21:45:37 -0400
commit53ca410a6a6032c2cde6aac6e95b57c68585e48a (patch)
tree79cda31e77dd2fee51b8f2f20e2e76989f4c8ad7
parent4494bb1367876f3067d0e7c90b1466b9bd88633f (diff)
parentcfa2ca3cbf2da7bbabcdf35c3085a969bd2370e4 (diff)
downloadsystemtap-steved-53ca410a6a6032c2cde6aac6e95b57c68585e48a.tar.gz
systemtap-steved-53ca410a6a6032c2cde6aac6e95b57c68585e48a.tar.xz
systemtap-steved-53ca410a6a6032c2cde6aac6e95b57c68585e48a.zip
Merge commit 'origin/master' into pr6429-comp-unwindsyms
* commit 'origin/master': Always include libdw using link groups. Fix bug in handling process(PID) probes. Added tests for 'process(PID)' variants. This commit makes changes to the VFS tapset. The changes include deprecation of syscalls2.stp: Add sys_renameat. Only probe lines once for the :* wildcard line pattern. Revert checking address in runtime bz451707: fix conversions.exp test $name Cleanup in tapsets.cxx Added powerpc support to runtime/syscall.h. Remove validating _stext due to many aliased symbols PR6646: Add checking address in runtime Fixed offset argument to vm_callback.
-rw-r--r--ChangeLog38
-rw-r--r--auto_free.h40
-rwxr-xr-xconfigure256
-rw-r--r--configure.ac29
-rw-r--r--runtime/ChangeLog10
-rw-r--r--runtime/syscall.h48
-rw-r--r--runtime/task_finder.c12
-rw-r--r--runtime/transport/ChangeLog10
-rw-r--r--runtime/transport/symbols.c4
-rw-r--r--tapset/ChangeLog4
-rw-r--r--tapset/syscalls2.stp23
-rw-r--r--tapset/vfs.stp303
-rw-r--r--tapsets.cxx175
-rw-r--r--testsuite/ChangeLog11
-rw-r--r--testsuite/buildok/vfs_testcase.stp461
-rw-r--r--testsuite/systemtap.base/utrace_p4.exp68
-rw-r--r--testsuite/systemtap.stress/conversions.exp4
17 files changed, 1105 insertions, 391 deletions
diff --git a/ChangeLog b/ChangeLog
index f66ffda7..4b1b25b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+2008-06-27 David Smith <dsmith@redhat.com>
+
+ * tapsets.cxx (utrace_derived_probe_group::emit_module_decls): Fix
+ bug in handling process(PID) probes.
+
+2008-06-24 K.Prasad <prasad@linux.vnet.ibm.com>
+
+ * tapset/vfs.stp: Deprecate probe points on old functions, namely
+ generic_file_readv(), generic_file_writev(),
+ generic_file_read() and generic_file_write().
+ * tapset/vfs.stp: Enhance the tapset by
+ providing more pure C functions, probes for newer VFS related functions
+ * testsuite/buildok/vfs_testcase.stp: Created a testsuite for the
+ new enhanced VFS Tapset which does a compile test i.e. with flags -up4
+
+2008-06-25 Stan Cox <scox@redhat.com>
+
+ * tapsets.cxx (iterate_over_srcfile_lines): Only probe a line once.
+
+2008-06-24 Tim Moore <timoore@redhat.com>
+
+ * auto_free.h: New file.
+ * tapsets.cxx (iterate_over_srcfile_lines, read_symbols): Use
+ auto_free instead of explicit calls to ::free().
+ (Compare): Class for comparing func_info objects and their
+ addresses.
+ (get_index_for_address): Remove.
+ (symbol_table::sort): new function.
+ (query_module_symtab): Iterate over list_by_addr using iterator
+ instead of index.
+ (~symbol_table): Don't bother clearing list_by_addr and
+ map_by_name.
+ (add_symbol): Don't keep list_by_addr in order.
+ (read_symbols, get_from_elf): Sort symbols after all are read.
+ (get_func_containing_address): Use std::upper_bound.
+ (purge_syscall_stubs): Don't iterate over whole list_by_addr
+ vector; use std::equal_range to look for possible stub addresses.
+
2008-06-23 Frank Ch. Eigler <fche@elastic.org>
* session.h (module_cache): Add field here.
diff --git a/auto_free.h b/auto_free.h
new file mode 100644
index 00000000..b13e7371
--- /dev/null
+++ b/auto_free.h
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+// Copyright (C) 2008 Red Hat Inc.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+#ifndef AUTO_FREE_H
+#define AUTO_FREE_H 1
+#include <cstdlib>
+
+// Very simple auto_ptr-like class for protecting storage allocated
+// with free().
+class auto_free
+{
+public:
+ auto_free(void* ptr) : _ptr(ptr) {}
+ ~auto_free()
+ {
+ if (_ptr)
+ std::free(_ptr);
+ }
+ void release()
+ {
+ _ptr = 0;
+ }
+private:
+ // No copying allowed.
+ auto_free(const auto_free& af)
+ {
+ }
+ // No assignment either
+ auto_free& operator=(const auto_free& rhs)
+ {
+ return *this;
+ }
+ void* _ptr;
+};
+#endif
diff --git a/configure b/configure
index e05e7321..32a850cb 100755
--- a/configure
+++ b/configure
@@ -1336,7 +1336,6 @@ Optional Features:
location).
--enable-docs enable building documentation (default on if latex
etc. found).
- --enable-staticdw support distributions with static libdw
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -6605,175 +6604,9 @@ fi
`
-# Check whether --enable-staticdw was given.
-if test "${enable_staticdw+set}" = set; then
- enableval=$enable_staticdw;
-fi
-
-
if test $build_elfutils = no; then
# Need libdwfl-capable recent elfutils from Fedora
save_LIBS="$LIBS"
- if test "x$enable_staticdw" != xyes; then
-
-
-{ echo "$as_me:$LINENO: checking for dwfl_module_getsym in -ldw" >&5
-echo $ECHO_N "checking for dwfl_module_getsym in -ldw... $ECHO_C" >&6; }
-if test "${ac_cv_lib_dw_dwfl_module_getsym+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldw $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dwfl_module_getsym ();
-int
-main ()
-{
-return dwfl_module_getsym ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_dw_dwfl_module_getsym=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_dw_dwfl_module_getsym=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_dw_dwfl_module_getsym" >&5
-echo "${ECHO_T}$ac_cv_lib_dw_dwfl_module_getsym" >&6; }
-if test $ac_cv_lib_dw_dwfl_module_getsym = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDW 1
-_ACEOF
-
- LIBS="-ldw $LIBS"
-
-else
-
- { { echo "$as_me:$LINENO: error: missing elfutils development headers/libraries (dw 0.123+)" >&5
-echo "$as_me: error: missing elfutils development headers/libraries (dw 0.123+)" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
-{ echo "$as_me:$LINENO: checking for ebl_openbackend in -lebl" >&5
-echo $ECHO_N "checking for ebl_openbackend in -lebl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_ebl_ebl_openbackend+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lebl $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ebl_openbackend ();
-int
-main ()
-{
-return ebl_openbackend ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_ebl_ebl_openbackend=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_ebl_ebl_openbackend=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_ebl_ebl_openbackend" >&5
-echo "${ECHO_T}$ac_cv_lib_ebl_ebl_openbackend" >&6; }
-if test $ac_cv_lib_ebl_ebl_openbackend = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBEBL 1
-_ACEOF
-
- LIBS="-lebl $LIBS"
-
-else
-
- { { echo "$as_me:$LINENO: error: missing elfutils development headers/libraries (ebl 0.123+)" >&5
-echo "$as_me: error: missing elfutils development headers/libraries (ebl 0.123+)" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
- stap_LIBS="$LIBS"
-
-else
-
- # Debian ships with a static libdw, which has a circular dependency on libebl
{ echo "$as_me:$LINENO: checking for dwfl_module_getsym in -ldw" >&5
echo $ECHO_N "checking for dwfl_module_getsym in -ldw... $ECHO_C" >&6; }
@@ -6845,103 +6678,18 @@ _ACEOF
else
- { { echo "$as_me:$LINENO: error: missing elfutils development headers/libraries (dw 0.123+)" >&5
+ { { echo "$as_me:$LINENO: error: missing elfutils development headers/libraries (dw 0.123+)" >&5
echo "$as_me: error: missing elfutils development headers/libraries (dw 0.123+)" >&2;}
{ (exit 1); exit 1; }; }
fi
-
-{ echo "$as_me:$LINENO: checking for ebl_openbackend in -lebl" >&5
-echo $ECHO_N "checking for ebl_openbackend in -lebl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_ebl_ebl_openbackend+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lebl -lelf $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ebl_openbackend ();
-int
-main ()
-{
-return ebl_openbackend ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_link") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext &&
- $as_test_x conftest$ac_exeext; then
- ac_cv_lib_ebl_ebl_openbackend=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lib_ebl_ebl_openbackend=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_ebl_ebl_openbackend" >&5
-echo "${ECHO_T}$ac_cv_lib_ebl_ebl_openbackend" >&6; }
-if test $ac_cv_lib_ebl_ebl_openbackend = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBEBL 1
-_ACEOF
-
- LIBS="-lebl $LIBS"
-
-else
-
- { { echo "$as_me:$LINENO: error: missing elfutils development headers/libraries (ebl 0.123+)" >&5
-echo "$as_me: error: missing elfutils development headers/libraries (ebl 0.123+)" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-
- stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf"
-
-fi
-
+ stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf"
LIBS="$save_LIBS"
else
# We built our own and stap_LDFLAGS points at the install.
- if test "x$enable_staticdw" != xyes; then
- stap_LIBS="-ldw -lebl"
-else
stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf"
fi
-fi
-
{ echo "$as_me:$LINENO: stap will link $stap_LIBS" >&5
echo "$as_me: stap will link $stap_LIBS" >&6;}
diff --git a/configure.ac b/configure.ac
index ed099702..c7338f80 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,36 +180,17 @@ AM_CONDITIONAL(BUILD_ELFUTILS, test $build_elfutils = yes)
AC_SUBST(elfutils_abs_srcdir, `AS_IF([test $build_elfutils = yes],
[cd $with_elfutils && pwd])`)
-AC_ARG_ENABLE([staticdw],
- [AS_HELP_STRING([--enable-staticdw], [support distributions with static libdw])])
-
if test $build_elfutils = no; then
# Need libdwfl-capable recent elfutils from Fedora
save_LIBS="$LIBS"
- AS_IF([test "x$enable_staticdw" != xyes],[
- AC_CHECK_LIB(dw, dwfl_module_getsym,,[
- AC_MSG_ERROR([missing elfutils development headers/libraries (dw 0.123+)])])
- AC_CHECK_LIB(ebl, ebl_openbackend,,[
- AC_MSG_ERROR([missing elfutils development headers/libraries (ebl 0.123+)])])
-
- stap_LIBS="$LIBS"
- ],[
- # Debian ships with a static libdw, which has a circular dependency on libebl
- AC_CHECK_LIB(dw, dwfl_module_getsym,[],[
- AC_MSG_ERROR([missing elfutils development headers/libraries (dw 0.123+)])],
- [-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf])
- dnl XXX Do we need the ebl check, since it was referenced above?
- AC_CHECK_LIB(ebl, ebl_openbackend,[],[
- AC_MSG_ERROR([missing elfutils development headers/libraries (ebl 0.123+)])],
- [-lelf])
-
- stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf"
- ])
+ AC_CHECK_LIB(dw, dwfl_module_getsym,[],[
+ AC_MSG_ERROR([missing elfutils development headers/libraries (dw 0.123+)])],
+ [-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf])
+ stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf"
LIBS="$save_LIBS"
else
# We built our own and stap_LDFLAGS points at the install.
- AS_IF([test "x$enable_staticdw" != xyes],[stap_LIBS="-ldw -lebl"],
- [stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf"])
+ stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf"
fi
AC_SUBST(stap_LIBS)
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index fb92dccc..6da5814c 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,5 +1,15 @@
+2008-06-24 David Smith <dsmith@redhat.com>
+
+ From: Srinivasa DS <srinivasa@in.ibm.com>
+ * syscall.h: Added powerpc support.
+
2008-06-23 David Smith <dsmith@redhat.com>
+ * task_finder.c (__stp_utrace_task_finder_target_quiesce): Fixed
+ vm_callback offset by shifting it left PAGE_SHIFT bits.
+ (__stp_target_call_vm_callback): Ditto.
+ (__stp_utrace_task_finder_target_syscall_exit): Ditto.
+
* task_finder.c (__stp_utrace_task_finder_report_exec): Handles
relative exec paths correctly.
diff --git a/runtime/syscall.h b/runtime/syscall.h
index 36fed2ff..3d1034e6 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -49,6 +49,13 @@
# endif
#endif
+#if defined(__powerpc__)
+#define MMAP_SYSCALL_NO(tsk) 90
+#define MPROTECT_SYSCALL_NO(tsk) 125
+#define MUNMAP_SYSCALL_NO(tsk) 91
+#define MREMAP_SYSCALL_NO(tsk) 163
+#endif
+
#if !defined(MMAP_SYSCALL_NO) || !defined(MPROTECT_SYSCALL_NO) \
|| !defined(MUNMAP_SYSCALL_NO) || !defined(MREMAP_SYSCALL_NO)
#error "Unimplemented architecture"
@@ -59,12 +66,20 @@ static inline unsigned long
__stp_user_syscall_nr(struct pt_regs *regs)
{
#if defined(STAPCONF_X86_UNIREGS)
- return regs->orig_ax;
+ return regs->orig_ax;
#elif defined(__x86_64__)
- return regs->orig_rax;
+ return regs->orig_rax;
#elif defined (__i386__)
- return regs->orig_eax;
+ return regs->orig_eax;
+#endif
+}
#endif
+
+#if defined(__powerpc__)
+static inline unsigned long
+__stp_user_syscall_nr(struct pt_regs *regs)
+{
+ return regs->gpr[0];
}
#endif
@@ -94,6 +109,14 @@ __stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
}
#endif
+#if defined(__powerpc__)
+static inline long *
+__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+ return &regs->gpr[3];
+}
+#endif
+
#if defined(__i386__) || defined(__x86_64__)
static inline long *
__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
@@ -157,4 +180,23 @@ __stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
}
#endif
+#if defined(__powerpc__)
+static inline long *
+__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
+ unsigned int n)
+{
+ switch (n) {
+ case 0: return &regs->gpr[3];
+ case 1: return &regs->gpr[4];
+ case 2: return &regs->gpr[5];
+ case 3: return &regs->gpr[6];
+ case 4: return &regs->gpr[7];
+ case 5: return &regs->gpr[8];
+ default:
+ _stp_error("syscall arg > 5");
+ return NULL;
+ }
+}
+#endif
+
#endif /* _SYSCALL_H_ */
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 71b11569..07610864 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -586,7 +586,8 @@ __stp_utrace_task_finder_target_quiesce(struct utrace_attached_engine *engine,
rc = tgt->vm_callback(tsk, 1, mmpath,
vma->vm_start,
vma->vm_end,
- vma->vm_pgoff);
+ (vma->vm_pgoff
+ << PAGE_SHIFT));
if (rc != 0) {
_stp_error("vm callback for %d failed: %d",
(int)tsk->pid, rc);
@@ -709,7 +710,8 @@ __stp_target_call_vm_callback(struct stap_task_finder_target *tgt,
}
else {
rc = tgt->vm_callback(tsk, 1, mmpath, vma->vm_start,
- vma->vm_end, vma->vm_pgoff);
+ vma->vm_end,
+ (vma->vm_pgoff << PAGE_SHIFT));
if (rc != 0) {
_stp_error("vm callback for %d failed: %d",
(int)tsk->pid, rc);
@@ -819,7 +821,8 @@ __stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engi
rc = tgt->vm_callback(tsk, 0, NULL,
entry->vm_start,
entry->vm_end,
- entry->vm_pgoff);
+ (entry->vm_pgoff
+ << PAGE_SHIFT));
if (rc != 0) {
_stp_error("vm callback for %d failed: %d",
(int)tsk->pid, rc);
@@ -852,7 +855,8 @@ __stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engi
rc = tgt->vm_callback(tsk, 0, NULL,
entry->vm_start,
entry->vm_end,
- entry->vm_pgoff);
+ (entry->vm_pgoff
+ << PAGE_SHIFT));
if (rc != 0) {
_stp_error("vm callback for %d failed: %d",
(int)tsk->pid, rc);
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index 2e59ff90..98548afa 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,13 @@
+
+
+2008-06-23 Wenji Huang <wenji.huang@oracle.com>
+ PR 6646
+ * symbols.c (_stp_validate_addr): Revert the previous code.
+
+2008-06-23 Wenji Huang <wenji.huang@oracle.com>
+ PR 6646
+ * symbols.c (_stp_validate_addr): Add validating address in runtime.
+
2008-06-13 Wenji Huang <wenji.huang@oracle.com>
* control.c (_stp_ctl_write_dbug): Remove STP_UNWIND support.
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index 4a3c4e17..9299fc67 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -205,11 +205,13 @@ static int _stp_init_kernel_symbols(void)
_dbug("Lookup of _stext failed. Exiting.\n");
return -1;
}
+
_stp_modules[0]->data = _stp_kallsyms_lookup_name("_etext");
if (_stp_modules[0]->data == 0) {
_dbug("Lookup of _etext failed. Exiting.\n");
return -1;
}
+
_stp_modules[0]->text_size = _stp_modules[0]->data - _stp_modules[0]->text;
_stp_modules_by_addr[0] = _stp_modules[0];
@@ -609,7 +611,7 @@ static int _stp_init_modules(void)
void *res;
struct module *mod;
const struct seq_operations *modules_op = (const struct seq_operations *)_stp_kallsyms_lookup_name("modules_op");
-
+
if (modules_op == NULL) {
_dbug("Lookup of modules_op failed.\n");
return -1;
diff --git a/tapset/ChangeLog b/tapset/ChangeLog
index 7365d4c9..0332a384 100644
--- a/tapset/ChangeLog
+++ b/tapset/ChangeLog
@@ -1,3 +1,7 @@
+2008-06-26 Zhaolei <zhaolei@cn.fujitsu.com>
+
+ * syscalls2.stp: Add sys_renameat.
+
2008-06-23 Zhaolei <zhaolei@cn.fujitsu.com>
* syscalls.stp: Add sys_mknodat.
diff --git a/tapset/syscalls2.stp b/tapset/syscalls2.stp
index 98bdc95f..64cbaa1d 100644
--- a/tapset/syscalls2.stp
+++ b/tapset/syscalls2.stp
@@ -833,6 +833,29 @@ probe syscall.rename.return = kernel.function("sys_rename").return {
retstr = returnstr(1)
}
+# renameat ___________________________________________________
+# new function with 2.6.16
+# long sys_renameat(int olddfd, const char __user *oldname,
+# int newdfd, const char __user *newname)
+probe syscall.renameat = kernel.function("sys_renameat") ? {
+ name = "renameat"
+ olddfd = $olddfd
+ olddfd_str = _dfd_str($olddfd)
+ oldname = $oldname
+ oldname_str = user_string($oldname)
+ newdfd = $newdfd
+ newdfd_str = _dfd_str($newdfd)
+ newname = $newname
+ newname_str = user_string($newname)
+ argstr = sprintf("%s, %s, %s, %s",
+ olddfd_str, user_string_quoted($oldname),
+ newdfd_str, user_string_quoted($newname))
+}
+probe syscall.renameat.return = kernel.function("sys_renameat").return ? {
+ name = "renameat"
+ retstr = returnstr(1)
+}
+
# request_key ________________________________________________
#
# long sys_request_key(const char __user *_type,
diff --git a/tapset/vfs.stp b/tapset/vfs.stp
index 6073dffc..78c79051 100644
--- a/tapset/vfs.stp
+++ b/tapset/vfs.stp
@@ -57,6 +57,18 @@ function __page_ino:long (page:long) %{ /* pure */
CATCH_DEREF_FAULT();
%}
+function __address_inode:long (page:long) %{ /* pure */
+ struct page *page = (struct page *)(long)THIS->page;
+ struct address_space *mapping =
+ (struct address_space *)(long)THIS;
+ if (mapping == NULL) {
+ THIS->__retvalue = -1;
+ } else {
+ THIS->__retvalue = (long)kread(&(mapping->host));
+ }
+ CATCH_DEREF_FAULT();
+%}
+
function __page_dev:long (page:long) %{ /* pure */
struct page *page = (struct page *)(long)THIS->page;
struct address_space *mapping = page? kread(&(page->mapping)) : NULL;
@@ -152,11 +164,47 @@ function __file_filename:string (file:long) %{ /* pure */
CATCH_DEREF_FAULT();
%}
+function __inode_num:long(file:long)
+%{
+ struct file *file = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *inode = NULL;
+
+ file = (struct file *)(long)THIS->file;
+ dentry = file? kread(&(file->f_dentry)) : NULL;
+ inode = dentry? kread(&(dentry->d_inode)) : NULL;
+ THIS->__retvalue = inode? (long)(kread(&(inode->i_ino))) : 0;
+ CATCH_DEREF_FAULT();
+%}
+
+function _get_fopv_size:long (iov:long, nr_segs:long)
+%{
+ struct iovec *iovp = (struct iovec *)(long)THIS->iov;
+ if (iovp) {
+ int i;
+ THIS->__retvalue = 0;
+ for (i = 0 ; i < THIS->nr_segs ; i++)
+ THIS->__retvalue += kread(&(iovp[i].iov_len));
+ } else
+ THIS->__retvalue = -1;
+
+ CATCH_DEREF_FAULT();
+%}
+
+function _dev_minor:long (dev:long) %{ /* pure */
+ THIS->__retvalue = (long)MINOR((dev_t)THIS->dev);
+%}
+
+function _dev_major:long (dev:long) %{ /* pure */
+ THIS->__retvalue = (long)MAJOR((dev_t)THIS->dev);
+%}
+
probe generic.fop.llseek = kernel.function ("generic_file_llseek")
{
dev = __file_dev($file)
devname = __find_bdevname(dev, __file_bdev($file))
ino = __file_ino($file)
+ file = $file
offset = $offset
origin = $origin
@@ -168,11 +216,19 @@ probe generic.fop.llseek = kernel.function ("generic_file_llseek")
probe generic.fop.llseek.return = kernel.function ("generic_file_llseek").return
{
name = "generic_file_llseek"
- retstr = returnstr(1)
+ name = "generic_file_llseek"
+ retstr = $return
+ file = $file
+ offset = $offset
+ origin = $origin
+
+ error = $return < 0 ? $return : 0
+ error_str = error ? errno_str(error) : ""
}
probe generic.fop.aio_read = kernel.function ("generic_file_aio_read")
{
+ file = $iocb->ki_filp
dev = __file_dev($iocb->ki_filp)
devname = __find_bdevname(dev, __file_bdev($iocb->ki_filp))
ino = __file_ino($iocb->ki_filp)
@@ -194,9 +250,15 @@ probe generic.fop.aio_read = kernel.function ("generic_file_aio_read")
}
probe generic.fop.aio_read.return = kernel.function ("generic_file_aio_read").return
{
+ file = $iocb->ki_filp
+ nr_segs = $nr_segs
name = "generic_file_aio_read"
retstr = sprintf("%d", $return)
+ bytes_read = $return > 0 ? $return : 0
+ error = $return < 0 ? $return : 0
+ error_str = error ? errno_str(error) : ""
+
if ($return > 0) {
size = $return
units = "bytes"
@@ -205,6 +267,7 @@ probe generic.fop.aio_read.return = kernel.function ("generic_file_aio_read").re
probe generic.fop.aio_write = kernel.function ("generic_file_aio_write")
{
+ file = $iocb->ki_filp
dev = __file_dev($iocb->ki_filp)
devname = __find_bdevname(dev, __file_bdev($iocb->ki_filp))
ino = __file_ino($iocb->ki_filp)
@@ -226,6 +289,7 @@ probe generic.fop.aio_write = kernel.function ("generic_file_aio_write")
}
probe generic.fop.aio_write.return = kernel.function ("generic_file_aio_write").return
{
+ file = $iocb->ki_filp
name = "generic_file_aio_write"
retstr = sprintf("%d", $return)
@@ -235,6 +299,7 @@ probe generic.fop.aio_write.return = kernel.function ("generic_file_aio_write").
}
}
+%( kernel_v < "2.6.19" %?
probe generic.fop.readv = kernel.function ("generic_file_readv") ?
{
dev = __file_dev($filp)
@@ -279,20 +344,28 @@ probe generic.fop.writev = kernel.function ("generic_file_writev")?
}
probe generic.fop.writev.return = kernel.function ("generic_file_writev").return ?
{
+ file = $file
name = "generic_file_writev"
retstr = sprintf("%d", $return)
+ bytes_written = $return > 0 ? $return : 0
+ error = $return < 0 ? $return : 0
+ error_str = error ? errno_str(error) : ""
+
if ($return > 0) {
size = $return
units = "bytes"
}
}
+%:
+%)
/* checks for aops->readpage, if not defined, return -ENOEXEC
else assigns generic_file_vm_ops to vma
add filemap_nopage, filemap_populate */
probe generic.fop.mmap = kernel.function ("generic_file_mmap")
{
+ file = $file
dev = __file_dev($file)
devname = __find_bdevname(dev, __file_bdev($file))
ino = __file_ino($file)
@@ -306,8 +379,12 @@ probe generic.fop.mmap = kernel.function ("generic_file_mmap")
}
probe generic.fop.mmap.return = kernel.function ("generic_file_mmap").return
{
+ file = $file
name = "generic_file_mmap"
retstr = sprintf("%d", $return)
+
+ error = $return < 0 ? $return : 0
+ error_str = error ? errno_str(error) : ""
}
probe generic.fop.open = kernel.function ("generic_file_open")
@@ -362,6 +439,7 @@ probe generic.fop.splice_read = kernel.function ("generic_file_splice_read") ?
dev = __file_dev($in)
devname = __find_bdevname(dev, __file_bdev($in))
ino = __file_ino($in)
+ file = $in
len = $len
flags = $flags
@@ -376,9 +454,17 @@ probe generic.fop.splice_read.return = kernel.function ("generic_file_splice_rea
{
name = "generic_file_splice_read"
retstr = sprintf("%d", $return)
+ file = $in
+ ino = __file_ino($in)
+ dev_major = _dev_major(_dev)
+ dev_minor = _dev_minor(_dev)
- if ($return > 0) {
- size = $return
+ ret = $return
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+
+ if (error) {
+ size = ret
units = "bytes"
}
}
@@ -388,6 +474,7 @@ probe generic.fop.splice_write = kernel.function ("generic_file_splice_write") ?
dev = __file_dev($out)
devname = __find_bdevname(dev, __file_bdev($out))
ino = __file_ino($out)
+ file = $out
len = $len
flags = $flags
@@ -403,12 +490,18 @@ probe generic.fop.splice_write.return = kernel.function ("generic_file_splice_wr
name = "generic_file_splice_write"
retstr = sprintf("%d", $return)
- if ($return > 0) {
+ file = $out
+
+ error = $return < 0 ? $return : 0
+ error_str = error ? errno_str(error) : ""
+
+ if (error) {
size = $return
units = "bytes"
}
}
+%( kernel_v < "2.6.19" %?
probe generic.fop.read = kernel.function ("generic_file_read") ?
{
dev = __file_dev($filp)
@@ -458,6 +551,7 @@ probe generic.fop.write.return = kernel.function ("generic_file_write").return ?
units = "bytes"
}
}
+%)
/* generic_writepages calls mpage_writepages(mapping, wbc, NULL) */
probe generic.aop.writepages = kernel.function ("mpage_writepages")
@@ -494,12 +588,19 @@ probe vfs.do_sync_read = kernel.function ("do_sync_read")
size = len
units = "bytes"
+ bytes_to_read = len
}
probe vfs.do_sync_read.return = kernel.function ("do_sync_read").return
{
name = "do_sync_read"
retstr = sprintf("%d", $return)
+ bytes_to_read = $len
+ ret = $return
+ bytes_read = ret > 0 ? ret : 0
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+
if ($return > 0) {
size = $return
units = "bytes"
@@ -515,6 +616,7 @@ probe vfs.do_sync_write = kernel.function ("do_sync_write")
len = $len
pos = ppos_pos($ppos)
buf = $buf
+ bytes_to_write = len
name = "do_sync_write"
argstr = sprintf("%d, %d , %p", len, pos, buf)
@@ -527,8 +629,15 @@ probe vfs.do_sync_write.return = kernel.function ("do_sync_write").return
name = "do_sync_write"
retstr = sprintf("%d", $return)
- if ($return > 0) {
- size = $return
+ bytes_to_write = $len
+ ppos = $ppos
+ ret = $return
+ bytes_written = ret > 0 ? ret : 0
+ error = $return < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+
+ if (error) {
+ size = ret
units = "bytes"
}
}
@@ -677,3 +786,185 @@ probe vfs.remove_from_page_cache.return = kernel.function ("__remove_from_page_c
retstr = sprintf("N/A")
}
+probe vfs.read = kernel.function ("vfs_read")
+{
+ file = $file
+ pos = $pos
+ buf = $buf
+ bytes_to_read = $count
+}
+
+probe vfs.read.return = kernel.function ("vfs_read").return
+{
+ file = $file
+ pos = $pos
+ buf = $buf
+ bytes_to_read = $count
+
+ ret = $return
+ bytes_read = ret > 0 ? ret : 0
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+}
+
+probe vfs.readv = kernel.function ("vfs_readv")
+{
+ file = $file
+ pos = $pos
+ vec = $vec
+ vlen = $vlen
+ bytes_to_read = _get_fopv_size($vec, $vlen)
+}
+
+probe vfs.readv.return = kernel.function ("vfs_readv").return
+{
+ file = $file
+ pos = $pos
+ vec = $vec
+ vlen = $vlen
+ bytes_to_read = _get_fopv_size($vec, $vlen)
+
+ ret = $return
+ bytes_read = ret > 0 ? ret : 0
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+}
+
+probe vfs.write = kernel.function ("vfs_write")
+{
+ file = $file
+ pos = $pos
+ buf = $buf
+ bytes_to_write = $count
+}
+
+probe vfs.write.return = kernel.function ("vfs_write").return
+{
+ file = $file
+ pos = $pos
+ buf = $buf
+ bytes_to_write = $count
+
+ ret = $return
+ bytes_written = ret > 0 ? ret : 0
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+}
+
+probe vfs.writev = kernel.function("vfs_writev")
+{
+ file = $file
+ pos = $pos
+ vlen = $vlen
+ vec = $vec
+ bytes_to_write = _get_fopv_size($vec, $vlen)
+}
+
+probe vfs.writev.return = kernel.function ("vfs_writev").return
+{
+ file = $file
+ pos = $pos
+ vlen = $vlen
+ vec = $vec
+ bytes_to_write = _get_fopv_size($vec, $vlen)
+
+ ret = $return
+ bytes_written = ret > 0 ? ret : 0
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+}
+
+probe _vfs.generic_file_readonly_mmap =
+kernel.function("generic_file_readonly_mmap")
+{
+ file = $file
+ vma = $vma
+}
+
+probe _vfs.generic_file_readonly_mmap.return = kernel.function ("generic_file_readonly_mmap").return
+{
+ file = $file
+ vma = $vma
+
+ ret = $return
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+}
+
+probe _vfs.generic_block_bmap = kernel.function ("generic_block_bmap")
+{
+ mapping = $mapping
+ block = $block
+ get_block = $get_block
+}
+
+probe _vfs.generic_commit_write = kernel.function ("generic_commit_write")
+{
+ file = $file
+ page = $page
+ from = $from
+ to = $to
+}
+
+probe _vfs.block_prepare_write = kernel.function ("__block_prepare_write")
+{
+ _inode = $inode
+ page = $page
+ write_from = $from
+ write_upto = $to
+}
+
+probe _vfs.block_prepare_write.return = kernel.function("__block_prepare_write").return
+{
+ _inode = $inode
+ page = $page
+ write_from = $from
+ write_upto = $to
+
+ ret = $return
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+}
+
+probe _vfs.block_write_begin = kernel.function ("block_write_begin")
+{
+ file = $file
+ pos = $pos
+ len = $len
+ flags = $flags
+
+ _inode = __address_inode($mapping)
+}
+
+probe _vfs.block_write_begin.return = kernel.function ("block_write_begin").return
+{
+ file = $file
+ pos = $pos
+ len = $len
+ flags = $flags
+
+ _inode = __address_inode($mapping)
+
+ ret = $return
+ error = ret < 0 ? ret : 0
+ error_str = error ? errno_str(error) : ""
+}
+
+probe _vfs.block_write_end = kernel.function ("block_write_end")
+{
+ file = $file
+ pos = $pos
+ len = $len
+ page = $page
+ _inode = __address_inode($mapping)
+}
+
+probe _vfs.block_write_end.return = kernel.function ("block_write_end").return
+{
+ file = $file
+ pos = $pos
+ len = $len
+ page = $page
+ _inode = __address_inode($mapping)
+ ret = $return
+}
diff --git a/tapsets.cxx b/tapsets.cxx
index a45233fc..35428fcd 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -15,6 +15,7 @@
#include "session.h"
#include "util.h"
#include "dwarf_wrappers.h"
+#include "auto_free.h"
#include <cstdlib>
#include <algorithm>
@@ -488,6 +489,27 @@ func_info
Dwarf_Addr addr;
Dwarf_Addr prologue_end;
bool weak;
+ // Comparison functor for list of functions sorted by address. The
+ // two versions that take a Dwarf_Addr let us use the STL algorithms
+ // upper_bound, equal_range et al., but we don't know whether the
+ // searched-for value will be passed as the first or the second
+ // argument.
+ struct Compare
+ {
+ bool operator() (const func_info* f1, const func_info* f2) const
+ {
+ return f1->addr < f2->addr;
+ }
+ // For doing lookups by address.
+ bool operator() (Dwarf_Addr addr, const func_info* f2) const
+ {
+ return addr < f2->addr;
+ }
+ bool operator() (const func_info* f1, Dwarf_Addr addr) const
+ {
+ return f1->addr < addr;
+ }
+ };
};
struct
@@ -566,12 +588,16 @@ symbol_table
module_info *mod_info; // associated module
map<string, func_info*> map_by_name;
vector<func_info*> list_by_addr;
+ typedef vector<func_info*>::iterator iterator_t;
+ typedef pair<iterator_t, iterator_t> range_t;
#ifdef __powerpc__
GElf_Word opd_section;
#endif
-
+ // add_symbol doesn't leave symbol table in order; call
+ // symbol_table::sort() when done adding symbols.
void add_symbol(const char *name, bool weak, Dwarf_Addr addr,
Dwarf_Addr *high_addr);
+ void sort();
enum info_status read_symbols(FILE *f, const string& path);
enum info_status read_from_elf_file(const string& path);
enum info_status read_from_text_file(const string& path);
@@ -583,7 +609,6 @@ symbol_table
func_info *lookup_symbol(const string& name);
Dwarf_Addr lookup_symbol_address(const string& name);
func_info *get_func_containing_address(Dwarf_Addr addr);
- int get_index_for_address(Dwarf_Addr addr);
symbol_table(module_info *mi) : mod_info(mi) {}
~symbol_table();
@@ -1179,16 +1204,19 @@ struct dwflpp
for (int l = lineno; ; l = l + 1)
{
+ set<int> lines_probed;
+ pair<set<int>::iterator,bool> line_probed;
dwarf_assert ("dwarf_getsrc_file",
dwarf_getsrc_file (module_dwarf,
srcfile, l, 0,
&srcsp, &nsrcs));
-
+ auto_free srcsp_af(srcsp);
if (line_type == WILDCARD || line_type == RANGE)
{
Dwarf_Addr line_addr;
dwarf_lineno (srcsp [0], &lineno);
- if (lineno != l)
+ line_probed = lines_probed.insert(lineno);
+ if (lineno != l || line_probed.second == false)
continue;
dwarf_lineaddr (srcsp [0], &line_addr);
if (dwarf_haspc (function, line_addr) != 1)
@@ -1247,24 +1275,15 @@ struct dwflpp
throw semantic_error (advice.str());
}
- try
- {
- for (size_t i = 0; i < nsrcs; ++i)
- {
- if (pending_interrupts) return;
- if (srcsp [i]) // skip over mismatched lines
- callback (dwarf_line_t(srcsp[i]), data);
- }
- }
- catch (...)
- {
- free (srcsp);
- throw;
- }
- if (line_type != WILDCARD || l == lines[1])
- break;
+ for (size_t i = 0; i < nsrcs; ++i)
+ {
+ if (pending_interrupts) return;
+ if (srcsp [i]) // skip over mismatched lines
+ callback (dwarf_line_t(srcsp[i]), data);
+ }
+ if (line_type != WILDCARD || l == lines[1])
+ break;
}
- free (srcsp);
}
@@ -2695,12 +2714,12 @@ dwarf_query::query_module_symtab()
<< endl;
return;
}
-
- size_t i;
- size_t nsyms = sym_table->list_by_addr.size();
- for (i = 0; i < nsyms; i++)
+ symbol_table::iterator_t iter;
+ for (iter = sym_table->list_by_addr.begin();
+ iter != sym_table->list_by_addr.end();
+ ++iter)
{
- fi = sym_table->list_by_addr.at(i);
+ fi = *iter;
if (!null_die(&fi->die))
continue; // already handled in query_module_dwarf()
if (dw.function_name_matches_pattern(fi->name, function_str_val))
@@ -4742,14 +4761,8 @@ dwarf_builder::build(systemtap_session & sess,
symbol_table::~symbol_table()
{
- // map::clear() and vector::clear() don't call destructors for
- // pointers, only for objects.
- int i;
- int nsym = (int) list_by_addr.size();
- for (i = 0; i < nsym; i++)
- delete list_by_addr.at(i);
- list_by_addr.clear();
- map_by_name.clear();
+ for (iterator_t i = list_by_addr.begin(); i != list_by_addr.end(); ++i)
+ delete *i;
}
void
@@ -4768,18 +4781,7 @@ symbol_table::add_symbol(const char *name, bool weak, Dwarf_Addr addr,
map_by_name[fi->name] = fi;
// TODO: Use a multimap in case there are multiple static
// functions with the same name?
- if (addr >= *high_addr)
- {
- list_by_addr.push_back(fi);
- *high_addr = addr;
- }
- else
- {
- // Symbols aren't in numerical order. FWIW, sort(1) doesn't
- // handle hex numbers without the leading 0x.
- int index = get_index_for_address(fi->addr);
- list_by_addr.insert(list_by_addr.begin()+(index+1), fi);
- }
+ list_by_addr.push_back(fi);
}
enum info_status
@@ -4787,7 +4789,8 @@ symbol_table::read_symbols(FILE *f, const string& path)
{
// Based on do_kernel_symbols() in runtime/staprun/symbols.c
int ret;
- char *name, *mod;
+ char *name = 0;
+ char *mod = 0;
char type;
unsigned long long addr;
Dwarf_Addr high_addr = 0;
@@ -4796,6 +4799,8 @@ symbol_table::read_symbols(FILE *f, const string& path)
// %as (non-POSIX) mallocs space for the string and stores its address.
while ((ret = fscanf(f, "%llx %c %as [%as", &addr, &type, &name, &mod)) > 0)
{
+ auto_free free_name(name);
+ auto_free free_mod(mod);
line++;
if (ret < 3)
{
@@ -4807,26 +4812,23 @@ symbol_table::read_symbols(FILE *f, const string& path)
// Caller should delete symbol_table object.
return info_absent;
}
- if (ret > 3)
+ else if (ret > 3)
{
// Modules are loaded above the kernel, so if we're getting
// modules, we're done.
- free(name);
- free(mod);
- goto done;
+ break;
}
if (type == 'T' || type == 't' || type == 'W')
add_symbol(name, (type == 'W'), (Dwarf_Addr) addr, &high_addr);
- free(name);
}
-done:
if (list_by_addr.size() < 1)
{
cerr << "Symbol table error: "
<< path << " contains no function symbols." << endl;
return info_absent;
}
+ sort();
return info_present;
}
@@ -4938,6 +4940,7 @@ symbol_table::get_from_elf()
add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK),
sym.st_value, &high_addr);
}
+ sort();
return info_present;
}
@@ -4979,35 +4982,12 @@ symbol_table::mark_dwarf_redundancies(dwflpp *dw)
func_info *
symbol_table::get_func_containing_address(Dwarf_Addr addr)
{
- int index = get_index_for_address(addr);
- if (index < 0)
+ iterator_t iter = upper_bound(list_by_addr.begin(), list_by_addr.end(), addr,
+ func_info::Compare());
+ if (iter == list_by_addr.begin())
return NULL;
- return list_by_addr.at(index);
-}
-
-// Find the index in list_by_addr of the last element whose address
-// is <= addr. Returns -1 if addr is less than the first address in
-// list_by_addr.
-int
-symbol_table::get_index_for_address(Dwarf_Addr addr)
-{
- // binary search from runtime/sym.c
- int begin = 0;
- int mid;
- int end = list_by_addr.size();
-
- if (end == 0 || addr < list_by_addr.at(0)->addr)
- return -1;
- do
- {
- mid = (begin + end) / 2;
- if (addr < list_by_addr.at(mid)->addr)
- end = mid;
- else
- begin = mid;
- }
- while (begin + 1 < end);
- return begin;
+ else
+ return *(iter - 1);
}
func_info *
@@ -5042,17 +5022,30 @@ symbol_table::purge_syscall_stubs()
Dwarf_Addr stub_addr = lookup_symbol_address("sys_ni_syscall");
if (stub_addr == 0)
return;
- for (size_t i = 0; i < list_by_addr.size(); i++)
- {
- func_info *fi = list_by_addr.at(i);
- if (fi->weak && fi->addr == stub_addr && fi->name != "sys_ni_syscall")
+ range_t purge_range = equal_range(list_by_addr.begin(), list_by_addr.end(),
+ stub_addr, func_info::Compare());
+ for (iterator_t iter = purge_range.first;
+ iter != purge_range.second;
+ ++iter)
+ {
+ func_info *fi = *iter;
+ if (fi->weak && fi->name != "sys_ni_syscall")
{
- list_by_addr.erase(list_by_addr.begin()+i);
- map_by_name.erase(fi->name);
- delete fi;
- i--;
- }
+ map_by_name.erase(fi->name);
+ delete fi;
+ *iter = 0;
+ }
}
+ // Range might have null pointer entries that should be erased.
+ list_by_addr.erase(remove(purge_range.first, purge_range.second,
+ (func_info*)0),
+ purge_range.second);
+}
+
+void
+symbol_table::sort()
+{
+ stable_sort(list_by_addr.begin(), list_by_addr.end(), func_info::Compare());
}
void
@@ -5823,7 +5816,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
// Emit a "fake" probe decl that is really a hook for to get
// our vm_callback called.
s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA";
- emit_vm_callback_probe_decl (s, false, NULL, it->first,
+ emit_vm_callback_probe_decl (s, false, "", it->first,
"__stp_tf_vm_cb");
s.op->newline() << "#endif";
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index 4fda9c5f..eda51529 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2008-06-27 David Smith <dsmith@redhat.com>
+
+ * systemtap.base/utrace_p4.exp: Added tests for 'process(PID)'
+ variants.
+
+2008-06-24 Frank Ch. Eigler <fche@elastic.org>
+
+ rhbz 451707
+ * systemtap.stress/conversions.exp: Reorder value overrides
+ so $test name conveys correct tested value.
+
2008-06-23 Stan Cox <scox@redhat.com>
* systemtap.base/stmt_rel.stp: Added test for
diff --git a/testsuite/buildok/vfs_testcase.stp b/testsuite/buildok/vfs_testcase.stp
new file mode 100644
index 00000000..dc78399c
--- /dev/null
+++ b/testsuite/buildok/vfs_testcase.stp
@@ -0,0 +1,461 @@
+#! stap -up4
+probe generic.fop.llseek
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("file = %p\n", file);
+ print("offset = %ll\n", offset);
+ print("origin = %d\n", origin);
+ print("maxbyte = %l\n", maxbyte);
+}
+
+probe generic.fop.llseek.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe generic.fop.aio_read
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("file = %p\n", file);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("pos = %ll\n", pos);
+ print("size = %l\n", size);
+ print("buf = %p\n", buf);
+}
+
+probe generic.fop.aio_read.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe generic.fop.aio_write
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("file = %p\n", file);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("pos = %ll\n", pos);
+ print("size = %l\n", size);
+ print("buf = %p\n", buf);
+}
+
+probe generic.fop.aio_write.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+%( kernel_v < "2.6.19" %?
+probe generic.fop.readv
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %lu\n", size);
+ print("pos = %ll\n", pos);
+}
+
+probe generic.fop.readv.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe generic.fop.writev
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %lu\n", size);
+ print("pos = %ll\n", pos);
+}
+
+probe generic.fop.writev.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+%:
+%)
+
+probe generic.fop.mmap
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("file = %p\n", file);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("vm_start = %lu\n", vm_start);
+ print("vm_end = %lu\n", vm_end);
+ print("vm_flags = %lu\n", vm_flags);
+}
+
+probe generic.fop.mmap.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe generic.fop.open
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %lu\n", size);
+ print("filename: %s\n", filename);
+ print("flag = %u\n", flag);
+}
+
+probe generic.fop.open.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+%( kernel_v < "2.6.23" %?
+probe generic.fop.sendfile
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("file = %p\n", file);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("pos = %ll\n", pos);
+ print("size = %l\n", size);
+}
+
+probe generic.fop.sendfile.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+%)
+
+
+probe generic.fop.splice_read
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("file = %p\n", file);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+ print("flags = %u\n", flags);
+}
+
+probe generic.fop.splice_read.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe generic.fop.splice_write
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("file = %p\n", file);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+ print("flags = %u\n", flags);
+}
+
+probe generic.fop.splice_write.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+%( kernel_v < "2.6.19" %?
+probe generic.fop.read
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("file = %p\n", file);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+}
+
+probe generic.fop.read.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe generic.fop.write
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+}
+
+probe generic.fop.write.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+%)
+
+probe generic.aop.writepages
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+}
+
+probe generic.aop.writepages.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe vfs.do_sync_read
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+ print("pos = %ll\n", pos);
+ print("buf = %u\n", buf);
+}
+
+probe vfs.do_sync_read.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe vfs.do_sync_write
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+ print("pos = %ll\n", pos);
+ print("buf = %u\n", buf);
+}
+
+probe vfs.do_sync_write.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe vfs.block_sync_page
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+ print("page_index = %l\n", page_index);
+}
+
+probe vfs.block_sync_page.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+
+probe vfs.__set_page_dirty_buffers
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+ print("index = %l\n", index);
+}
+
+probe vfs.__set_page_dirty_buffers.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe vfs.do_mpage_readpage
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("size = %l\n", size);
+ print("index = %l\n", index);
+}
+
+probe vfs.do_mpage_readpage.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe vfs.add_to_page_cache
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("index = %ll\n", index);
+ print("nrpages = %lu\n", nrpages);
+}
+
+probe vfs.add_to_page_cache.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe vfs.remove_from_page_cache
+{
+ print("Probe hit the function: %s\n", name);
+ print("Probe function argstr: %s\n", argstr);
+ print("dev = %l\n", dev);
+ print("devname = %s\n", devname);
+ print("ino = %l\n", ino);
+ print("index = %ll\n", index);
+}
+
+probe vfs.remove_from_page_cache.return
+{
+ print("Probe return from function: %s with return value = %s\n", name, retstr);
+}
+
+probe vfs.read
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("pos = %p\n", pos);
+ print("buf = %p\n", buf);
+}
+
+probe vfs.read.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
+probe vfs.readv
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("pos = %p\n", pos);
+ print("vec = %p\n", vec);
+ print("vlen = %lu\n", vlen);
+}
+
+probe vfs.readv.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
+probe vfs.write
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("pos = %p\n", pos);
+ print("buf = %p\n", buf);
+}
+
+probe vfs.write.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
+probe vfs.writev
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("pos = %p\n", pos);
+ print("vec = %p\n", vec);
+ print("vlen = %lu\n", vlen);
+}
+
+probe vfs.writev.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
+probe _vfs.generic_file_readonly_mmap
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("vma = %p\n", vma);
+}
+
+probe _vfs.generic_file_readonly_mmap.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
+probe _vfs.generic_block_bmap
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("mapping = %p\n", mapping);
+ print("block = %llu\n", block);
+ print("get_block = %p\n", get_block);
+}
+
+probe _vfs.generic_commit_write
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("page = %p\n", page);
+ print("from = %u to=%u\n", from, to);
+}
+
+probe _vfs.block_prepare_write
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("_inode = %p\n", _inode);
+ print("page = %p\n", page);
+ print("write_from = %u write_upto=%u\n", write_from, write_upto);
+}
+probe _vfs.block_prepare_write.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
+probe _vfs.block_write_begin
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("pos = %llu\n", pos);
+ print("len = %u\n", len);
+ print("flags = %u\n", flags);
+ print("_inode = %l\n", _inode);
+}
+probe _vfs.block_write_begin.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
+probe _vfs.block_write_end
+{
+ print("Probe hit the function: %s\n", probefunc());
+ print("file = %p\n", file);
+ print("pos = %llu\n", pos);
+ print("len = %u\n", len);
+ print("page = %p\n", page);
+ print("_inode = %l\n", _inode);
+}
+
+probe _vfs.block_write_end.return
+{
+ print("Probe return from function: %s with return value = %s\n", probefunc(), ret);
+}
+
diff --git a/testsuite/systemtap.base/utrace_p4.exp b/testsuite/systemtap.base/utrace_p4.exp
index 5544ee55..333cff21 100644
--- a/testsuite/systemtap.base/utrace_p4.exp
+++ b/testsuite/systemtap.base/utrace_p4.exp
@@ -25,6 +25,7 @@ proc stap_compile { TEST_NAME compile script args } {
-re "parse error" { incr compile_errors 1; exp_continue}
-re "compilation failed" {incr compile_errors 1; exp_continue}
-re "semantic error:" {incr compile_errors 1; exp_continue}
+ -re "terminate called" {incr compile_errors 1; exp_continue}
}
catch close
wait
@@ -56,6 +57,13 @@ set syscall_return_script {"probe process(\"/bin/ls\").syscall.return { printf(\
set thread_begin_script {"probe process(\"/bin/ls\").thread.begin { print(\"ls thread.begin\") }"}
set thread_end_script {"probe process(\"/bin/ls\").thread.end { print(\"ls thread.end\") }"}
+set pid_begin_script {"probe process(123).begin { print(\"123 begin\") }"}
+set pid_end_script {"probe process(123).end { print(\"123 end\") }"}
+set pid_syscall_script {"probe process(123).syscall { printf(\"|%d\", \$syscall) }"}
+set pid_syscall_return_script {"probe process(123).syscall.return { printf(\"|%d\", \$syscall) }"}
+set pid_thread_begin_script {"probe process(123).thread.begin { print(\"123 thread.begin\") }"}
+set pid_thread_end_script {"probe process(123).thread.end { print(\"123 thread.end\") }"}
+
# Try to find utrace_attach symbol in /proc/kallsyms
set path "/proc/kallsyms"
if {! [catch {exec grep -q utrace_attach $path} dummy]} {
@@ -70,46 +78,94 @@ set TEST_NAME "UTRACE_P4_01"
if {$utrace_support_found == 0} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
- # Try compiling a begin script
+ # Try compiling a begin script using a path
stap_compile $TEST_NAME 1 $begin_script
}
+set TEST_NAME "UTRACE_P4_01_pid"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling a begin script using a pid
+ stap_compile $TEST_NAME 1 $pid_begin_script
+}
+
set TEST_NAME "UTRACE_P4_02"
if {$utrace_support_found == 0} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
- # Try compiling a end script
+ # Try compiling a end script using a path
stap_compile $TEST_NAME 1 $end_script
}
+set TEST_NAME "UTRACE_P4_02_pid"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling a end script using a pid
+ stap_compile $TEST_NAME 1 $pid_end_script
+}
+
set TEST_NAME "UTRACE_P4_03"
if {$utrace_support_found == 0} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
- # Try compiling a syscall script
+ # Try compiling a syscall script using a path
stap_compile $TEST_NAME 1 $syscall_script
}
+set TEST_NAME "UTRACE_P4_03_pid"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling a syscall script using a pid
+ stap_compile $TEST_NAME 1 $pid_syscall_script
+}
+
set TEST_NAME "UTRACE_P4_04"
if {$utrace_support_found == 0} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
- # Try compiling a syscall return script
+ # Try compiling a syscall return script using a path
stap_compile $TEST_NAME 1 $syscall_return_script
}
+set TEST_NAME "UTRACE_P4_04_pid"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling a syscall return script using a pid
+ stap_compile $TEST_NAME 1 $pid_syscall_return_script
+}
+
set TEST_NAME "UTRACE_P4_05"
if {$utrace_support_found == 0} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
- # Try compiling an thread.begin script
+ # Try compiling an thread.begin script using a path
stap_compile $TEST_NAME 1 $thread_begin_script
}
+set TEST_NAME "UTRACE_P4_05_pid"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling an thread.begin script using a pid
+ stap_compile $TEST_NAME 1 $pid_thread_begin_script
+}
+
set TEST_NAME "UTRACE_P4_06"
if {$utrace_support_found == 0} {
untested "$TEST_NAME : no kernel utrace support found"
} else {
- # Try compiling an thread.end script
+ # Try compiling an thread.end script using a path
stap_compile $TEST_NAME 1 $thread_end_script
}
+
+set TEST_NAME "UTRACE_P4_06_pid"
+if {$utrace_support_found == 0} {
+ untested "$TEST_NAME : no kernel utrace support found"
+} else {
+ # Try compiling an thread.end script using a pid
+ stap_compile $TEST_NAME 1 $pid_thread_end_script
+}
diff --git a/testsuite/systemtap.stress/conversions.exp b/testsuite/systemtap.stress/conversions.exp
index 9c2c2fa9..27de10c2 100644
--- a/testsuite/systemtap.stress/conversions.exp
+++ b/testsuite/systemtap.stress/conversions.exp
@@ -1,12 +1,12 @@
set file $srcdir/$subdir/conversions.stp
foreach value {0 0xffffffff 0xffffffffffffffff} {
- set test "conversions.stp $value"
- if {![installtest_p]} { untested $test; continue }
# PR 4121: address 0 is valid on s390x
if {[istarget s390x-*-*] && $value == 0} { set value 0x7777777777 }
# PR 4540: ia64 thinks 0xffffffffffffffff okay for character accesses
if {[istarget ia64-*-*] && $value == 0xffffffffffffffff } { set value 0xafffffffffffffff }
+ set test "conversions.stp $value"
+ if {![installtest_p]} { untested $test; continue }
spawn stap -DMAXERRORS=40 $file $value
set errs 0
verbose -log "exp $test $errs"