diff options
author | fche <fche> | 2006-11-26 23:28:15 +0000 |
---|---|---|
committer | fche <fche> | 2006-11-26 23:28:15 +0000 |
commit | c931ec8ab64f5b6667e28b0f64338643d4b9ed03 (patch) | |
tree | 80b739d8a696c6acc3ce26853ebc9c8de603c52f | |
parent | cc7d24cd109128d558445507e508f5b43906ef16 (diff) | |
download | systemtap-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-- | ChangeLog | 12 | ||||
-rwxr-xr-x | configure | 83 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | stap.1.in | 7 | ||||
-rw-r--r-- | tapsets.cxx | 75 | ||||
-rw-r--r-- | translate.cxx | 3 |
6 files changed, 179 insertions, 6 deletions
@@ -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(). @@ -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` @@ -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 |