summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfche <fche>2006-11-26 23:28:15 +0000
committerfche <fche>2006-11-26 23:28:15 +0000
commitc931ec8ab64f5b6667e28b0f64338643d4b9ed03 (patch)
tree80b739d8a696c6acc3ce26853ebc9c8de603c52f
parentcc7d24cd109128d558445507e508f5b43906ef16 (diff)
downloadsystemtap-steved-c931ec8ab64f5b6667e28b0f64338643d4b9ed03.tar.gz
systemtap-steved-c931ec8ab64f5b6667e28b0f64338643d4b9ed03.tar.xz
systemtap-steved-c931ec8ab64f5b6667e28b0f64338643d4b9ed03.zip
2006-11-26 Frank Ch. Eigler <fche@redhat.com>
PRs 2685, 3596, toward 2725. * tapsets.cxx (common_probe_entryfn_prologue): Skip probe on insufficient stack. (build_blacklist): Add a slew of lock-related calls. (query_module): Check for debuginfo architecture match. * translate.cxx (translate_pass): Add default MINSTACKSPACE. * configure.ac: Link stap with -lebl too. * configure: Regenerated. * stap.1.in: Document MINSTACKSPACE parameter.
-rw-r--r--ChangeLog12
-rwxr-xr-xconfigure83
-rw-r--r--configure.ac5
-rw-r--r--stap.1.in7
-rw-r--r--tapsets.cxx75
-rw-r--r--translate.cxx3
6 files changed, 179 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 1fe67b59..c71a8c27 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2006-11-26 Frank Ch. Eigler <fche@redhat.com>
+
+ PRs 2685, 3596, toward 2725.
+ * tapsets.cxx (common_probe_entryfn_prologue): Skip probe on
+ insufficient stack.
+ (build_blacklist): Add a slew of lock-related calls.
+ (query_module): Check for debuginfo architecture match.
+ * translate.cxx (translate_pass): Add default MINSTACKSPACE.
+ * configure.ac: Link stap with -lebl too.
+ * configure: Regenerated.
+ * stap.1.in: Document MINSTACKSPACE parameter.
+
2006-11-21 Frank Ch. Eigler <fche@elastic.org>
* translate.cxx (emit_module_init): Adapt to 2.6.19 utsname().
diff --git a/configure b/configure
index 240df784..7cee7614 100755
--- a/configure
+++ b/configure
@@ -5859,13 +5859,94 @@ echo "$as_me: error: systemtap requires elfutils 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 gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ebl_openbackend ();
+int
+main ()
+{
+ebl_openbackend ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; 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 conftest.err conftest.$ac_objext \
+ 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: systemtap requires elfutils 0.123+" >&5
+echo "$as_me: error: systemtap requires elfutils 0.123+" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
stap_LIBS="$LIBS"
LIBS="$SAVE_LIBS"
else
# We built our own and stap_LDFLAGS points at the install.
- stap_LIBS=-ldw
+ stap_LIBS="-ldw -lebl"
fi
+{ echo "$as_me:$LINENO: stap will link $stap_LIBS" >&5
+echo "$as_me: stap will link $stap_LIBS" >&6;}
date=`date +%Y-%m-%d`
diff --git a/configure.ac b/configure.ac
index 5ff48549..ea3b61da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,13 +101,16 @@ if test $build_elfutils = no; then
save_LIBS="$LIBS"
AC_CHECK_LIB(dw, dwfl_module_getsym,,[
AC_MSG_ERROR([systemtap requires elfutils 0.123+])])
+ AC_CHECK_LIB(ebl, ebl_openbackend,,[
+ AC_MSG_ERROR([systemtap requires elfutils 0.123+])])
stap_LIBS="$LIBS"
LIBS="$SAVE_LIBS"
else
# We built our own and stap_LDFLAGS points at the install.
- stap_LIBS=-ldw
+ stap_LIBS="-ldw -lebl"
fi
AC_SUBST(stap_LIBS)
+AC_MSG_NOTICE([stap will link $stap_LIBS])
dnl Plop in the build (configure) date
date=`date +%Y-%m-%d`
diff --git a/stap.1.in b/stap.1.in
index 5b5cd3e6..3986c52b 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -746,7 +746,7 @@ script is translated again assuming the same conditions exist (same kernel
version, same systemtap version, etc.). Cached files are stored in
the
.I $SYSTEMTAP_DIR/cache
-directory.
+directory, which may be periodically cleaned/erased by the user.
.SH SAFETY AND SECURITY
Systemtap is an administrative tool. It exposes kernel internal data
@@ -801,6 +801,11 @@ means that the first error will exit the script.
.TP
MAXSKIPPED
Maximum number of skipped reentrant probes before an exit is triggered, default 100.
+.TP
+MINSTACKSPACE
+Minimum number of free kernel stack bytes required in order to
+run a probe handler, default 1024. This number should be large enough
+for the probe handler's own needs, plus a safety margin.
.PP
In case something goes wrong with
diff --git a/tapsets.cxx b/tapsets.cxx
index 55a53cca..852ef378 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -29,6 +29,7 @@ extern "C" {
#include <fcntl.h>
#include <elfutils/libdwfl.h>
#include <elfutils/libdw.h>
+#include <elfutils/libebl.h>
#include <dwarf.h>
#include <elf.h>
#include <obstack.h>
@@ -174,6 +175,16 @@ common_probe_entryfn_prologue (translator_output* o, string statestr)
o->newline() << "local_irq_save (flags);";
+ // Check for enough free enough stack space
+ o->newline() << "if ((((unsigned long) (& c)) & (THREAD_SIZE-1))";
+ o->newline(1) << "< (THREAD_SIZE - MINSTACKSPACE - sizeof (struct task_struct))) {";
+ o->newline() << "if (atomic_inc_return (& skipped_count) > MAXSKIPPED) {";
+ o->newline(1) << "atomic_set (& session_state, STAP_SESSION_ERROR);";
+ o->newline() << "_stp_exit ();";
+ o->newline(-1) << "}";
+ o->newline() << "goto probe_epilogue;";
+ o->newline(-1) << "}";
+
o->newline() << "if (atomic_read (&session_state) != " << statestr << ")";
o->newline(1) << "goto probe_epilogue;";
o->indent(-1);
@@ -717,7 +728,7 @@ struct dwflpp
// NB: "rc == 0" means OK in this case
- void dwfl_assert(string desc, int rc, string extra_msg = "")
+ static void dwfl_assert(string desc, int rc, string extra_msg = "")
{
string msg = "libdwfl failure (" + desc + "): ";
if (rc < 0) msg += dwfl_errmsg (rc);
@@ -2037,6 +2048,18 @@ dwarf_query::build_blacklist()
blacklisted_probes.insert("unhandled_fault");
blacklisted_probes.insert("unknown_nmi_error");
+ blacklisted_probes.insert("_read_trylock");
+ blacklisted_probes.insert("_read_lock");
+ blacklisted_probes.insert("_read_unlock");
+ blacklisted_probes.insert("_write_trylock");
+ blacklisted_probes.insert("_write_lock");
+ blacklisted_probes.insert("_write_unlock");
+ blacklisted_probes.insert("_spin_lock");
+ blacklisted_probes.insert("_spin_lock_irqsave");
+ blacklisted_probes.insert("_spin_trylock");
+ blacklisted_probes.insert("_spin_unlock");
+ blacklisted_probes.insert("_spin_unlock_irqrestore");
+
// __switch_to is only disallowed on x86_64
if (sess.architecture == "x86_64")
blacklisted_probes.insert("__switch_to");
@@ -2748,11 +2771,57 @@ query_module (Dwfl_Module *mod __attribute__ ((unused)),
if (q->has_module && !q->dw.module_name_matches(q->module_val))
return DWARF_CB_OK;
+ // Validate the machine code in this elf file against the
+ // session machine. This is important, in case the wrong kind
+ // of debuginfo is being automagically processed by elfutils.
+ // Unfortunately, while we can tell i686 apart from x86-64,
+ // we can't help confusing i586 vs i686 (both EM_386).
+
+ Dwarf_Addr _junk;
+ Elf* elf = dwfl_module_getelf (mod, &_junk);
+ Ebl* ebl = ebl_openbackend (elf);
+ int elf_machine = ebl_get_elfmachine (ebl);
+ const char* debug_filename = "";
+ const char* main_filename = "";
+ (void) dwfl_module_info (mod, NULL, NULL,
+ NULL, NULL, NULL,
+ & main_filename,
+ & debug_filename);
+ const string& sess_machine = q->sess.architecture;
+ string expect_machine;
+ switch (elf_machine)
+ {
+ case EM_386: expect_machine = "i686"; break;
+ case EM_X86_64: expect_machine = "x86_64"; break;
+ case EM_PPC: expect_machine = "ppc"; break;
+ case EM_PPC64: expect_machine = "ppc64"; break;
+ case EM_S390: expect_machine = "s390x"; break;
+ case EM_IA_64: expect_machine = "ia64"; break;
+ // XXX: fill in some more of these
+ default: expect_machine = "?"; break;
+ }
+
+ if (! debug_filename) debug_filename = main_filename;
+ if (! debug_filename) debug_filename = name;
+
+ if (sess_machine != expect_machine)
+ {
+ stringstream msg;
+ msg << "ELF machine " << expect_machine << " (code " << elf_machine
+ << ") mismatch with target " << sess_machine
+ << " in '" << debug_filename << "'";
+ throw semantic_error(msg.str ());
+ }
+
if (q->sess.verbose>2)
clog << "focused on module '" << q->dw.module_name
- << "' = [" << hex << q->dw.module_start
+ << " = [" << hex << q->dw.module_start
<< "-" << q->dw.module_end
- << ", bias " << q->dw.module_bias << "]" << dec << "\n";
+ << ", bias " << q->dw.module_bias << "]" << dec
+ << " file " << debug_filename
+ << " ELF machine " << expect_machine
+ << " (code " << elf_machine << ")"
+ << "\n";
if (q->has_inline_num || q->has_function_num || q->has_statement_num)
{
diff --git a/translate.cxx b/translate.cxx
index 09c51a6e..f36280da 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -3984,6 +3984,9 @@ translate_pass (systemtap_session& s)
s.op->newline() << "#ifndef MAXSKIPPED";
s.op->newline() << "#define MAXSKIPPED 100";
s.op->newline() << "#endif";
+ s.op->newline() << "#ifndef MINSTACKSPACE";
+ s.op->newline() << "#define MINSTACKSPACE 1024";
+ s.op->newline() << "#endif";
// impedance mismatch
// STP_STRING_SIZE defines the size of the buffer