summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorddomingo <ddomingo@redhat.com>2008-09-11 12:07:38 +1000
committerddomingo <ddomingo@redhat.com>2008-09-11 12:07:38 +1000
commit936eeb672167eaec2e5d8e9d7cf7fe9e962efe58 (patch)
treef340b3f78479294491e76e6533c28160b3cc2ee1
parent6f57b072898d1858e0af448169c759dd44efddca (diff)
parent223f5b6b6e2c945c442a5dde7e63e637237f575b (diff)
downloadsystemtap-steved-936eeb672167eaec2e5d8e9d7cf7fe9e962efe58.tar.gz
systemtap-steved-936eeb672167eaec2e5d8e9d7cf7fe9e962efe58.tar.xz
systemtap-steved-936eeb672167eaec2e5d8e9d7cf7fe9e962efe58.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
-rw-r--r--ChangeLog46
-rw-r--r--Makefile.in17
-rw-r--r--NEWS8
-rw-r--r--aclocal.m438
-rw-r--r--config.in6
-rwxr-xr-xconfigure139
-rw-r--r--configure.ac5
-rw-r--r--coveragedb.cxx30
-rw-r--r--elaborate.cxx206
-rw-r--r--main.cxx27
-rw-r--r--runtime/ChangeLog38
-rw-r--r--runtime/runtime.h8
-rw-r--r--runtime/stack-i386.c6
-rw-r--r--runtime/stack-x86_64.c2
-rw-r--r--runtime/sym.c55
-rw-r--r--runtime/sym.h7
-rw-r--r--runtime/unwind.c32
-rw-r--r--session.h2
-rw-r--r--systemtap.spec51
-rw-r--r--tapsets.cxx12
-rw-r--r--testsuite/ChangeLog4
-rw-r--r--testsuite/systemtap.base/probe_list.exp19
-rw-r--r--translate.cxx101
23 files changed, 601 insertions, 258 deletions
diff --git a/ChangeLog b/ChangeLog
index 44cfc4cc..3855d477 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/NEWS b/NEWS
index 04ba292e..b7647c30 100644
--- a/NEWS
+++ b/NEWS
@@ -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:
diff --git a/aclocal.m4 b/aclocal.m4
index 9d70920d..0e2027cd 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -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])
diff --git a/config.in b/config.in
index 5c1a3894..0f5677e9 100644
--- a/config.in
+++ b/config.in
@@ -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
diff --git a/configure b/configure
index 5f5c4c03..b912e408 100755
--- a/configure
+++ b/configure
@@ -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++)
diff --git a/main.cxx b/main.cxx
index 5d0739eb..563e4b01 100644
--- a/main.cxx
+++ b/main.cxx
@@ -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)&REG_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;
diff --git a/session.h b/session.h
index e8100cf5..22575e8d 100644
--- a/session.h
+++ b/session.h
@@ -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();