diff options
-rw-r--r-- | ChangeLog | 46 | ||||
-rw-r--r-- | Makefile.in | 17 | ||||
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | aclocal.m4 | 38 | ||||
-rw-r--r-- | config.in | 6 | ||||
-rwxr-xr-x | configure | 139 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | coveragedb.cxx | 30 | ||||
-rw-r--r-- | elaborate.cxx | 206 | ||||
-rw-r--r-- | main.cxx | 27 | ||||
-rw-r--r-- | runtime/ChangeLog | 38 | ||||
-rw-r--r-- | runtime/runtime.h | 8 | ||||
-rw-r--r-- | runtime/stack-i386.c | 6 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 2 | ||||
-rw-r--r-- | runtime/sym.c | 55 | ||||
-rw-r--r-- | runtime/sym.h | 7 | ||||
-rw-r--r-- | runtime/unwind.c | 32 | ||||
-rw-r--r-- | session.h | 2 | ||||
-rw-r--r-- | systemtap.spec | 51 | ||||
-rw-r--r-- | tapsets.cxx | 12 | ||||
-rw-r--r-- | testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | testsuite/systemtap.base/probe_list.exp | 19 | ||||
-rw-r--r-- | translate.cxx | 101 |
23 files changed, 601 insertions, 258 deletions
@@ -1,3 +1,49 @@ +2008-09-10 Josh Stone <joshua.i.stone@intel.com> + + * main.cxx (printscript): Ensure no variables are printed in probe lists + unless -L was specified. + +2008-09-10 Frank Ch. Eigler <fche@elastic.org> + + PR6876: translator speedup for many $vars + * session.h (systemtap_session.functions): vector->map. + * coveragedb.cxx, elaborate.cxx, main.cxx, tapsets.cxx, translate.cxx: + Adapt all users. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * configure.ac: Check for dwarf_getelf. elfutils 0.126+. + Use AM_PROG_MKDIR_P instead of AC_PROG_MKDIR_P. + * Makefile.in: Regenerated. + * aclocal.m4: Likewise. + * config.in: Likewise. + * configure: Likewise. + +2008-09-10 Dave Brolley <brolley@redhat.com> + + * systemtap.spec: Remove avahi-tools and nc from dependencies + for systemtap and systemtap-runtime packages. Remove stap-* + scripts from %files of systemtap and systemtap-runtime + packages. Make sure systemattap-runtime only picks up + staprun.8* man pages. Create new systemtap-client and + systemtap-server packages. + * NEWS: Add network security warning for the systemtap + client/server. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * translate.cxx (dump_unwindsyms): Rename module_base output to + dwarf_module_base. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * translate.cxx (dump_unwindsyms): Output module_base. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * translate.cxx (get_unwind_data): New function. + (dump_unwindsyms): Output unwind data. + 2008-09-09 Masami Hiramatsu <mhiramat@redhat.com> * stapprobes.5.in: Added a description about $return. diff --git a/Makefile.in b/Makefile.in index ff10a31d..08d82151 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.10 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -1130,8 +1130,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -1156,8 +1156,8 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -1167,13 +1167,12 @@ ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -57,7 +57,13 @@ 4, the client behaves like the 'stap' front end itself. This means, among other things, that the client will automatically load the resulting module on the local host unless -p[1234] - was specified. See stap-server(8) for more details. + was specified. + + This client/server implementation is a prototype. It provides + NO NETWORK SECURITY OF ANY KIND and should be used only + among trusted hosts on a trusted network. + + See stap-server(8) for more details. - Global variables which are written to but never read are now automatically displayed when the session does a shutdown. For example: @@ -1,7 +1,7 @@ -# generated automatically by aclocal 1.10 -*- Autoconf -*- +# generated automatically by aclocal 1.10.1 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -11,12 +11,15 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. -m4_if(m4_PACKAGE_VERSION, [2.61],, -[m4_fatal([this file was generated for autoconf 2.61. -You have another version of autoconf. If you want to use that, -you should regenerate the build system entirely.], [63])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(AC_AUTOCONF_VERSION, [2.61],, +[m4_warning([this file was generated for autoconf 2.61. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) -# Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -31,7 +34,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.10' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.10], [], +m4_if([$1], [1.10.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -47,8 +50,10 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.10])dnl -_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)]) +[AM_AUTOMAKE_VERSION([1.10.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- @@ -343,7 +348,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue @@ -391,13 +396,13 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006 Free Software Foundation, Inc. +# 2005, 2006, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 12 +# serial 13 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. @@ -502,16 +507,17 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJC], # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. +_am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in - $1 | $1:* ) + $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done -echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # @@ -872,7 +878,7 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])]) # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- -# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in. +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) @@ -12,9 +12,6 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `cap' library (-lcap). */ -#undef HAVE_LIBCAP - /* Define to 1 if you have the `dw' library (-ldw). */ #undef HAVE_LIBDW @@ -39,9 +36,6 @@ /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the <sys/capability.h> header file. */ -#undef HAVE_SYS_CAPABILITY_H - /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H @@ -2294,47 +2294,11 @@ fi -{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 -echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; } -if test -z "$MKDIR_P"; then - if test "${ac_cv_path_mkdir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done -done -IFS=$as_save_IFS - -fi - - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - test -d ./--version && rmdir ./--version - MKDIR_P="$ac_install_sh -d" - fi -fi -{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5 -echo "${ECHO_T}$MKDIR_P" >&6; } +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac { echo "$as_me:$LINENO: checking whether ln -s works" >&5 echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } @@ -6532,6 +6496,82 @@ echo "$as_me: error: missing elfutils development headers/libraries (install elf { (exit 1); exit 1; }; } fi + +{ echo "$as_me:$LINENO: checking for dwarf_getelf in -ldw" >&5 +echo $ECHO_N "checking for dwarf_getelf in -ldw... $ECHO_C" >&6; } +if test "${ac_cv_lib_dw_dwarf_getelf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldw -Wl,--start-group -ldw -lebl -Wl,--end-group -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 dwarf_getelf (); +int +main () +{ +return dwarf_getelf (); + ; + 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_dwarf_getelf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dw_dwarf_getelf=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_dwarf_getelf" >&5 +echo "${ECHO_T}$ac_cv_lib_dw_dwarf_getelf" >&6; } +if test $ac_cv_lib_dw_dwarf_getelf = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDW 1 +_ACEOF + + LIBS="-ldw $LIBS" + +else + + { { echo "$as_me:$LINENO: error: elfutils, libdw too old, need 0.126+" >&5 +echo "$as_me: error: elfutils, libdw too old, need 0.126+" >&2;} + { (exit 1); exit 1; }; } +fi + stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf" LIBS="$save_LIBS" else @@ -8220,21 +8260,22 @@ echo "$as_me: $ac_file is unchanged" >&6;} fi rm -f "$tmp/out12" # Compute $ac_file's index in $config_headers. +_am_arg=$ac_file _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in - $ac_file | $ac_file:* ) + $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done -echo "timestamp for $ac_file" >`$as_dirname -- $ac_file || -$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X$ac_file : 'X\(//\)[^/]' \| \ - X$ac_file : 'X\(//\)$' \| \ - X$ac_file : 'X\(/\)' \| . 2>/dev/null || -echo X$ac_file | +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -8271,7 +8312,7 @@ echo "$as_me: executing $ac_file commands" >&6;} # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ diff --git a/configure.ac b/configure.ac index 294fabe1..4a30bc99 100644 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ AC_PREREQ(2.59) AM_INIT_AUTOMAKE AM_MAINTAINER_MODE -AC_PROG_MKDIR_P +AM_PROG_MKDIR_P AC_PROG_LN_S AC_PROG_CC AC_PROG_CXX @@ -183,6 +183,9 @@ if test $build_elfutils = no; then AC_CHECK_LIB(dw, dwfl_module_getsym,[],[ AC_MSG_ERROR([missing elfutils development headers/libraries (install elfutils-devel, libebl-dev, libdw-dev and/or libebl-devel)])], [-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf]) + AC_CHECK_LIB(dw, dwarf_getelf,[],[ + AC_MSG_ERROR([elfutils, libdw too old, need 0.126+])], + [-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf]) stap_LIBS="-Wl,--start-group -ldw -lebl -Wl,--end-group -lelf" LIBS="$save_LIBS" else diff --git a/coveragedb.cxx b/coveragedb.cxx index 63cc4c0f..aafcd545 100644 --- a/coveragedb.cxx +++ b/coveragedb.cxx @@ -62,11 +62,12 @@ void print_coverage_info(systemtap_session &s) } // print out used functions clog << "---- used functions----- " << endl; - for (unsigned i=0; i<s.functions.size(); i++) { - clog << "function: " << s.functions[i]->tok->location - << " " << s.functions[i]->name - << endl; - } + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) + { + clog << "function: " << it->second->tok->location + << " " << it->second->name + << endl; + } // print out unused functions clog << "---- unused functions----- " << endl; for (unsigned i=0; i<s.unused_functions.size(); i++) { @@ -262,15 +263,16 @@ void sql_update_used_functions(sqlite3 *db, systemtap_session &s) { // update db used functions - for (unsigned i=0; i<s.functions.size(); i++) { - struct source_loc place = s.functions[i]->tok->location; - coverage_element x(place); - - x.type = db_type_function; - x.name = s.functions[i]->name; - x.compiled = 1; - increment_element(db, x); - } + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) + { + struct source_loc place = it->second->tok->location; + coverage_element x(place); + + x.type = db_type_function; + x.name = it->second->name; + x.compiled = 1; + increment_element(db, x); + } } diff --git a/elaborate.cxx b/elaborate.cxx index 3dfc7183..552ef338 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -912,8 +912,8 @@ semantic_pass_stats (systemtap_session & sess) { stat_decl_collector sdc(sess); - for (unsigned i = 0; i < sess.functions.size(); ++i) - sess.functions[i]->body->visit (&sdc); + for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++) + it->second->body->visit (&sdc); for (unsigned i = 0; i < sess.probes.size(); ++i) sess.probes[i]->body->visit (&sdc); @@ -946,9 +946,9 @@ semantic_pass_vars (systemtap_session & sess) map<functiondecl *, set<vardecl *> *> fmv; no_var_mutation_during_iteration_check chk(sess, fmv); - for (unsigned i = 0; i < sess.functions.size(); ++i) + for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++) { - functiondecl * fn = sess.functions[i]; + functiondecl * fn = it->second; if (fn->body) { set<vardecl *> * m = new set<vardecl *>(); @@ -958,10 +958,10 @@ semantic_pass_vars (systemtap_session & sess) } } - for (unsigned i = 0; i < sess.functions.size(); ++i) + for (map<string,functiondecl*>::iterator it = sess.functions.begin(); it != sess.functions.end(); it++) { - if (sess.functions[i]->body) - sess.functions[i]->body->visit (&chk); + functiondecl * fn = it->second; + if (fn->body) fn->body->visit (&chk); } for (unsigned i = 0; i < sess.probes.size(); ++i) @@ -1072,7 +1072,7 @@ semantic_pass_symbols (systemtap_session& s) s.globals.push_back (dome->globals[i]); for (unsigned i=0; i<dome->functions.size(); i++) - s.functions.push_back (dome->functions[i]); + s.functions[dome->functions[i]->name] = dome->functions[i]; for (unsigned i=0; i<dome->embeds.size(); i++) s.embeds.push_back (dome->embeds[i]); @@ -1735,11 +1735,12 @@ symresolution_info::find_var (const string& name, int arity) functiondecl* symresolution_info::find_function (const string& name, unsigned arity) { - for (unsigned j = 0; j < session.functions.size(); j++) + // the common path + if (session.functions.find(name) != session.functions.end()) { - functiondecl* fd = session.functions[j]; - if (fd->name == name && - fd->formal_args.size() == arity) + functiondecl* fd = session.functions[name]; + assert (fd->name == name); + if (fd->formal_args.size() == arity) return fd; } @@ -1785,25 +1786,30 @@ void semantic_pass_opt1 (systemtap_session& s, bool& relaxed_p) if (s.probes[i]->sole_location()->condition) s.probes[i]->sole_location()->condition->visit (& ftv); } - for (unsigned i=0; i<s.functions.size(); /* see below */) + vector<functiondecl*> new_unused_functions; + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { - if (ftv.traversed.find(s.functions[i]) == ftv.traversed.end()) + functiondecl* fd = it->second; + if (ftv.traversed.find(fd) == ftv.traversed.end()) { - if (s.functions[i]->tok->location.file == s.user_file->name && // !tapset + if (fd->tok->location.file == s.user_file->name && // !tapset ! s.suppress_warnings) - s.print_warning ("eliding unused function '" + s.functions[i]->name + "'", s.functions[i]->tok); + s.print_warning ("eliding unused function '" + fd->name + "'", fd->tok); else if (s.verbose>2) - clog << "Eliding unused function " << s.functions[i]->name + clog << "Eliding unused function " << fd->name << endl; - if (s.tapset_compile_coverage) { - s.unused_functions.push_back (s.functions[i]); - } - s.functions.erase (s.functions.begin() + i); + // s.functions.erase (it); // NB: can't, since we're already iterating upon it + new_unused_functions.push_back (fd); relaxed_p = false; - // NB: don't increment i } - else - i++; + } + for (unsigned i=0; i<new_unused_functions.size(); i++) + { + map<string,functiondecl*>::iterator where = s.functions.find (new_unused_functions[i]->name); + assert (where != s.functions.end()); + s.functions.erase (where); + if (s.tapset_compile_coverage) + s.unused_functions.push_back (new_unused_functions[i]); } } @@ -1877,53 +1883,55 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati } } - for (unsigned i=0; i<s.functions.size(); i++) - for (unsigned j=0; j<s.functions[i]->locals.size(); /* see below */) - { - vardecl* l = s.functions[i]->locals[j]; - if (vut.read.find (l) == vut.read.end() && - vut.written.find (l) == vut.written.end()) - { - if (l->tok->location.file == s.user_file->name && // !tapset - ! s.suppress_warnings) - s.print_warning ("eliding unused variable '" + l->name + "'", l->tok); - else if (s.verbose>2) - clog << "Eliding unused local variable " - << l->name << " in function " << s.functions[i]->name - << endl; - if (s.tapset_compile_coverage) { - s.functions[i]->unused_locals.push_back - (s.functions[i]->locals[j]); - } - s.functions[i]->locals.erase(s.functions[i]->locals.begin() + j); - relaxed_p = false; - // don't increment j - } - else - { - if (vut.written.find (l) == vut.written.end()) - if (iterations == 0 && ! s.suppress_warnings) - { - stringstream o; - vector<vardecl*>::iterator it; - for ( it = s.functions[i]->formal_args.begin() ; - it != s.functions[i]->formal_args.end(); it++) - if (l->name != (*it)->name) - o << " " << (*it)->name; - for (it = s.functions[i]->locals.begin(); it != s.functions[i]->locals.end(); it++) - if (l->name != (*it)->name) - o << " " << (*it)->name; - for (it = s.globals.begin(); it != s.globals.end(); it++) - if (l->name != (*it)->name) - o << " " << (*it)->name; - - s.print_warning ("read-only local variable '" + l->name + "' " + - (o.str() == "" ? "" : ("(alternatives:" + o.str() + ")")), l->tok); - } + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) + { + functiondecl *fd = it->second; + for (unsigned j=0; j<fd->locals.size(); /* see below */) + { + vardecl* l = fd->locals[j]; + if (vut.read.find (l) == vut.read.end() && + vut.written.find (l) == vut.written.end()) + { + if (l->tok->location.file == s.user_file->name && // !tapset + ! s.suppress_warnings) + s.print_warning ("eliding unused variable '" + l->name + "'", l->tok); + else if (s.verbose>2) + clog << "Eliding unused local variable " + << l->name << " in function " << fd->name + << endl; + if (s.tapset_compile_coverage) { + fd->unused_locals.push_back (fd->locals[j]); + } + fd->locals.erase(fd->locals.begin() + j); + relaxed_p = false; + // don't increment j + } + else + { + if (vut.written.find (l) == vut.written.end()) + if (iterations == 0 && ! s.suppress_warnings) + { + stringstream o; + vector<vardecl*>::iterator it; + for (it = fd->formal_args.begin() ; + it != fd->formal_args.end(); it++) + if (l->name != (*it)->name) + o << " " << (*it)->name; + for (it = fd->locals.begin(); it != fd->locals.end(); it++) + if (l->name != (*it)->name) + o << " " << (*it)->name; + for (it = s.globals.begin(); it != s.globals.end(); it++) + if (l->name != (*it)->name) + o << " " << (*it)->name; + + s.print_warning ("read-only local variable '" + l->name + "' " + + (o.str() == "" ? "" : ("(alternatives:" + o.str() + ")")), l->tok); + } - j++; - } - } + j++; + } + } + } for (unsigned i=0; i<s.globals.size(); /* see below */) { vardecl* l = s.globals[i]; @@ -1932,7 +1940,7 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati { if (l->tok->location.file == s.user_file->name && // !tapset ! s.suppress_warnings) - s.print_warning ("eliding unused variable '" + l->name + "'", l->tok); + s.print_warning ("eliding unused variable '" + l->name + "'", l->tok); else if (s.verbose>2) clog << "Eliding unused global variable " << l->name << endl; @@ -2144,8 +2152,8 @@ void semantic_pass_opt3 (systemtap_session& s, bool& relaxed_p) for (unsigned i=0; i<s.probes.size(); i++) s.probes[i]->body->visit (& dar); - for (unsigned i=0; i<s.functions.size(); i++) - s.functions[i]->body->visit (& dar); + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) + it->second->body->visit (& dar); // The rewrite operation is performed within the visitor. // XXX: we could also zap write-only globals here @@ -2390,6 +2398,8 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) for (unsigned i=0; i<s.probes.size(); i++) { + if (pending_interrupts) break; + derived_probe* p = s.probes[i]; duv.focal_vars.clear (); @@ -2411,9 +2421,11 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) // XXX: possible duplicate warnings; see below } } - for (unsigned i=0; i<s.functions.size(); i++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { - functiondecl* fn = s.functions[i]; + if (pending_interrupts) break; + + functiondecl* fn = it->second; duv.focal_vars.clear (); duv.focal_vars.insert (fn->locals.begin(), fn->locals.end()); @@ -2788,9 +2800,9 @@ void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p) vuv.current_stmt = & p->body; p->body->visit (& vuv); } - for (unsigned i=0; i<s.functions.size(); i++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { - functiondecl* fn = s.functions[i]; + functiondecl* fn = it->second; vuv.current_stmt = & fn->body; fn->body->visit (& vuv); } @@ -2854,30 +2866,34 @@ void semantic_pass_opt6 (systemtap_session& s, bool& relaxed_p) // Walk through all the functions, looking for duplicates. map<string, functiondecl*> functionsig_map; map<functiondecl*, functiondecl*> duplicate_function_map; - for (unsigned i=0; i < s.functions.size(); /* see below */) + + + vector<functiondecl*> newly_zapped_functions; + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { - string functionsig = get_functionsig(s.functions[i]); + functiondecl *fd = it->second; + string functionsig = get_functionsig(fd); if (functionsig_map.count(functionsig) == 0) { // This function is unique. Remember it. - functionsig_map[functionsig] = s.functions[i]; - i++; + functionsig_map[functionsig] = fd; } else { // This function is a duplicate. - duplicate_function_map[s.functions[i]] - = functionsig_map[functionsig]; - - // Remove the duplicate function (since we don't need it - // anymore). - s.functions.erase (s.functions.begin() + i); - + duplicate_function_map[fd] = functionsig_map[functionsig]; + newly_zapped_functions.push_back (fd); relaxed_p = false; - // NB: don't increment i } } + for (unsigned i=0; i<newly_zapped_functions.size(); i++) + { + map<string,functiondecl*>::iterator where = s.functions.find (newly_zapped_functions[i]->name); + assert (where != s.functions.end()); + s.functions.erase (where); + } + // If we have duplicate functions, traverse down the tree, replacing // the appropriate function calls. @@ -2971,21 +2987,21 @@ semantic_pass_types (systemtap_session& s) ti.num_newly_resolved = 0; ti.num_still_unresolved = 0; - for (unsigned j=0; j<s.functions.size(); j++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { if (pending_interrupts) break; - functiondecl* fn = s.functions[j]; + functiondecl* fd = it->second; ti.current_probe = 0; - ti.current_function = fn; + ti.current_function = fd; ti.t = pe_unknown; - fn->body->visit (& ti); + fd->body->visit (& ti); // NB: we don't have to assert a known type for // functions here, to permit a "void" function. // The translator phase will omit the "retvalue". // - // if (fn->type == pe_unknown) - // ti.unresolved (fn->tok); + // if (fd->type == pe_unknown) + // ti.unresolved (fd->tok); } for (unsigned j=0; j<s.probes.size(); j++) @@ -147,6 +147,8 @@ printscript(systemtap_session& s, ostream& o) for (unsigned i=0; i<s.probes.size(); i++) { + if (pending_interrupts) return; + derived_probe* p = s.probes[i]; // NB: p->basest() is not so interesting; // p->almost_basest() doesn't quite work, so ... @@ -180,14 +182,15 @@ printscript(systemtap_session& s, ostream& o) if (seen.find (pp) == seen.end()) { o << pp; - // This list will be empty unless s.unoptimized = true -- i.e., -L mode - for (unsigned j=0; j<p->locals.size(); j++) - { - o << " "; - vardecl* v = p->locals[j]; - v->printsig (o); - } - o << endl; + // Print the locals for -L mode only + if (s.unoptimized) + for (unsigned j=0; j<p->locals.size(); j++) + { + o << " "; + vardecl* v = p->locals[j]; + v->printsig (o); + } + o << endl; seen.insert (pp); } } @@ -198,6 +201,7 @@ printscript(systemtap_session& s, ostream& o) o << "# global embedded code" << endl; for (unsigned i=0; i<s.embeds.size(); i++) { + if (pending_interrupts) return; embeddedcode* ec = s.embeds[i]; ec->print (o); o << endl; @@ -207,6 +211,7 @@ printscript(systemtap_session& s, ostream& o) o << "# globals" << endl; for (unsigned i=0; i<s.globals.size(); i++) { + if (pending_interrupts) return; vardecl* v = s.globals[i]; v->printsig (o); if (s.verbose && v->init) @@ -219,9 +224,10 @@ printscript(systemtap_session& s, ostream& o) if (s.functions.size() > 0) o << "# functions" << endl; - for (unsigned i=0; i<s.functions.size(); i++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { - functiondecl* f = s.functions[i]; + if (pending_interrupts) return; + functiondecl* f = it->second; f->printsig (o); o << endl; if (f->locals.size() > 0) @@ -244,6 +250,7 @@ printscript(systemtap_session& s, ostream& o) o << "# probes" << endl; for (unsigned i=0; i<s.probes.size(); i++) { + if (pending_interrupts) return; derived_probe* p = s.probes[i]; p->printsig (o); o << endl; diff --git a/runtime/ChangeLog b/runtime/ChangeLog index f7a844d8..97b1a0c0 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,36 @@ +2008-09-10 Frank Ch. Eigler <fche@elastic.org> + + * runtime.h (STP_USE_FRAME_POINTER): Remove architecture #if's. + All will activate it if CONFIG_FRAME_POINTER unless + STP_USE_DWARF_UNWINDER. + * stack-i386.c: (__stp_stack_print): Handle !DWARF and !FRAME + configuration. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * sym.h (_stp_module): Rename module_base to dwarf_module_base. + * unwind.c (adjustStartLoc): Document and use dwarf_module_base. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * runtime.h (CONFIG_FRAME_POINTER): Don't enable when + STP_USE_DWARF_UNWINDER is already defined. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * sym.h (_stp_module): Add module_base field. + * unwind.c (adjustStartLoc): New function. + (_stp_search_unwind_hdr): Use adjustStartLoc. + (unwind): Likewise. + +2008-09-10 Mark Wielaard <mjw@redhat.com> + + * unwind.c (unwind): Use _stp_mod_sec_lookup to get module and + unwind tables. + * runtime.h (STP_USE_FRAME_BUFFER): Disable by default for now. + * stack-x86_64.c (__stp_stack_print): Add levels to + _stp_stack_print_fallback call. + 2008-09-09 Masami Hiramatsu <mhiramat@redhat.com> * regs-ia64.c (__ia64_fetch_register): Return the address of the @@ -15,6 +48,11 @@ 2008-09-09 Mark Wielaard <mwielaard@redhat.com> + * sym.c (_stp_mod_sec_lookup): New function, extracted from + _stp_kallsyms_lookup. + +2008-09-09 Mark Wielaard <mwielaard@redhat.com> + * sym.c (_stp_kallsyms_lookup): Correct this_section_offset calculation. diff --git a/runtime/runtime.h b/runtime/runtime.h index fd0cac9e..cd3d0b11 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -68,13 +68,15 @@ static struct #ifdef CONFIG_FRAME_POINTER /* Just because frame pointers are available does not mean we can trust them. */ -#if defined (__i386__) || defined (__arm__) +#ifndef STP_USE_DWARF_UNWINDER #define STP_USE_FRAME_POINTER #endif #endif -/* dwarf unwinder only tested so far on i386 and x86_64 */ -#if !defined(STP_USE_FRAME_BUFFER) && (defined(__i386__) || defined(__x86_64__)) +/* dwarf unwinder only tested so far on i386 and x86_64, + but globally disabled for now */ +#if 0 +// !defined(STP_USE_FRAME_BUFFER) && (defined(__i386__) || defined(__x86_64__)) #define STP_USE_DWARF_UNWINDER #endif diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index ad101889..ed7e2ce1 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -54,9 +54,10 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) fp = next_fp; } #else +#ifdef STP_USE_DWARF_UNWINDER struct unwind_frame_info info; arch_unw_init_frame_info(&info, regs); - + while (levels && !arch_unw_user_mode(&info)) { int ret = unwind(&info); dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info)); @@ -71,5 +72,8 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) _stp_stack_print_fallback(context, UNW_SP(&info), verbose, levels); break; } +#else /* ! STP_USE_DWARF_UNWINDER */ + _stp_stack_print_fallback(context, (unsigned long)®_SP(regs), verbose, levels); #endif /* STP_USE_FRAME_POINTER */ +#endif } diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 783e72bd..d3ec91cf 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -45,6 +45,6 @@ static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels) break; } #else /* ! STP_USE_DWARF_UNWINDER */ - _stp_stack_print_fallback(REG_SP(regs), verbose); + _stp_stack_print_fallback(REG_SP(regs), verbose, levels); #endif } diff --git a/runtime/sym.c b/runtime/sym.c index b594d9c2..1a9e26b2 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -73,6 +73,37 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi } +/* Return module owner and fills in closest section of the address + if found, return NULL otherwise. + XXX: needs to be address-space-specific. */ +static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, + struct _stp_section **sec) +{ + struct _stp_module *m = NULL; + unsigned midx = 0; + unsigned long closest_section_offset = ~0; + for (midx = 0; midx < _stp_num_modules; midx++) + { + unsigned secidx; + for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++) + { + unsigned long this_section_addr; + unsigned long this_section_offset; + this_section_addr = _stp_modules[midx]->sections[secidx].addr; + if (addr < this_section_addr) continue; + this_section_offset = addr - this_section_addr; + if (this_section_offset < closest_section_offset) + { + closest_section_offset = this_section_offset; + m = _stp_modules[midx]; + *sec = & m->sections[secidx]; + } + } + } + return m; +} + + /* XXX: needs to be address-space-specific. */ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbolsize, unsigned long *offset, @@ -86,29 +117,7 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo unsigned long flags; unsigned end, begin = 0; - /* Find the closest section (and its owner module); fill in m & sec. */ - { - unsigned midx = 0; - unsigned long closest_section_offset = ~0; - for (midx = 0; midx < _stp_num_modules; midx++) - { - unsigned secidx; - for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++) - { - unsigned long this_section_addr = _stp_modules[midx]->sections[secidx].addr; - unsigned long this_section_offset; - if (addr < this_section_addr) continue; - this_section_offset = addr - this_section_addr; - if (this_section_offset < closest_section_offset) - { - closest_section_offset = this_section_offset; - m = _stp_modules[midx]; - sec = & m->sections[secidx]; - } - } - } - } - + m = _stp_mod_sec_lookup(addr, &sec); if (unlikely (m == NULL || sec == NULL)) return NULL; diff --git a/runtime/sym.h b/runtime/sym.h index b2fb8ee9..5888d2c7 100644 --- a/runtime/sym.h +++ b/runtime/sym.h @@ -33,7 +33,12 @@ struct _stp_module { /* any notifier hooks that will tell us when a module */ /* is unloading. */ unsigned long module; /* XXX: why not struct module * ? */ - + + /* This is to undo .debug_frame relocation performed by elfutils, */ + /* which is done during the translate phase when we encode the */ + /* unwind data into the module. See adjustStartLoc() in unwind.c. */ + unsigned long dwarf_module_base; + /* the stack unwind data for this module */ void *unwind_data; void *unwind_hdr; diff --git a/runtime/unwind.c b/runtime/unwind.c index 21ea4559..bc8a93dc 100644 --- a/runtime/unwind.c +++ b/runtime/unwind.c @@ -550,10 +550,29 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, s return result && ptr.p8 == end && (targetLoc == 0 || state->label == NULL); } +// If this is an address inside a module, adjust for section relocation +// and the elfutils base relocation done during loading of the .dwarf_frame +// in translate.cxx. +static unsigned long +adjustStartLoc (unsigned long startLoc, + struct _stp_module *m, + struct _stp_section *s) +{ + if (startLoc && (strcmp (m->name, "kernel") != 0)) + { + startLoc = _stp_module_relocate (m->name, s->name, + startLoc); + startLoc -= m->dwarf_module_base; + } + return startLoc; +} + /* If we previously created an unwind header, then use it now to binary search */ /* for the FDE corresponding to pc. */ -static u32 *_stp_search_unwind_hdr(unsigned long pc, struct _stp_module *m) +static u32 *_stp_search_unwind_hdr(unsigned long pc, + struct _stp_module *m, + struct _stp_section *s) { const u8 *ptr, *end, *hdr = m->unwind_hdr; unsigned long startLoc; @@ -600,6 +619,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc, struct _stp_module *m) do { const u8 *cur = ptr + (num / 2) * (2 * tableSize); startLoc = read_pointer(&cur, cur + tableSize, hdr[3]); + startLoc = adjustStartLoc(startLoc, m, s); if (pc < startLoc) num /= 2; else { @@ -608,7 +628,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc, struct _stp_module *m) } } while (startLoc && num > 1); - if (num == 1 && (startLoc = read_pointer(&ptr, ptr + tableSize, hdr[3])) != 0 && pc >= startLoc) + if (num == 1 && (startLoc = adjustStartLoc(read_pointer(&ptr, ptr + tableSize, hdr[3]), m, s)) != 0 && pc >= startLoc) fde = (void *)read_pointer(&ptr, ptr + tableSize, hdr[3]); dbug_unwind(1, "returning fde=%lx startLoc=%lx", fde, startLoc); @@ -676,6 +696,7 @@ int unwind(struct unwind_frame_info *frame) signed ptrType = -1; uleb128_t retAddrReg = 0; struct _stp_module *m; + struct _stp_section *s = NULL; struct unwind_state state; dbug_unwind(1, "pc=%lx, %lx", pc, UNW_PC(frame)); @@ -683,7 +704,7 @@ int unwind(struct unwind_frame_info *frame) if (UNW_PC(frame) == 0) return -EINVAL; - m = NULL /*_stp_get_unwind_info(pc) */; + m = _stp_mod_sec_lookup (pc, &s); if (unlikely(m == NULL)) { dbug_unwind(1, "No module found for pc=%lx", pc); return -EINVAL; @@ -694,7 +715,7 @@ int unwind(struct unwind_frame_info *frame) goto err; } - fde = _stp_search_unwind_hdr(pc, m); + fde = _stp_search_unwind_hdr(pc, m, s); dbug_unwind(1, "%s: fde=%lx\n", m->name, fde); /* found the fde, now set startLoc and endLoc */ @@ -704,6 +725,8 @@ int unwind(struct unwind_frame_info *frame) ptr = (const u8 *)(fde + 2); ptrType = fde_pointer_type(cie); startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); + startLoc = adjustStartLoc(startLoc, m, s); + dbug_unwind(2, "startLoc=%lx, ptrType=%s", startLoc, _stp_eh_enc_name(ptrType)); if (!(ptrType & DW_EH_PE_indirect)) ptrType &= DW_EH_PE_FORM | DW_EH_PE_signed; @@ -733,6 +756,7 @@ int unwind(struct unwind_frame_info *frame) ptr = (const u8 *)(fde + 2); startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); + startLoc = adjustStartLoc(startLoc, m, s); dbug_unwind(2, "startLoc=%lx, ptrType=%s", startLoc, _stp_eh_enc_name(ptrType)); if (!startLoc) continue; @@ -131,7 +131,7 @@ struct systemtap_session // resolved globals/functions/probes for the run as a whole std::vector<stapfile*> files; std::vector<vardecl*> globals; - std::vector<functiondecl*> functions; + std::map<std::string,functiondecl*> functions; std::vector<derived_probe*> probes; // see also *_probes groups below std::vector<embeddedcode*> embeds; std::map<std::string, statistic_decl> stat_decls; diff --git a/systemtap.spec b/systemtap.spec index e9050d77..4a7d2b4a 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -45,7 +45,6 @@ Requires: crash %if %{with_docs} BuildRequires: /usr/bin/latex /usr/bin/dvips /usr/bin/ps2pdf latex2html %endif -Requires: avahi-tools nc %description SystemTap is an instrumentation system for systems running Linux 2.6. @@ -59,7 +58,6 @@ License: GPLv2+ URL: http://sourceware.org/systemtap/ Requires: kernel >= 2.6.9-11 Requires(pre): shadow-utils -Requires: avahi-tools nc %description runtime SystemTap runtime is the runtime component of an instrumentation @@ -77,6 +75,32 @@ Requires: systemtap dejagnu The testsuite allows testing of the entire SystemTap toolchain without having to rebuild from sources. +%package client +Summary: Instrumentation System Client +Group: Development/System +License: GPLv2+ +URL: http://sourceware.org/systemtap/ +Requires: systemtap-runtime = %{version}-%{release} +Requires: avahi-tools nc mktemp + +%description client +SystemTap client is the client component of an instrumentation +system for systems running Linux 2.6. Developers can write +instrumentation to collect data on the operation of the system. + +%package server +Summary: Instrumentation System Server +Group: Development/System +License: GPLv2+ +URL: http://sourceware.org/systemtap/ +Requires: systemtap +Requires: avahi-tools nc net-tools mktemp + +%description server +SystemTap server is the server component of an instrumentation +system for systems running Linux 2.6. Developers can write +instrumentation to collect data on the operation of the system. + %prep %setup -q %{?setup_elfutils} @@ -183,8 +207,6 @@ exit 0 %endif %{_bindir}/stap -%{_bindir}/stap-server -%{_bindir}/stap-serverd %{_mandir}/man1/* %{_mandir}/man5/* @@ -205,13 +227,8 @@ exit 0 %files runtime %defattr(-,root,root) %attr(4111,root,root) %{_bindir}/staprun -%{_bindir}/stap-client -%{_bindir}/stap-find-servers -%{_bindir}/stap-start-server -%{_bindir}/stap-find-or-start-server -%{_bindir}/stap-stop-server %{_libexecdir}/%{name} -%{_mandir}/man8/* +%{_mandir}/man8/staprun.8* %doc README AUTHORS NEWS COPYING @@ -219,6 +236,20 @@ exit 0 %defattr(-,root,root) %{_datadir}/%{name}/testsuite +%files client +%defattr(-,root,root) +%{_bindir}/stap-client +%{_bindir}/stap-find-servers +%{_bindir}/stap-find-or-start-server +%{_mandir}/man8/stap-server.8* + +%files server +%defattr(-,root,root) +%{_bindir}/stap-server +%{_bindir}/stap-serverd +%{_bindir}/stap-start-server +%{_bindir}/stap-stop-server +%{_mandir}/man8/stap-server.8* %changelog * Tue Jul 15 2008 Frank Ch. Eigler <fche@redhat.com> - 0.7-1 diff --git a/tapsets.cxx b/tapsets.cxx index 28f945fe..308cef1f 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1090,6 +1090,7 @@ struct dwflpp for (unsigned i=0; i<v->size(); i++) { + if (pending_interrupts) return; Dwarf_Die die = v->at(i); int rc = (*callback)(& die, data); if (rc != DWARF_CB_OK) break; @@ -2659,6 +2660,7 @@ dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, void * arg), { for (cu_function_cache_t::iterator it = v->begin(); it != v->end(); it++) { + if (pending_interrupts) return DWARF_CB_ABORT; string func_name = it->first; Dwarf_Die die = it->second; if (function_name_matches_pattern (func_name, subkey)) @@ -4428,6 +4430,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) } const char *diename = dwarf_diename (&result); + if (! diename) continue; + tsym->tok = e->tok; tsym->base_name = "$"; tsym->base_name += diename; @@ -4526,7 +4530,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) v->tok = e->tok; fdecl->formal_args.push_back(v); } - q.sess.functions.push_back(fdecl); + q.sess.functions[fdecl->name]=fdecl; // Synthesize a functioncall. functioncall* n = new functioncall; @@ -7684,7 +7688,7 @@ procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) v->tok = e->tok; fdecl->formal_args.push_back(v); } - sess.functions.push_back(fdecl); + sess.functions[fdecl->name]=fdecl; // Synthesize a functioncall. functioncall* n = new functioncall; @@ -7930,7 +7934,7 @@ mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) fdecl->name = fname; fdecl->body = ec; fdecl->type = mark_args[argnum-1]->stp_type; - sess.functions.push_back(fdecl); + sess.functions[fdecl->name]=fdecl; // Synthesize a functioncall. functioncall* n = new functioncall; @@ -8838,7 +8842,7 @@ perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) fdecl->name = fname; fdecl->body = ec; fdecl->type = pe_long; - sess.functions.push_back(fdecl); + sess.functions[fdecl->name]=fdecl; // Synthesize a functioncall. functioncall* n = new functioncall; diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index 3effc92f..288705b1 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-09-10 Josh Stone <joshua.i.stone@intel.com> + + * systemtap.base/probe_list.exp: New test for correct probe listing. + 2008-09-09 Frank Ch. Eigler <fche@elastic.org> * systemtap.base/uprobes.*: Tweak regexps for read-only src tree diff --git a/testsuite/systemtap.base/probe_list.exp b/testsuite/systemtap.base/probe_list.exp new file mode 100644 index 00000000..b3e6884b --- /dev/null +++ b/testsuite/systemtap.base/probe_list.exp @@ -0,0 +1,19 @@ +# This test ensures that "-l" lists only include probe names, and not any of +# the local variables. There was a bug that "-l" would print variables that +# couldn't be optimized away, due to an incorrect assumption in the +# implementation. + +# NB: This is a bit abusively formed. Currently -l internally writes "probe" +# and "{}" around its argument. For this test we want to introduce a variable +# that can't be optimized away. The trailing comment mark lets the auto "{}" +# get ignored. +spawn stap -l "begin { if (a) next }#" + +expect { + # the output should not include anything else, like the 'a' local. + -re "^begin\r\n$" { + pass "probe list is correct" + return + } +} +fail "probe list is incorrect" diff --git a/translate.cxx b/translate.cxx index e5435fac..64308fe3 100644 --- a/translate.cxx +++ b/translate.cxx @@ -948,9 +948,9 @@ c_unparser::emit_common_header () } } - for (unsigned i=0; i<session->functions.size(); i++) + for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++) { - functiondecl* fd = session->functions[i]; + functiondecl* fd = it->second; o->newline() << "struct function_" << c_varname (fd->name) << "_locals {"; o->indent(1); @@ -1778,8 +1778,8 @@ c_unparser::emit_map_type_instantiations () for (unsigned i = 0; i < session->probes.size(); ++i) collect_map_index_types(session->probes[i]->locals, types); - for (unsigned i = 0; i < session->functions.size(); ++i) - collect_map_index_types(session->functions[i]->locals, types); + for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++) + collect_map_index_types(it->second->locals, types); if (!types.empty()) o->newline() << "#include \"alloc.c\""; @@ -4340,6 +4340,43 @@ struct unwindsym_dump_context }; +// Get the .debug_frame section for the given module. +// l will be set to the length of the size of the unwind data if found. +static void *get_unwind_data (Dwfl_Module *m, size_t *l) +{ + Dwarf_Addr bias = 0; + Dwarf *dw; + GElf_Ehdr *ehdr, ehdr_mem; + GElf_Shdr *shdr, shdr_mem; + Elf_Scn *scn = NULL; + Elf_Data *data = NULL; + + dw = dwfl_module_getdwarf(m, &bias); + if (dw != NULL) + { + Elf *elf = dwarf_getelf(dw); + ehdr = gelf_getehdr(elf, &ehdr_mem); + while ((scn = elf_nextscn(elf, scn))) + { + shdr = gelf_getshdr(scn, &shdr_mem); + if (strcmp(elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name), + ".debug_frame") == 0) + { + data = elf_rawdata(scn, NULL); + break; + } + } + } + + if (data != NULL) + { + *l = data->d_size; + return data->d_buf; + } + + return NULL; +} + static int dump_unwindsyms (Dwfl_Module *m, void **userdata __attribute__ ((unused)), @@ -4431,7 +4468,7 @@ dump_unwindsyms (Dwfl_Module *m, else if (n > 0) { assert (secname != NULL); - // secname adequately set + // secname adequately set // NB: it may be an empty string for ET_DYN objects // like shared libraries, as their relocation base @@ -4459,6 +4496,31 @@ dump_unwindsyms (Dwfl_Module *m, } } + // Add unwind data to be included if it exists for this module. + size_t len = 0; + void *unwind = get_unwind_data (m, &len); + if (unwind != NULL) + { + c->output << "#ifdef STP_USE_DWARF_UNWINDER" << endl; + c->output << "static uint8_t _stp_module_" << stpmod_idx + << "_unwind_data[] = " << endl; + c->output << " {"; + for (size_t i = 0; i < len; i++) + { + int h = ((uint8_t *)unwind)[i]; + c->output << "0x" << hex << h << dec << ","; + if ((i + 1) % 16 == 0) + c->output << endl << " "; + } + c->output << "};" << endl; + c->output << "#endif /* STP_USE_DWARF_UNWINDER */" << endl; + } + else + { + c->session.print_warning ("No unwind data for " + modname + + ", " + dwfl_errmsg (-1)); + } + for (unsigned secidx = 0; secidx < seclist.size(); secidx++) { c->output << "struct _stp_symbol " @@ -4489,6 +4551,27 @@ dump_unwindsyms (Dwfl_Module *m, c->output << "struct _stp_module _stp_module_" << stpmod_idx << " = {" << endl; c->output << ".name = " << lex_cast_qstring (modname) << ", " << endl; + c->output << ".dwarf_module_base = 0x" << hex << base << dec << ", " << endl; + + if (unwind != NULL) + { + c->output << "#ifdef STP_USE_DWARF_UNWINDER" << endl; + c->output << ".unwind_data = " + << "_stp_module_" << stpmod_idx << "_unwind_data, " << endl; + c->output << ".unwind_data_len = " << len << ", " << endl; + c->output << "#else" << endl; + } + + c->output << ".unwind_data = NULL, " << endl; + c->output << ".unwind_data_len = 0, " << endl; + + if (unwind != NULL) + c->output << "#endif /* STP_USE_DWARF_UNWINDER */" << endl; + + c->output << ".unwind_hdr = NULL, " << endl; + c->output << ".unwind_hdr_len = 0, " << endl; + c->output << ".unwind_is_ehframe = 0, " << endl; + c->output << ".sections = _stp_module_" << stpmod_idx << "_sections" << ", " << endl; c->output << ".num_sections = sizeof(_stp_module_" << stpmod_idx << "_sections)/" << "sizeof(struct _stp_section), " << endl; @@ -4724,19 +4807,19 @@ translate_pass (systemtap_session& s) s.op->newline(-1) << "};"; s.op->assert_0_indent(); - for (unsigned i=0; i<s.functions.size(); i++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { if (pending_interrupts) return 1; s.op->newline(); - s.up->emit_functionsig (s.functions[i]); + s.up->emit_functionsig (it->second); } s.op->assert_0_indent(); - for (unsigned i=0; i<s.functions.size(); i++) + for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++) { if (pending_interrupts) return 1; s.op->newline(); - s.up->emit_function (s.functions[i]); + s.up->emit_function (it->second); } s.op->assert_0_indent(); |