diff options
63 files changed, 1693 insertions, 3747 deletions
@@ -18,3 +18,9 @@ systemtap.spec testresults stapio stap_merge +CVS +.checkstyle +.cproject +.metadata +.project +.settings @@ -1,19 +1,3 @@ -2008-03-25 Frank Ch. Eigler <fche@elastic.org> - - * stap.1.in: Clarify utility of epilogue type probe aliases. - -2008-03-21 Eugene Teo <eugeneteo@kernel.sg> - - PR 5528 - * tapset/conversions.stp (user_string_n, user_string_n2, - user_string_n_warn, user_string_n_quoted, user_short, user_short_warn, - user_int, user_int_warn, user_long, user_long_warn, user_char, - user_char_warn): New user_* functions. - * stapfuncs.5.in: Documented the new functions. - * testsuite/systemtap.stress/conversions.stp: Test new functions. - * testsuite/buildok/conversions.stp: Test new functions. - * testsuite/buildok/conversions-embedded.stp: Test new functions. - 2008-03-20 Frank Ch. Eigler <fche@elastic.org> PR 5975. diff --git a/Makefile.am b/Makefile.am index 1fc4dbec..a53fdba0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,19 +53,19 @@ endif staprun_SOURCES = runtime/staprun/staprun.c runtime/staprun/staprun_funcs.c\ runtime/staprun/ctl.c runtime/staprun/common.c \ - runtime/staprun/cap.c runtime/staprun/symbols.c + runtime/staprun/cap.c staprun_CPPFLAGS = $(AM_CPPFLAGS) -staprun_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) -staprun_LDADD = @PROCFLAGS@ @cap_LIBS@ -lpthread +staprun_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) -DSINGLE_THREADED +staprun_LDADD = @PROCFLAGS@ @cap_LIBS@ stapio_SOURCES = runtime/staprun/stapio.c \ runtime/staprun/mainloop.c runtime/staprun/common.c \ - runtime/staprun/ctl.c \ + runtime/staprun/ctl.c runtime/staprun/unwind_data.c \ runtime/staprun/relay.c runtime/staprun/relay_old.c stapio_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) -stapio_LDADD = @PROCFLAGS@ -lpthread +stapio_LDADD = @PROCFLAGS@ -ldw -lpthread install-exec-hook: if [ `id -u` -eq 0 ]; then chmod 04111 "$(DESTDIR)$(bindir)/staprun"; fi @@ -127,8 +127,9 @@ dist-hook: dist-add-samples find $(distdir) -name 'stap' -o -name '*.log' -o -name '*.sum' -o -name 'site.exp' | xargs rm -rf install-data-local: -# mkdir -p $(DESTDIR)$(pkgdatadir)/runtime/transport $(DESTDIR)$(pkgdatadir)/tapset (cd $(srcdir)/runtime; for f in *.[ch]; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/$$f; done) + (cd $(srcdir)/runtime/unwind; find . \( -name '*.[ch]' \) -print \ + | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/unwind/$$f; done) (cd $(srcdir)/runtime/transport; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/transport/$$f; done) (cd $(srcdir)/runtime/uprobes; for f in Makefile *.[ch]; \ diff --git a/Makefile.in b/Makefile.in index e82d66a3..9fc103d3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -102,15 +102,15 @@ stap_LINK = $(CXXLD) $(stap_CXXFLAGS) $(CXXFLAGS) $(stap_LDFLAGS) \ $(LDFLAGS) -o $@ am_stapio_OBJECTS = stapio-stapio.$(OBJEXT) stapio-mainloop.$(OBJEXT) \ stapio-common.$(OBJEXT) stapio-ctl.$(OBJEXT) \ - stapio-relay.$(OBJEXT) stapio-relay_old.$(OBJEXT) + stapio-unwind_data.$(OBJEXT) stapio-relay.$(OBJEXT) \ + stapio-relay_old.$(OBJEXT) stapio_OBJECTS = $(am_stapio_OBJECTS) stapio_DEPENDENCIES = stapio_LINK = $(CCLD) $(stapio_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_staprun_OBJECTS = staprun-staprun.$(OBJEXT) \ staprun-staprun_funcs.$(OBJEXT) staprun-ctl.$(OBJEXT) \ - staprun-common.$(OBJEXT) staprun-cap.$(OBJEXT) \ - staprun-symbols.$(OBJEXT) + staprun-common.$(OBJEXT) staprun-cap.$(OBJEXT) staprun_OBJECTS = $(am_staprun_OBJECTS) staprun_DEPENDENCIES = staprun_LINK = $(CCLD) $(staprun_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -286,18 +286,18 @@ CLEANFILES = $(am__append_3) $(pkglibexec_PROGRAMS) @BUILD_ELFUTILS_TRUE@stap_DEPENDENCIES = lib-elfutils/libdw.so staprun_SOURCES = runtime/staprun/staprun.c runtime/staprun/staprun_funcs.c\ runtime/staprun/ctl.c runtime/staprun/common.c \ - runtime/staprun/cap.c runtime/staprun/symbols.c + runtime/staprun/cap.c staprun_CPPFLAGS = $(AM_CPPFLAGS) -staprun_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) -staprun_LDADD = @PROCFLAGS@ @cap_LIBS@ -lpthread +staprun_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) -DSINGLE_THREADED +staprun_LDADD = @PROCFLAGS@ @cap_LIBS@ stapio_SOURCES = runtime/staprun/stapio.c \ runtime/staprun/mainloop.c runtime/staprun/common.c \ - runtime/staprun/ctl.c \ + runtime/staprun/ctl.c runtime/staprun/unwind_data.c \ runtime/staprun/relay.c runtime/staprun/relay_old.c stapio_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) -stapio_LDADD = @PROCFLAGS@ -lpthread +stapio_LDADD = @PROCFLAGS@ -ldw -lpthread loc2c_test_SOURCES = loc2c-test.c loc2c.c loc2c_test_CPPFLAGS = $(stap_CPPFLAGS) loc2c_test_LDFLAGS = $(stap_LDFLAGS) @@ -505,12 +505,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapio-relay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapio-relay_old.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapio-stapio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stapio-unwind_data.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-cap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-ctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-staprun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-staprun_funcs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/staprun-symbols.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -638,6 +638,20 @@ stapio-ctl.obj: runtime/staprun/ctl.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapio_CFLAGS) $(CFLAGS) -c -o stapio-ctl.obj `if test -f 'runtime/staprun/ctl.c'; then $(CYGPATH_W) 'runtime/staprun/ctl.c'; else $(CYGPATH_W) '$(srcdir)/runtime/staprun/ctl.c'; fi` +stapio-unwind_data.o: runtime/staprun/unwind_data.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapio_CFLAGS) $(CFLAGS) -MT stapio-unwind_data.o -MD -MP -MF $(DEPDIR)/stapio-unwind_data.Tpo -c -o stapio-unwind_data.o `test -f 'runtime/staprun/unwind_data.c' || echo '$(srcdir)/'`runtime/staprun/unwind_data.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stapio-unwind_data.Tpo $(DEPDIR)/stapio-unwind_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/staprun/unwind_data.c' object='stapio-unwind_data.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapio_CFLAGS) $(CFLAGS) -c -o stapio-unwind_data.o `test -f 'runtime/staprun/unwind_data.c' || echo '$(srcdir)/'`runtime/staprun/unwind_data.c + +stapio-unwind_data.obj: runtime/staprun/unwind_data.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapio_CFLAGS) $(CFLAGS) -MT stapio-unwind_data.obj -MD -MP -MF $(DEPDIR)/stapio-unwind_data.Tpo -c -o stapio-unwind_data.obj `if test -f 'runtime/staprun/unwind_data.c'; then $(CYGPATH_W) 'runtime/staprun/unwind_data.c'; else $(CYGPATH_W) '$(srcdir)/runtime/staprun/unwind_data.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stapio-unwind_data.Tpo $(DEPDIR)/stapio-unwind_data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/staprun/unwind_data.c' object='stapio-unwind_data.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapio_CFLAGS) $(CFLAGS) -c -o stapio-unwind_data.obj `if test -f 'runtime/staprun/unwind_data.c'; then $(CYGPATH_W) 'runtime/staprun/unwind_data.c'; else $(CYGPATH_W) '$(srcdir)/runtime/staprun/unwind_data.c'; fi` + stapio-relay.o: runtime/staprun/relay.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stapio_CFLAGS) $(CFLAGS) -MT stapio-relay.o -MD -MP -MF $(DEPDIR)/stapio-relay.Tpo -c -o stapio-relay.o `test -f 'runtime/staprun/relay.c' || echo '$(srcdir)/'`runtime/staprun/relay.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stapio-relay.Tpo $(DEPDIR)/stapio-relay.Po @@ -736,20 +750,6 @@ staprun-cap.obj: runtime/staprun/cap.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-cap.obj `if test -f 'runtime/staprun/cap.c'; then $(CYGPATH_W) 'runtime/staprun/cap.c'; else $(CYGPATH_W) '$(srcdir)/runtime/staprun/cap.c'; fi` -staprun-symbols.o: runtime/staprun/symbols.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-symbols.o -MD -MP -MF $(DEPDIR)/staprun-symbols.Tpo -c -o staprun-symbols.o `test -f 'runtime/staprun/symbols.c' || echo '$(srcdir)/'`runtime/staprun/symbols.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/staprun-symbols.Tpo $(DEPDIR)/staprun-symbols.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/staprun/symbols.c' object='staprun-symbols.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-symbols.o `test -f 'runtime/staprun/symbols.c' || echo '$(srcdir)/'`runtime/staprun/symbols.c - -staprun-symbols.obj: runtime/staprun/symbols.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -MT staprun-symbols.obj -MD -MP -MF $(DEPDIR)/staprun-symbols.Tpo -c -o staprun-symbols.obj `if test -f 'runtime/staprun/symbols.c'; then $(CYGPATH_W) 'runtime/staprun/symbols.c'; else $(CYGPATH_W) '$(srcdir)/runtime/staprun/symbols.c'; fi` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/staprun-symbols.Tpo $(DEPDIR)/staprun-symbols.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/staprun/symbols.c' object='staprun-symbols.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(staprun_CPPFLAGS) $(CPPFLAGS) $(staprun_CFLAGS) $(CFLAGS) -c -o staprun-symbols.obj `if test -f 'runtime/staprun/symbols.c'; then $(CYGPATH_W) 'runtime/staprun/symbols.c'; else $(CYGPATH_W) '$(srcdir)/runtime/staprun/symbols.c'; fi` - .cxx.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @@ -1498,8 +1498,9 @@ dist-hook: dist-add-samples find $(distdir) -name 'stap' -o -name '*.log' -o -name '*.sum' -o -name 'site.exp' | xargs rm -rf install-data-local: -# mkdir -p $(DESTDIR)$(pkgdatadir)/runtime/transport $(DESTDIR)$(pkgdatadir)/tapset (cd $(srcdir)/runtime; for f in *.[ch]; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/$$f; done) + (cd $(srcdir)/runtime/unwind; find . \( -name '*.[ch]' \) -print \ + | while read f; do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/unwind/$$f; done) (cd $(srcdir)/runtime/transport; for f in *.[ch]; \ do $(INSTALL_DATA) -D $$f $(DESTDIR)$(pkgdatadir)/runtime/transport/$$f; done) (cd $(srcdir)/runtime/uprobes; for f in Makefile *.[ch]; \ diff --git a/doc/ChangeLog b/doc/ChangeLog index e652078d..902e1d1e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,7 +1,3 @@ -2008-03-25 Frank Ch. Eigler <fche@elastic.org> - - * langref.tex: Clarify utility of epilogue-type probe aliases. - 2008-03-04 David Smith <dsmith@redhat.com> * tutorial.tex: Made minor changes to remove warnings. diff --git a/doc/langref.tex b/doc/langref.tex index 973769d4..5b91d01d 100644 --- a/doc/langref.tex +++ b/doc/langref.tex @@ -230,7 +230,7 @@ This prints: \end{verbatim} \end{vindent} Any larger number input to the function may exceed the MAXACTION or MAXNESTING -limits, which will be caught at run time and result in an error. For more +limits, which will be caught by the parser and result in an error. For more about limits see Section~\ref{sub:SystemTap-safety}. \newpage{} \subsection{The stap command} @@ -436,10 +436,8 @@ probe syscall.read = kernel.function("sys_read") { \index{epilogue-style aliases} \index{+=} The statement block that follows an alias definition is implicitly added -as an epilogue to any probe that refers to the alias. It is not useful -to define new variable there (since no subsequent code will see it), but -rather the code can take action based upon variables left set by the -prologue or by the user code. The following is an example: +as an epilogue to any probe that refers to the alias. The following is an +example: \begin{vindent} \begin{verbatim} @@ -447,15 +445,15 @@ prologue or by the user code. The following is an example: # epilogue. # probe syscall.read += kernel.function("sys_read") { - if (traceme) println ("tracing me") + fildes = $fd } \end{verbatim} \end{vindent} \subsubsection{Probe alias usage} -A probe alias is used the same way as any built-in probe type, by -naming it: +Another probe definition may use a previously defined alias. The following +is an example. \begin{vindent} \begin{verbatim} @@ -1029,6 +1027,12 @@ type conversions between strings and numbers. Inconsistent type-related use of identifiers signals an error. +\subsubsection{Numbers} +\index{numbers} +Numbers are 64-bit signed integers. The parser will also accept (and wrap +around) values above positive $2^{63}$. + + \subsubsection{Literals} \index{literals} Literals are either strings or integers. Literals can be expressed as decimal, @@ -1037,10 +1041,10 @@ octal, or hexadecimal, using C notation. Type suffixes (e.g., \emph{L} or \subsubsection{Integers\label{sub:Integers}} -\index{integers} \index{numbers} +\index{integers} Integers are decimal, hexadecimal, or octal, and use the same notation as in C. Integers are 64-bit signed quantities, although the parser also accepts -(and wraps around) values above positive $2^{63}$ but below $2^{64}$. +(and wraps around) values above positive $2^{63}$. \subsubsection{Strings\label{sub:Strings}} diff --git a/runtime/.gitignore b/runtime/.gitignore new file mode 100644 index 00000000..ceddd64c --- /dev/null +++ b/runtime/.gitignore @@ -0,0 +1 @@ +!staprun diff --git a/runtime/Makefile b/runtime/Makefile deleted file mode 100644 index 22d25ff9..00000000 --- a/runtime/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for SystemTap runtime and example probes -# - -all: - make -w -C stpd - cd probes; ./build - -relayfs: - make -w -C relayfs - -clean: - make -w -C relayfs clean - make -w -C stpd clean - cd probes; ./build clean diff --git a/runtime/bench2/Makefile b/runtime/bench2/Makefile deleted file mode 100644 index ffb2991a..00000000 --- a/runtime/bench2/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: itest - -itest: itest.c - gcc -D_GNU_SOURCE -Wall -Wextra -Wstrict-prototypes -Werror -O3 -o itest itest.c -lpthread - -clean: - /bin/rm -f itest diff --git a/runtime/debug.h b/runtime/debug.h index 8f877ede..9b2fe5c5 100644 --- a/runtime/debug.h +++ b/runtime/debug.h @@ -14,6 +14,8 @@ * _dbug() writes to systemtap stderr. * errk() writes to the system log. */ +int _stp_transport_state = 0; + #define _dbug(args...) _stp_dbug(__FUNCTION__, __LINE__, args) #define errk(args...) do { \ @@ -21,46 +23,42 @@ printk(args); \ } while (0) -#ifdef DEBUG_TRANSPORT -#undef DEBUG_TRANSPORT -#define DEBUG_TRANSPORT 1 -#else -#define DEBUG_TRANSPORT 0 -#endif +/* + * To use these, enable them from the command line when compiling. + * For example, "stap -DDEBUG_UNWIND=3" + * will activate dbug_unwind() and print messages with level <= 3. + */ -#ifdef DEBUG_UNWIND -#undef DEBUG_UNWIND -#define DEBUG_UNWIND 2 -#else -#define DEBUG_UNWIND 0 -#endif +/* Note: DEBUG_MEM is implemented in alloc.c */ -#ifdef DEBUG_SYMBOLS -#undef DEBUG_SYMBOLS -#define DEBUG_SYMBOLS 4 +#ifdef DEBUG_TRANS /* transport */ +/* Note: transport is debugged using printk() */ +#define dbug_trans(level, args...) do { \ + if ((level) <= DEBUG_TRANS) { \ + printk("%s:%d ",__FUNCTION__, __LINE__); \ + printk(args); \ + } \ + } while (0) #else -#define DEBUG_SYMBOLS 0 +#define dbug_trans(level, args...) ; #endif -#define DEBUG_TYPE (DEBUG_TRANSPORT|DEBUG_UNWIND|DEBUG_SYMBOLS) - -#if DEBUG_TYPE > 0 - -#define dbug(type, args...) do { \ - if ((type) & DEBUG_TYPE) \ +#ifdef DEBUG_UNWIND /* stack unwinder */ +#define dbug_unwind(level, args...) do { \ + if ((level) <= DEBUG_UNWIND) \ _stp_dbug(__FUNCTION__, __LINE__, args); \ } while (0) +#else +#define dbug_unwind(level, args...) ; +#endif -#define kbug(type, args...) do { \ - if ((type) & DEBUG_TYPE) { \ - printk("%s:%d ",__FUNCTION__, __LINE__); \ - printk(args); \ - } \ +#ifdef DEBUG_SYMBOLS +#define dbug_sym(level, args...) do { \ + if ((level) <= DEBUG_SYMBOLS) \ + _stp_dbug(__FUNCTION__, __LINE__, args); \ } while (0) - #else -#define dbug(type, args...) ; -#define kbug(type, args...) ; -#endif /* DEBUG_TYPE > 0 */ +#define dbug_sym(level, args...) ; +#endif #endif /* _STP_DEBUG_H_ */ diff --git a/runtime/lket/b2a/.cvsignore b/runtime/lket/b2a/.cvsignore deleted file mode 100644 index e289e6f1..00000000 --- a/runtime/lket/b2a/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile lket-b2a .deps diff --git a/runtime/lket/b2a/Makefile.am b/runtime/lket/b2a/Makefile.am deleted file mode 100644 index 01472f6a..00000000 --- a/runtime/lket/b2a/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -bin_PROGRAMS = lket-b2a -lket_b2a_SOURCES = lket_b2a.c -lket_b2a_DEPENDENCIES = lket_b2a.h -lket_b2a_LDFLAGS = `pkg-config --libs glib-2.0` -lket_b2a_CFLAGS = -O2 -D_GNU_SOURCE -Wall `pkg-config --cflags glib-2.0` - -if HAS_MYSQL -lket_b2a_CFLAGS += -DHAS_MYSQL -if HAS_MYSQL_CONFIG -lket_b2a_LDFLAGS += `mysql_config --libs` -lket_b2a_CFLAGS += `mysql_config --cflags` -else -lket_b2a_CFLAGS += -I/usr/include/mysql -g -pipe -fsigned-char -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -lket_b2a_LDFLAGS += -L/usr/lib/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto -endif -endif - - diff --git a/runtime/lket/b2a/Makefile.in b/runtime/lket/b2a/Makefile.in deleted file mode 100644 index e262682a..00000000 --- a/runtime/lket/b2a/Makefile.in +++ /dev/null @@ -1,449 +0,0 @@ -# Makefile.in generated by automake 1.10 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006 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. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -bin_PROGRAMS = lket-b2a$(EXEEXT) -@HAS_MYSQL_TRUE@am__append_1 = -DHAS_MYSQL -@HAS_MYSQL_CONFIG_TRUE@@HAS_MYSQL_TRUE@am__append_2 = `mysql_config --libs` -@HAS_MYSQL_CONFIG_TRUE@@HAS_MYSQL_TRUE@am__append_3 = `mysql_config --cflags` -@HAS_MYSQL_CONFIG_FALSE@@HAS_MYSQL_TRUE@am__append_4 = -I/usr/include/mysql -g -pipe -fsigned-char -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -@HAS_MYSQL_CONFIG_FALSE@@HAS_MYSQL_TRUE@am__append_5 = -L/usr/lib/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto -subdir = runtime/lket/b2a -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -am__installdirs = "$(DESTDIR)$(bindir)" -binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) -PROGRAMS = $(bin_PROGRAMS) -am_lket_b2a_OBJECTS = lket_b2a-lket_b2a.$(OBJEXT) -lket_b2a_OBJECTS = $(am_lket_b2a_OBJECTS) -lket_b2a_LDADD = $(LDADD) -lket_b2a_LINK = $(CCLD) $(lket_b2a_CFLAGS) $(CFLAGS) \ - $(lket_b2a_LDFLAGS) $(LDFLAGS) -o $@ -DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@ -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(lket_b2a_SOURCES) -DIST_SOURCES = $(lket_b2a_SOURCES) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATE = @DATE@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MYSQL_CONFIG = @MYSQL_CONFIG@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PROCFLAGS = @PROCFLAGS@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -U = @U@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -cap_LIBS = @cap_LIBS@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -elfutils_abs_srcdir = @elfutils_abs_srcdir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sqlite3_LIBS = @sqlite3_LIBS@ -srcdir = @srcdir@ -stap_LIBS = @stap_LIBS@ -subdirs = @subdirs@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -lket_b2a_SOURCES = lket_b2a.c -lket_b2a_DEPENDENCIES = lket_b2a.h -lket_b2a_LDFLAGS = `pkg-config --libs glib-2.0` $(am__append_2) \ - $(am__append_5) -lket_b2a_CFLAGS = -O2 -D_GNU_SOURCE -Wall `pkg-config --cflags \ - glib-2.0` $(am__append_1) $(am__append_3) $(am__append_4) -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu runtime/lket/b2a/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu runtime/lket/b2a/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-binPROGRAMS: $(bin_PROGRAMS) - @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" - @list='$(bin_PROGRAMS)'; for p in $$list; do \ - p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ - if test -f $$p \ - ; then \ - f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ - $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ - else :; fi; \ - done - -uninstall-binPROGRAMS: - @$(NORMAL_UNINSTALL) - @list='$(bin_PROGRAMS)'; for p in $$list; do \ - f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ - rm -f "$(DESTDIR)$(bindir)/$$f"; \ - done - -clean-binPROGRAMS: - -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) -lket-b2a$(EXEEXT): $(lket_b2a_OBJECTS) $(lket_b2a_DEPENDENCIES) - @rm -f lket-b2a$(EXEEXT) - $(lket_b2a_LINK) $(lket_b2a_OBJECTS) $(lket_b2a_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lket_b2a-lket_b2a.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` - -lket_b2a-lket_b2a.o: lket_b2a.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lket_b2a_CFLAGS) $(CFLAGS) -MT lket_b2a-lket_b2a.o -MD -MP -MF $(DEPDIR)/lket_b2a-lket_b2a.Tpo -c -o lket_b2a-lket_b2a.o `test -f 'lket_b2a.c' || echo '$(srcdir)/'`lket_b2a.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/lket_b2a-lket_b2a.Tpo $(DEPDIR)/lket_b2a-lket_b2a.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lket_b2a.c' object='lket_b2a-lket_b2a.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lket_b2a_CFLAGS) $(CFLAGS) -c -o lket_b2a-lket_b2a.o `test -f 'lket_b2a.c' || echo '$(srcdir)/'`lket_b2a.c - -lket_b2a-lket_b2a.obj: lket_b2a.c -@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lket_b2a_CFLAGS) $(CFLAGS) -MT lket_b2a-lket_b2a.obj -MD -MP -MF $(DEPDIR)/lket_b2a-lket_b2a.Tpo -c -o lket_b2a-lket_b2a.obj `if test -f 'lket_b2a.c'; then $(CYGPATH_W) 'lket_b2a.c'; else $(CYGPATH_W) '$(srcdir)/lket_b2a.c'; fi` -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/lket_b2a-lket_b2a.Tpo $(DEPDIR)/lket_b2a-lket_b2a.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lket_b2a.c' object='lket_b2a-lket_b2a.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lket_b2a_CFLAGS) $(CFLAGS) -c -o lket_b2a-lket_b2a.obj `if test -f 'lket_b2a.c'; then $(CYGPATH_W) 'lket_b2a.c'; else $(CYGPATH_W) '$(srcdir)/lket_b2a.c'; fi` - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(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; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(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; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(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; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) -installdirs: - for dir in "$(DESTDIR)$(bindir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-binPROGRAMS clean-generic mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-exec-am: install-binPROGRAMS - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-binPROGRAMS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ - clean-generic ctags distclean distclean-compile \ - distclean-generic distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-binPROGRAMS \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-binPROGRAMS - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/runtime/lket/b2a/lket_b2a.c b/runtime/lket/b2a/lket_b2a.c deleted file mode 100644 index ab1bb299..00000000 --- a/runtime/lket/b2a/lket_b2a.c +++ /dev/null @@ -1,1030 +0,0 @@ -// Copyright (C) 2005, 2006 IBM Corp. -// Copyright (C) 2006 Red Hat Inc. -// Copyright (C) 2007 Bull S.A.S -// -// This file is part of systemtap, and is free software. You can -// redistribute it and/or modify it under the terms of the GNU General -// Public License (GPL); either version 2, or (at your option) any -// later version. - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <ctype.h> -#include <assert.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include "lket_b2a.h" - -/* A flag indicate whether to store the trace - data into local file/MySQL database */ -int into_file, into_db; -int name_flag=1, id_flag=0, appname_flag=1; -#ifdef HAS_MYSQL - -#define SQLSIZE 1024*1024 -int sql_count; -#define INSERT_THRESHOLD 100 -char sql[4096]; -char sqlStatement[SQLSIZE]; -char sql_col[1024]; -char sql_val[2048]; - -MYSQL mysql; -#endif - -/* A FILE handle points to a local file used to - store the trace data */ -FILE *outfp; - -#define TIMING_GETCYCLES 0x01 -#define TIMING_GETTIMEOFDAY 0x02 -#define TIMING_SCHEDCLOCK 0x03 - -typedef struct _cpufreq_info { - long timebase; - long long last_cycles; - long long last_time; -} cpufreq_info; - -#define MAX_CPUS 256 -cpufreq_info cpufreq[MAX_CPUS]; - -static long timing_method = TIMING_GETTIMEOFDAY; - -static long long start_timestamp; - -GTree *appNameTree; - -/* event table */ -event_desc *events_des[MAX_EVT_TYPES][MAX_GRPID][MAX_HOOKID]; - -#define b2a_error(fmt, args...) do { fprintf(stderr, "Error %d@%s: "fmt, __LINE__, __func__, ## args);\ - exit(-1); } while(0) - -void usage() -{ -printf("Usage:\n\ - lket-b2a Options INFILE1 [INFILE2...]\n\ - Options:\n\ - -f dump the trace data into a local file named \"lket.out\"\n\ - -n name_flag. name_flag set to 0 means not printing the event\n\ - description string and 1 means printing. Only valid with -f\n\ - option. name_flag is set to 1 by default.\n\ - -i id_flag. id_flag set to 0 means not printing event groupid and\n\ - hookid and 1 means printing. Only valid with -f option. id_flag\n\ - is set to 0 by default.\n\ - -a appname_flag. appname_flag set to 0 means not printing process\n\ - name and 1 means printing. Only valid with -f option. appname_flag\n\ - is set to 1 by default.\n\ - -m dump the trace data into MySQL\n\ - Example:\n\ - lket-b2a -f -a 1 -i 1 -n 0 stpd_cpu*\n\ - lket-b2a -m stpd_cpu*\n"); -} - -int main(int argc, char *argv[]) -{ - lket_pkt_header *hdrs = NULL; - FILE **infps = NULL; - char outfilename[MAX_STRINGLEN]={0}; - int i, j, total_infiles = 0; - long long min; - int retvalue = 0; - - char database[18]; - time_t timer; - struct tm *tm; - - time(&timer); - tm = localtime(&timer); - strftime(database, 18, "DB%Y%m%d%H%M%S", tm); - - while (1) { - int c = getopt(argc, argv, "mfi:n:a:"); - if (c < 0) // no more options - break; - switch (c) { - case 'm': - into_db = 1; - break; - case 'f': - into_file = 1; - break; - case 'n': - name_flag = atoi(optarg); - if(name_flag!=0 && name_flag!=1) { - fprintf(stderr, "you must specify 0 or 1 for -n option\n"); - usage(); - exit(-1); - } - break; - case 'i': - id_flag = atoi(optarg); - if(id_flag!=0 && id_flag!=1) { - fprintf(stderr, "you must specify 0 or 1 for -i option\n"); - usage(); - exit(-1); - } - break; - case 'a': - appname_flag = atoi(optarg); - if(appname_flag!=0 && appname_flag!=1) { - fprintf(stderr, "you must specify 0 or 1 for -a option\n"); - usage(); - exit(-1); - } - break; - - default: - printf("Error in options\n"); - usage(); - exit(-1); - break; - } - } - -#ifndef HAS_MYSQL - if(into_db) { - b2a_error("-m option is not supported since lket-b2a is not compiled with mysql support\n"); - } -#endif - if(into_file==0 && into_db==0) { -#ifdef HAS_MYSQL - fprintf(stderr, "At least one of -m/-f option should be specified\n"); -#else - fprintf(stderr, "-f option must be specified\n"); -#endif - usage(); - exit(-1); - } - - total_infiles = argc - optind; - - // open the input files and the output file - infps = (FILE **)malloc(total_infiles * sizeof(FILE *)); - if(!infps) { - b2a_error("Unable to malloc infps\n"); - } - - memset(infps, 0, total_infiles * sizeof(FILE *)); - for(i=0; i < total_infiles; i++) { - infps[i] = fopen(argv[optind++], "r"); - if(infps[i] == NULL) { - printf("Unable to open %s\n", argv[optind-1]); - retvalue = -1; - goto failed; - } - } - - if(into_file) { - if(strnlen(outfilename, MAX_STRINGLEN) == 0) - strncpy(outfilename, DEFAULT_OUTFILE_NAME, MAX_STRINGLEN); - - outfp = fopen(outfilename, "w"); - if(outfp == NULL) { - fprintf(stderr,"Unable to create %s\n", outfilename); - retvalue = -1; - goto failed; - } - } - /* create the search tree */ - appNameTree = g_tree_new_full(compareFunc, NULL, NULL, destroyTreeData); - -#ifdef HAS_MYSQL - if(into_db) { - if(!mysql_init(&mysql)) { - b2a_error("Failed to Init MySQL: Error: %s\n", - mysql_error(&mysql)); - } - - if(!mysql_real_connect(&mysql, NULL, NULL, NULL, NULL, 0, NULL, - CLIENT_MULTI_STATEMENTS)) { - b2a_error("Failed to connect to database: Error: %s\n", - mysql_error(&mysql)); - } - - snprintf(sql, 64,"create database %s", database); - - if(mysql_query(&mysql, sql)) { - b2a_error("Failed create database %s, Error: %s\n", - database, mysql_error(&mysql)); - } - - if(!mysql_real_connect(&mysql, NULL, NULL, NULL, database, 0, NULL, - CLIENT_MULTI_STATEMENTS)) { - b2a_error("Failed to connect to database %s: Error: %s\n", - database, mysql_error(&mysql)); - } - } -#endif - - // find the lket header - find_init_header(infps, total_infiles); - - // allocate packet headers array - hdrs = malloc(total_infiles * sizeof(lket_pkt_header)); - if(!hdrs) { - printf("Unable to malloc hdrs \n"); - retvalue = -1; - goto failed; - } - memset(hdrs, 0, total_infiles * sizeof(lket_pkt_header)); - - // initialize packet headers array - start_timestamp = 0; - j = 0; - for(i=0; i < total_infiles; i++) { - get_pkt_header(infps[i], &hdrs[i]); - if( (hdrs[i].microsecond < start_timestamp && hdrs[i].microsecond >0) - || (start_timestamp == 0)) { - start_timestamp = hdrs[i].microsecond; - j = i; - } - } - - // initialize the start cycles - if(timing_method == TIMING_GETCYCLES) { - for(i=0; i<MAX_CPUS; i++) { - cpufreq[i].last_cycles = start_timestamp; - cpufreq[i].last_time = 0; - } - } - - // main loop of parsing & merging - min = start_timestamp; - do { - // j is the next - if(min) { - if(HDR_GroupID(&hdrs[j])==_GROUP_REGEVT) { - if(HDR_HookID(&hdrs[j]) == _HOOKID_REGEVTDESC) - register_evt_desc(infps[j],hdrs[j].sys_size); - else - register_events(HDR_HookID(&hdrs[j]), infps[j], - hdrs[j].sys_size); - } else { - - if(HDR_GroupID(&hdrs[j])==_GROUP_PROCESS && - (HDR_HookID(&hdrs[j])==_HOOKID_PROCESS_SNAPSHOT - || HDR_HookID(&hdrs[j])==_HOOKID_PROCESS_EXECVE - || HDR_HookID(&hdrs[j])==_HOOKID_PROCESS_FORK)) - { - register_appname(j, infps[j], &hdrs[j]); - } - - if(HDR_GroupID(&hdrs[j])==_GROUP_CPUFREQ - && HDR_HookID(&hdrs[j])==_HOOKID_SWITCH_CPUFREQ - && timing_method == TIMING_GETCYCLES) - { - int64_t new_timebase; - fread(&new_timebase, sizeof(new_timebase), 1, infps[j]); - - cpufreq[HDR_CpuID(&hdrs[j])].last_time += - (hdrs[j].microsecond - - cpufreq[HDR_CpuID(&hdrs[j])].last_cycles) - / cpufreq[HDR_CpuID(&hdrs[j])].timebase; - cpufreq[j].last_cycles = hdrs[j].microsecond; - cpufreq[HDR_CpuID(&hdrs[j])].timebase = new_timebase; - - fseek(infps[j], -sizeof(new_timebase), SEEK_CUR); - } - - dump_data(hdrs[j], infps[j]); - } - // update hdr[j] -#ifdef DEBUG_OUTPUT - fprintf(stderr, "File %d, Offset: %ld\n", j, ftell(infps[j])); -#endif - get_pkt_header(infps[j], &hdrs[j]); - } - // recalculate the smallest timestamp - min = hdrs[0].microsecond; - j = 0; - for(i=1; i < total_infiles ; i++) { - if((min == 0) || - (hdrs[i].microsecond < min && hdrs[i].microsecond > 0)) { - min = hdrs[i].microsecond; - j = i; - } - } - } while(min != 0); - -failed: - // close all opened files - for(i=0; i < total_infiles; i++) - if(infps[i]) - fclose(infps[i]); - if(outfp) - fclose(outfp); - - // free all allocated memory space - if(infps) - free(infps); - if(hdrs) - free(hdrs); - - for(i=1; i<MAX_GRPID; i++) - for(j=1; j<MAX_HOOKID; j++) { - if(events_des[_HOOKID_REGSYSEVT][i][j] != NULL) { -#ifdef HAS_MYSQL - if(events_des[_HOOKID_REGSYSEVT][i][j]->flag == 0 && into_db) { - snprintf(sql, 256, "drop table %d_%d",i,j); - if(mysql_query(&mysql,sql)) { - b2a_error("Failed to exec sql: %s, Error: %s\n", - sql, mysql_error(&mysql)); - } - snprintf(sql, 256, "delete from table_desc where table_name='%d_%d'",i,j); - if(mysql_query(&mysql,sql)) { - b2a_error("Failed to exec sql: %s, Error: %s\n", - sql, mysql_error(&mysql)); - } - } - /* destroy entrytime tree */ - if(events_des[_HOOKID_REGSYSEVT][i][j]->entrytime) - g_tree_destroy(events_des[_HOOKID_REGSYSEVT][i][j]->entrytime); -#endif - } - } - -#ifdef HAS_MYSQL - if(into_db) { - mysql_close(&mysql); - } -#endif - if (appNameTree) - g_tree_destroy(appNameTree); - - return retvalue; -} - -/* register newly found process name for addevent.process.snapshot - and addevent.process.execve */ -void register_appname(int i, FILE *fp, lket_pkt_header *phdr) -{ - int pid, tid, ppid; - char *appname=NULL; - int count; - int len; - int c; - int location; - len=0; - count=0; - -#ifdef HAS_MYSQL - static int flag = 0; - - if(into_db) { - if(flag==0) { - if(mysql_query(&mysql, "create table appNameMap ( pid INT, pname varchar(20))")) { - b2a_error("Failed to create appNameMap table, Error: %s\n", - mysql_error(&mysql)); - } - } - flag=1; - } -#endif - appname = (char *)malloc(512); - location = ftell(fp); - - if(HDR_HookID(phdr) == _HOOKID_PROCESS_SNAPSHOT ) { /* process_snapshot */ - fread(&tid, 1, 4, fp); /* read tid */ - fread(&pid, 1, 4, fp); /* read pid */ - fread(&ppid, 1, 4, fp); /* read ppid */ - c = fgetc_unlocked(fp); - len+=13; - while (c && len < 1024) { - appname[count++] = (char)c; - c = fgetc_unlocked(fp); - ++len; - } - appname[count]='\0'; - } else if (HDR_HookID(phdr) == _HOOKID_PROCESS_EXECVE) { /* process.execve */ - fread(&tid, 1, 4, fp); /* read tid */ - fread(&pid, 1, 4, fp); /* read pid */ - fread(&ppid, 1, 4, fp); /* read ppid */ - c = fgetc_unlocked(fp); - len+=5; - while (c && len < 1024) { - appname[count++] = (char)c; - c = fgetc_unlocked(fp); - ++len; - } - appname[count]='\0'; - } else if (HDR_HookID(phdr) == _HOOKID_PROCESS_FORK) { - fread(&tid, 1, 4, fp); /* read tid */ - fread(&pid, 1, 4, fp); /* read pid */ - fread(&ppid, 1, 4, fp); /* read ppid */ - - char *appname_ptr; - appname_ptr = (char *)(g_tree_lookup(appNameTree,(gconstpointer)((long)ppid))); - if(appname_ptr == NULL) - strncpy(appname, "N/A", 4); - else - strncpy(appname, appname_ptr, 256); - - } else { - free(appname); - return; - } - fseek(fp, location, SEEK_SET); -#ifdef HAS_MYSQL - if(into_db) { - snprintf(sql, 256,"insert into appNameMap values ( %d, \"%s\")", pid, appname); - if(mysql_query(&mysql,sql)) { - b2a_error("Failed to exec SQL: %s, Error: %s\n", - sql, mysql_error(&mysql)); - } - } -#endif - g_tree_insert(appNameTree, (gpointer)((long)pid), (gpointer)appname); -} - - -gint compareFunc(gconstpointer a, gconstpointer b, gpointer user_data) -{ - if((long)(a) > (long)(b)) return 1; - else if ((long)(a) < (long)(b)) return -1; - else return 0; -} - -void destroyTreeData(gpointer data) -{ - free(data); -} - -/* - * search the LKET init header in a set of input files, - * and the header structure is defined in tapsets/lket_trace.stp - */ -void find_init_header(FILE **infps, const int total_infiles) -{ - int i, j, k; - int32_t magic; - percpu_header pcpu; - - /* information from lket_init_header */ - int16_t inithdr_len; - int8_t ver_major; - int8_t ver_minor; - int8_t big_endian; - int8_t timing_field; - int8_t bits_width; - int32_t init_timebase; - char timing_methods_str[128]; - - if(total_infiles <= 0 ) - b2a_error("total_infiles <= 0\n"); - j = total_infiles; - for(i=0; i<total_infiles; i++) { - /* skip percpu header */ - if(fread(&pcpu, 1, sizeof(pcpu), infps[i]) < sizeof(pcpu)) - continue; - if(fread(&magic, 1, sizeof(magic), infps[i]) < sizeof(magic)) - continue; - if(magic == (int32_t)LKET_MAGIC) { - //found - j = i; - if(into_file) - fprintf(outfp, "LKET Magic:\t0x%X\n", magic); - //read other content of lket_int_header - if(fread(&inithdr_len, 1, sizeof(inithdr_len), infps[i]) - < sizeof(inithdr_len)) - break; - if(into_file) - fprintf(outfp, "InitHdrLen:\t%d\n", inithdr_len); - if(fread(&ver_major, 1, sizeof(ver_major), infps[i]) < sizeof(ver_major)) - break; - if(into_file) - fprintf(outfp, "Version Major:\t%d\n", ver_major); - if(fread(&ver_minor, 1, sizeof(ver_minor), infps[i]) < sizeof(ver_minor)) - break; - if(into_file) - fprintf(outfp, "Version Minor:\t%d\n", ver_minor); - if(fread(&big_endian, 1, sizeof(big_endian), infps[i]) < sizeof(big_endian)) - break; - if(into_file) - fprintf(outfp, "Big endian:\t%s\n", big_endian ? "YES":"NO"); - if(fread(&timing_field, 1, sizeof(timing_field), infps[i]) - < sizeof(timing_field)) - break; - timing_method = timing_field; - if(into_file) - fprintf(outfp, "Timing method:\t"); - switch(timing_method) { - case TIMING_GETCYCLES: - snprintf(timing_methods_str, 128, "get_cycles"); - if(into_file) - fprintf(outfp, "get_cycles()\n"); - break; - case TIMING_GETTIMEOFDAY: - snprintf(timing_methods_str, 128,"do_gettimeofday"); - if(into_file) - fprintf(outfp, "do_gettimeofday()\n"); - break; - case TIMING_SCHEDCLOCK: - snprintf(timing_methods_str, 128, "sched_clock"); - if(into_file) - fprintf(outfp, "sched_clock()\n"); - break; - default: - snprintf(timing_methods_str,128, - "Unsupported timing method"); - if(into_file) - fprintf(outfp, "Unsupported timging method\n"); - } - if(fread(&bits_width, 1, sizeof(bits_width), infps[i]) < sizeof(bits_width)) - break; - if(into_file) - fprintf(outfp, "Bits width:\t%d\n", bits_width); - if(fread(&init_timebase, 1, sizeof(init_timebase), infps[i]) - < sizeof(init_timebase)) - break; - if(into_file) - fprintf(outfp, - "Initial CPU timebase:\t%d (cycles per microsecond)\n", - init_timebase); - if(timing_method == TIMING_GETCYCLES) { - for(k = 0; k < MAX_CPUS; k++) - cpufreq[k].timebase = init_timebase; - } - break; - } - } - -#ifdef HAS_MYSQL - if(into_db) { - if(mysql_query(&mysql, "create table trace_header ( Major_Ver TINYINT, Minor_Ver TINYINT, Big_Endian TINYINT, Timing_Method varchar(20), Bits_Width TINYINT)" )) { - b2a_error("Failed to create trace_header table, Error: %s\n", - mysql_error(&mysql)); - } - snprintf(sql, 256, "insert into trace_header value ( %d, %d, %d, \"%s\", %d )", - ver_major, ver_minor, big_endian, timing_methods_str, bits_width); - - if(mysql_query(&mysql, sql)) { - b2a_error("Failed exec SQL %d: \n %s \n, Error: %s\n", - __LINE__, sql, mysql_error(&mysql)); - } - } -#endif - for(i=0; i<total_infiles && i!=j; i++) - fseek(infps[i], 0LL, SEEK_SET); - return; -} - -/* - * read the lket_pkt_header structure at the begining of the input file - */ -int get_pkt_header(FILE *fp, lket_pkt_header *phdr) -{ - percpu_header pcpu; - size_t size; - if(feof(fp)) return 0; - - if((size = fread(&pcpu, 1, sizeof(pcpu), fp)) < sizeof(pcpu)) { - if (feof(fp)) { - bzero(phdr, sizeof(lket_pkt_header)); - return 0; - } else - b2a_error("fread read %u bytes than expected %u, feof:%d\n", - (unsigned) size, (unsigned) sizeof(pcpu), - feof(fp)); - } - - if((size = fread(phdr, 1, sizeof(lket_pkt_header), fp)) < sizeof(lket_pkt_header)) { - if(feof(fp)) { - bzero(phdr, sizeof(lket_pkt_header)); - return 0; - } else - b2a_error("fread read %u bytes than expected %u, feof:%d\n", (unsigned) size, (unsigned) sizeof(lket_pkt_header), feof(fp)); - } - - phdr->sys_size -= sizeof(lket_pkt_header)-sizeof(phdr->total_size)-sizeof(phdr->sys_size); - phdr->total_size -= sizeof(lket_pkt_header)-sizeof(phdr->total_size)-sizeof(phdr->sys_size); - return 0; -} - -void print_pkt_header(lket_pkt_header *phdr) -{ - long long usecs; - int sec, usec; - int grpid, hookid, pid, tid, ppid; - - if(!phdr) - b2a_error("phdr is NULL\n"); - - if(timing_method == TIMING_GETCYCLES) - usecs = (phdr->microsecond - cpufreq[HDR_CpuID(phdr)].last_cycles) - / cpufreq[HDR_CpuID(phdr)].timebase + cpufreq[HDR_CpuID(phdr)].last_time; - else if(timing_method == TIMING_SCHEDCLOCK) - usecs = (phdr->microsecond - start_timestamp) / 1000; - else - usecs = phdr->microsecond - start_timestamp; - - sec = usecs/1000000; - usec = usecs%1000000; - - grpid = HDR_GroupID(phdr); - hookid = HDR_HookID(phdr); - pid = HDR_PID(phdr); - tid = HDR_TID(phdr); - ppid = HDR_PPID(phdr); - - if(into_file) { - fprintf(outfp, "\n%d.%d CPU:%d TID:%d, PID:%d, PPID:%d, ", sec, usec, - HDR_CpuID(phdr), tid, pid, ppid); - if(appname_flag==1) { - char *appname_ptr; - appname_ptr = (char *)(g_tree_lookup(appNameTree,(gconstpointer)((long)pid))); - if(appname_ptr == NULL) - fprintf(outfp, "APPNAME:N/A "); - else - fprintf(outfp, "APPNAME:%s ", appname_ptr); - } - if(name_flag==1) - fprintf(outfp, "EVT_NAME:%s ", events_des[_HOOKID_REGSYSEVT][grpid][hookid]->description); - if(id_flag==1) - fprintf(outfp, "HOOKGRP:%d HOOKID:%d ", grpid, hookid); - } - -#ifdef HAS_MYSQL - if(into_db) { - if(!(hookid%2)) { // return type event - long long *entrytime; - long long entryusecs; - entrytime = g_tree_lookup(events_des[_HOOKID_REGSYSEVT][grpid][hookid-1]->entrytime, - (gconstpointer)((long)tid)); - if(entrytime==NULL) // key not found - entryusecs = 0; - else - entryusecs = *entrytime; - snprintf(sql_col, 128, "groupid, hookid, usec, thread_id, process_id, parentprocess_id, \ - cpu_id, entry_usec,"); - snprintf(sql_val, 256, "%d, %d, %lld, %d, %d, %d, %d, %lld,", grpid, - hookid, usecs, tid, pid, ppid, HDR_CpuID(phdr), - entryusecs); - } else { - snprintf(sql_col, 128, "groupid, hookid, usec, thread_id, process_id, parentprocess_id, cpu_id,"); - snprintf(sql_val, 256, "%d, %d, %lld, %d, %d, %d, %d, ", grpid, - hookid, usecs, tid, pid, ppid, HDR_CpuID(phdr)); - } - if(hookid%2) { - char *entrytime = malloc(sizeof(long long)); - *((long long *)entrytime) = usecs; - g_tree_insert(events_des[_HOOKID_REGSYSEVT][grpid][hookid]->entrytime, - (gpointer)((long)tid), (gpointer)entrytime); - } - } -#endif - -} - -#ifdef HAS_MYSQL -char *get_sqltype(char *fmt) -{ - if(strncmp(fmt, "INT8", 4) == 0) - return "TINYINT"; - if(strncmp(fmt, "INT16", 5) == 0) - return "SMALLINT"; - if(strncmp(fmt, "INT32", 5) == 0) - return "INT"; - if(strncmp(fmt, "INT64", 5) == 0) - return "BIGINT"; - if(strncmp(fmt, "STRING", 6) == 0) - return "VARCHAR(20)"; - return ""; -} -#endif - -void register_evt_desc(FILE *infp, size_t size) -{ -#ifdef HAS_MYSQL - static int has_table = 0; -#endif - int grpid, hookid; - int len = 0; - char *evt_body; - evt_body = malloc(size); - fread(evt_body, size, 1, infp); - grpid = *(int8_t *)evt_body; - hookid = *(int8_t *)(evt_body+1); - len = strlen(evt_body+2)+2; - if(!events_des[_HOOKID_REGSYSEVT][grpid][hookid]) - events_des[_HOOKID_REGSYSEVT][grpid][hookid] = malloc(sizeof(event_desc)); - events_des[_HOOKID_REGSYSEVT][grpid][hookid]->description = malloc(len); - - strncpy(events_des[_HOOKID_REGSYSEVT][grpid][hookid]->description, evt_body+2, len); -#ifdef HAS_MYSQL - events_des[_HOOKID_REGSYSEVT][grpid][hookid]->entrytime = g_tree_new_full( - compareFunc, NULL, NULL, destroyTreeData); - if(into_db) { - if(!has_table) { - snprintf(sql, 1024, "create table table_desc ( table_name varchar(6), table_desc varchar(32))"); - if(mysql_query(&mysql, sql)) { - b2a_error("Failed exec SQL: \n %s \n, Error: %s\n", - sql, mysql_error(&mysql)); - } - has_table = 1; - } - - snprintf(sql, 1024, "insert into table_desc ( table_name, table_desc) values ( \"%d_%d\", \"%s\")", grpid, hookid, - evt_body+2); - - if(mysql_query(&mysql, sql)) { - b2a_error("Failed exec SQL:\n %s \n, Error: %s\n", - sql, mysql_error(&mysql)); - } - } -#endif - free(evt_body); -} - -void register_events(int evt_type, FILE *infp, size_t size) -{ - int cnt=0, len=0; - - char *evt_body, *evt_fmt, *evt_names, *tmp, *fmt, *name; - int8_t grpid, hookid; - - evt_body = malloc(size); - - fread(evt_body, size, 1, infp); - - grpid = *(int8_t *)evt_body; - hookid = *(int8_t *)(evt_body+1); - - if(!events_des[evt_type][grpid][hookid]) - events_des[evt_type][grpid][hookid] = malloc(sizeof(event_desc)); - if(!events_des[evt_type][grpid][hookid]) { - b2a_error("error when malloc for event_des[%d][%d][%d]\n", - evt_type, grpid, hookid); - } - -#ifdef HAS_MYSQL - if(into_db) { - if(evt_type==_HOOKID_REGSYSEVT) { /* if sys event, create a table */ - if(!(hookid%2)) {/* if this is a return type event, should record - the entry time of this event */ - snprintf(sql, 1024, "create table %d_%d ( groupid TINYINT, hookid TINYINT, usec BIGINT, thread_id INT, process_id INT, parentprocess_id INT, cpu_id TINYINT, entry_usec BIGINT,", grpid, hookid); - } else { - snprintf(sql, 1024, "create table %d_%d ( groupid TINYINT, hookid TINYINT, usec BIGINT, thread_id INT, process_id INT, parentprocess_id INT, cpu_id TINYINT,", grpid, hookid); - } - } - if(evt_type==_HOOKID_REGUSREVT) { /* if user event, alter an existing table */ - snprintf(sql, 1024, "alter table %d_%d ", grpid, hookid); - } - } - - if(size == 2) // skip if no event format is provided - goto gen_sql; -#endif - - evt_fmt = evt_body+2; - - for(tmp=evt_fmt; *tmp!=0; tmp++); - - evt_names = tmp+1; - - fmt = strsep(&evt_fmt, ":"); - name = strsep(&evt_names, ":"); - - if(fmt==NULL || name==NULL) { - b2a_error("error in event format/names string\n"); - } - - while(fmt!=NULL && name!=NULL) { -#ifdef HAS_MYSQL - if(into_db) { - if(evt_type==_HOOKID_REGSYSEVT) { - strcat(sql, "`"); - strcat(sql, name); - strcat(sql, "` "); - strcat(sql, get_sqltype(fmt)); - strcat(sql, ","); - } - if(evt_type==_HOOKID_REGUSREVT) { - strcat(sql, "add "); - strcat(sql, "`"); - strcat(sql, name); - strcat(sql, "` "); - strcat(sql, get_sqltype(fmt)); - strcat(sql, ","); - } - } -#endif - strncpy(events_des[evt_type][grpid][hookid]->evt_fmt[cnt], fmt, 7); - strncpy(events_des[evt_type][grpid][hookid]->evt_names[cnt], - name, MAX_FIELDNAME_LEN); - strncpy(events_des[evt_type][grpid][hookid]->fmt+len, get_fmtstr(fmt), 8); - len+=strlen(get_fmtstr(fmt)); - fmt = strsep(&evt_fmt, ":"); - name = strsep(&evt_names, ":"); - cnt++; - } - events_des[evt_type][grpid][hookid]->count = cnt; - *(events_des[evt_type][grpid][hookid]->fmt+len)='\0'; - -#ifdef HAS_MYSQL -gen_sql: - if(into_db) { - if(evt_type==_HOOKID_REGSYSEVT) - sql[strlen(sql)-1]=')'; - if(evt_type==_HOOKID_REGUSREVT) - sql[strlen(sql)-1]='\0'; - - if(mysql_query(&mysql, sql)) { - b2a_error("Failed exec SQL: \n %s \n, Error: %s\n", - sql, mysql_error(&mysql)); - } - } -#endif - free(evt_body); -} - -char *get_fmtstr(char *fmt) -{ - if(strncmp(fmt, "INT8", 4) == 0) - return "%1b"; - if(strncmp(fmt, "INT16", 5) == 0) - return "%2b"; - if(strncmp(fmt, "INT32", 5) == 0) - return "%4b"; - if(strncmp(fmt, "INT64", 5) == 0) - return "%8b"; - if(strncmp(fmt, "STRING", 6) == 0) - return "%0s"; - return ""; -} - -int dump_data(lket_pkt_header header, FILE *infp) -{ - int i, c, j; - int16_t stemp; - int32_t ntemp; - long long lltemp; - int readbytes = 0; - int total_bytes = 0; - int size = 0; - int evt_num = 1; - - char tmp_int[32]; - - char *fmt, *name, *buffer; - int grpid = HDR_GroupID(&header); - int hookid = HDR_HookID(&header); - - print_pkt_header(&header); - - /* if the data contains user appended extra data */ - if(header.total_size != header.sys_size) - evt_num = 3; - - /* iterate the sys and user event */ - for(j=1; j<= evt_num; j+=2) { - - readbytes = 0; - - if(j == 1) /* if current one is a sys event */ - size = header.sys_size; - if(j == 2) /* if current one is a user event */ - size = header.total_size - header.sys_size; - - if(into_file && (events_des[j][grpid][hookid] == NULL || - events_des[j][grpid][hookid]->count <= 0)) { - //no format is provided, dump in hex - buffer = malloc(size); - fread(buffer, size, 1, infp); - fwrite(buffer, size, 1, outfp); - free(buffer); - total_bytes += size; - continue; - } - - events_des[j][grpid][hookid]->flag = 1; - - for(i=0; i<events_des[j][grpid][hookid]->count; i++) { - fmt = events_des[j][grpid][hookid]->evt_fmt[i]; - name = events_des[j][grpid][hookid]->evt_names[i]; -#ifdef HAS_MYSQL - if(into_db) { - strcat(sql_col, "`"); - strcat(sql_col, name); - strcat(sql_col, "`,"); - } -#endif - - if(into_file) { - fwrite(name, strlen(name), 1, outfp); - fwrite(":", 1, 1, outfp); - } - if(strncmp(fmt, "INT8", 4)==0) { - c = fgetc_unlocked(infp); - if(into_file) - fprintf(outfp, "%d,", (int8_t)c); - sprintf(tmp_int, "%d,", (int8_t)c); -#ifdef HAS_MYSQL - if(into_db) - strcat(sql_val, tmp_int); -#endif - readbytes+=1; - } else if(strncmp(fmt, "INT16", 5)==0) { - fread(&stemp, 2, 1, infp); - if(into_file) - fprintf(outfp, "%d,", (int16_t)stemp); - sprintf(tmp_int, "%d,", (int16_t)stemp); -#ifdef HAS_MYSQL - if(into_db) - strcat(sql_val, tmp_int); -#endif - readbytes+=2; - } else if(strncmp(fmt, "INT32", 5)==0) { - fread(&ntemp, 4, 1, infp); - if(into_file) - fprintf(outfp, "%d,", (int32_t)ntemp); - snprintf(tmp_int, 20, "%d,", (int32_t)ntemp); -#ifdef HAS_MYSQL - if(into_db) - strcat(sql_val, tmp_int); -#endif - readbytes+=4; - } else if(strncmp(fmt, "INT64", 5)==0) { - fread(&lltemp, 8, 1, infp); - if(into_file) - fprintf(outfp, "%lld,",lltemp); - snprintf(tmp_int, 30, "%lld,", lltemp); -#ifdef HAS_MYSQL - if(into_db) - strcat(sql_val, tmp_int); -#endif - readbytes+=8; - } else if(strncmp(fmt, "STRING", 6)==0) { - -#ifdef HAS_MYSQL - int tmplen=0; - if(into_db) { - tmplen=strlen(sql_val); - sql_val[tmplen++]='"'; - } -#endif - c = fgetc_unlocked(infp); - ++readbytes; - while (c && readbytes < size) { - if(into_file) - fputc_unlocked(c, outfp); -#ifdef HAS_MYSQL - if(into_db) - sql_val[tmplen++]=c; -#endif - c = fgetc_unlocked(infp); - ++readbytes; - } - if(!c) { - if(into_file) - fputc_unlocked(',', outfp); -#ifdef HAS_MYSQL - if(into_db) { - sql_val[tmplen++]='"'; - sql_val[tmplen++]=','; - sql_val[tmplen]='\0'; - } -#endif - continue; - } - else { - b2a_error("error processing STRING\n"); - } - } - } - total_bytes += readbytes; - } - -#ifdef HAS_MYSQL - if(into_db) { - sql_col[strlen(sql_col)-1] = '\0'; - sql_val[strlen(sql_val)-1] = '\0'; - snprintf(sql, 1024, "insert into %d_%d (%s) values (%s)", - grpid, hookid, sql_col, sql_val); - - if(sql_count >= INSERT_THRESHOLD) { - if(mysql_query(&mysql, sqlStatement)) { - b2a_error("Failed exec SQL:\n%s\n, Error:\n%s\n", - sqlStatement, mysql_error(&mysql)); - } - while(!mysql_next_result(&mysql)); - sql_count=0; - sqlStatement[0]='\0'; - } else { - //strncpy(sqlStatement, sql, 2048); - strcat(sqlStatement, sql); - strcat(sqlStatement, ";"); - sql_count++; - } - } -#endif - - return total_bytes; -} diff --git a/runtime/lket/b2a/lket_b2a.h b/runtime/lket/b2a/lket_b2a.h deleted file mode 100644 index 46ca91f6..00000000 --- a/runtime/lket/b2a/lket_b2a.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef _LKET_B2A_H -#define _LKET_B2A_H - -#include <glib.h> - -#ifdef HAS_MYSQL -#include <mysql/mysql.h> -#endif - -typedef struct _percpu_header { - int32_t seq; - int32_t len; -} percpu_header; - -#define LKET_MAGIC 0xAEFCDB6B - -#define MAX_STRINGLEN 256 - -#define MAX_GRPID 255 -#define MAX_HOOKID 255 -#define MAX_EVT_TYPES 3 - -#define DEFAULT_OUTFILE_NAME "lket.out" - -/* Group ID Definitions */ -int _GROUP_REGEVT = 1; -int _GROUP_PROCESS = 3; -int _GROUP_CPUFREQ = 15; - -/* hookIDs defined inside each group */ -int _HOOKID_REGSYSEVT = 1; -int _HOOKID_REGUSREVT = 3; -int _HOOKID_REGEVTDESC = 5; - -int _HOOKID_PROCESS_SNAPSHOT = 1; -int _HOOKID_PROCESS_EXECVE = 3; -int _HOOKID_PROCESS_FORK = 5; - -//int _HOOKID_INIT_CPUFREQ = 1; -int _HOOKID_SWITCH_CPUFREQ = 1; - -typedef struct _lket_pkt_header { - int16_t total_size; - int16_t sys_size; - int64_t microsecond; - /* tid_pid is (tid<<32|pid) */ - int64_t tid_pid; - /* aggr is the bit-OP of: - (int64_t)current->parent->tgid << 32 | - (int32_t)GroupID << 24 | (int32_t)hookID << 16 | - (int16_t)current->thread_info->cpu << 8 - */ - int64_t aggr; -} __attribute__((packed)) lket_pkt_header; - -#define HDR_TID(ptr) (int32_t)(((ptr)->tid_pid)>>32) -#define HDR_PID(ptr) (int32_t)((ptr)->tid_pid) -#define HDR_PPID(ptr) (int32_t)(((ptr)->aggr)>>32) -#define HDR_GroupID(ptr) (int8_t)(((ptr)->aggr)>>24) -#define HDR_HookID(ptr) (int8_t)(((ptr)->aggr)>>16) -#define HDR_CpuID(ptr) (int8_t)(((ptr)->aggr)>>8) - -#define MAX_FIELDS 32 /* max fields in a record */ -#define MAX_FIELDNAME_LEN 16 /* max len of a field */ - -typedef struct { -#ifdef HAS_MYSQL - GTree *entrytime; -#endif - char evt_fmt[MAX_FIELDS][7]; /* e.g. INT8,STRING,INT16,... */ - char evt_names[MAX_FIELDS][MAX_FIELDNAME_LEN]; /* e.g. protocal,dev_name,buff_len,... */ - char fmt[256]; /* e.g. %1b,%0s,%2b,... */ - char *description; /* a string description of this event, such as "iosyscall.read.entry" */ - int count; /* # of fields */ - int flag; /* a flag indicates whether exists trace data for this event */ -} event_desc; - -/* - * search the lket_init_header structure in a set of input files - */ -static void find_init_header(FILE **fp, const int total_infiles); - -/* - * read the lket_pkt_header structure at the begining of the input file - */ -static int get_pkt_header(FILE *fp, lket_pkt_header *phdr); - -/* - * print the lket_pkt_header structure into the output file - */ -static void print_pkt_header(lket_pkt_header *phdr); - -void register_appname(int i, FILE *fp, lket_pkt_header *phdr); -gint compareFunc(gconstpointer a, gconstpointer b, gpointer user_data); -void destroyTreeData(gpointer data); -void register_evt_desc(FILE *infp, size_t size); -void register_events(int evt_type, FILE *infp, size_t size); -int dump_data(lket_pkt_header header, FILE *infp); -char *get_fmtstr(char *fmt); - -#endif diff --git a/runtime/map.c b/runtime/map.c index 513e27df..a436d7ed 100644 --- a/runtime/map.c +++ b/runtime/map.c @@ -15,7 +15,6 @@ * @brief Implements maps (associative arrays) and lists */ -#include "alloc.c" #include "sym.c" #include "stat-common.c" #include "map-stat.c" diff --git a/runtime/probes.c b/runtime/probes.c index 19539044..6fe844fb 100644 --- a/runtime/probes.c +++ b/runtime/probes.c @@ -25,7 +25,7 @@ void _stp_unregister_jprobes (struct jprobe *probes, int num_probes) int i; for (i = 0; i < num_probes; i++) unregister_jprobe(&probes[i]); - dbug("All jprobes removed\n"); + // dbug("All jprobes removed\n"); } /** Register a group of jprobes. @@ -46,7 +46,7 @@ int _stp_register_jprobes (struct jprobe *probes, int num_probes) ret = -1; /* FIXME */ goto out; } - dbug("inserting jprobe at %s (%p)\n", probes[i].kp.addr, addr); + // dbug("inserting jprobe at %s (%p)\n", probes[i].kp.addr, addr); probes[i].kp.addr = (kprobe_opcode_t *)addr; ret = register_jprobe(&probes[i]); if (ret) @@ -69,7 +69,7 @@ void _stp_unregister_kprobes (struct kprobe *probes, int num_probes) int i; for (i = 0; i < num_probes; i++) unregister_kprobe(&probes[i]); - dbug("All kprobes removed\n"); + // dbug("All kprobes removed\n"); } @@ -83,7 +83,7 @@ void _stp_unregister_kretprobes (struct kretprobe *probes, int num_probes) int i; for (i = 0; i < num_probes; i++) unregister_kretprobe(&probes[i]); - dbug("All return probes removed\n"); + // dbug("All return probes removed\n"); } #endif @@ -104,7 +104,7 @@ int _stp_register_kprobes (struct kprobe *probes, int num_probes) ret = -1; goto out; } - dbug("inserting kprobe at %s (%p)\n", probes[i].addr, addr); + // dbug("inserting kprobe at %s (%p)\n", probes[i].addr, addr); probes[i].addr = (kprobe_opcode_t *)addr; ret = register_kprobe(&probes[i]); if (ret) @@ -136,7 +136,7 @@ int _stp_register_kretprobes (struct kretprobe *probes, int num_probes) ret = -1; /* FIXME */ goto out; } - dbug("inserting kretprobe at %s (%p)\n", probes[i].kp.addr, addr); + // dbug("inserting kretprobe at %s (%p)\n", probes[i].kp.addr, addr); probes[i].kp.addr = (kprobe_opcode_t *)addr; ret = register_kretprobe(&probes[i]); if (ret) diff --git a/runtime/probes/bench/Makefile b/runtime/probes/bench/Makefile deleted file mode 100644 index 9154e3dc..00000000 --- a/runtime/probes/bench/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: ttest itest - -ttest: ttest.c - gcc -Wall -O3 -o ttest ttest.c - -itest: itest.c - gcc -Wall -O3 -o itest itest.c - -clean: - /bin/rm -f itest ttest stpd_cpu* xxx* diff --git a/runtime/runtime.h b/runtime/runtime.h index 318d3038..b9a9c778 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -76,7 +76,6 @@ static struct #include "io.c" #include "arith.c" #include "copy.c" -#include "sym.h" #include "sym.c" #ifdef STP_PERFMON #include "perf.c" diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 186b2ad4..3ba99201 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * x86_64 stack tracing functions - * Copyright (C) 2005, 2006, 2007 Red Hat Inc. + * Copyright (C) 2005-2008 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -8,13 +8,38 @@ * later version. */ -static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) +// todo: don't use unwinder for kernel if CONFIG_FRAME + +/* DWARF unwinder failed. Just dump intereting addresses on kernel stack. */ +static void _stp_stack_print_fallback(unsigned long stack, int verbose) { - unsigned long *stack = (unsigned long *)REG_SP(regs); unsigned long addr; - while ((long)stack & (THREAD_SIZE-1)) { - addr = *stack++; - _stp_func_print(addr, verbose, 1); + while (stack & (THREAD_SIZE - 1)) { + if (unlikely(__stp_get_user(addr, (unsigned long *)stack))) { + /* cannot access stack. give up. */ + return; + } + _stp_func_print(addr, verbose, 0); + stack++; + } +} + +static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels) +{ + struct unwind_frame_info info; + arch_unw_init_frame_info(&info, regs); + + /* we haven't actually executed the instruction at the IP yet. */ + UNW_PC(&info) -= 1; + + while (!arch_unw_user_mode(&info)) { + int ret = unwind(&info); + dbug_unwind(1, "ret=%d PC=%lx\n", ret, UNW_PC(&info)); + if (ret < 0) { + _stp_stack_print_fallback(UNW_SP(&info), verbose); + break; + } + _stp_func_print(UNW_PC(&info), verbose, 1); } } diff --git a/runtime/stack.c b/runtime/stack.c index 9c01d65c..e338f587 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * Stack tracing functions - * Copyright (C) 2005, 2006, 2007 Red Hat Inc. + * Copyright (C) 2005-2008 Red Hat Inc. * Copyright (C) 2005 Intel Corporation. * * This file is part of systemtap, and is free software. You can @@ -23,6 +23,7 @@ #include "sym.c" #include "regs.h" +#include "unwind.c" #define MAXBACKTRACE 20 diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index 2e0c3c5c..1dcb6b00 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -27,7 +27,7 @@ static void sigproc(int signum) return; send_request(STP_EXIT, NULL, 0); } else if (signum == SIGQUIT) - cleanup_and_exit(2); + cleanup_and_exit(2); else if (signum == SIGINT || signum == SIGHUP || signum == SIGTERM) send_request(STP_EXIT, NULL, 0); } @@ -40,7 +40,7 @@ static void setup_main_signals(int cleanup) if (cleanup == 0) { a.sa_handler = sigproc; sigaction(SIGCHLD, &a, NULL); - } else + } else a.sa_handler = SIG_IGN; sigaction(SIGINT, &a, NULL); sigaction(SIGTERM, &a, NULL); @@ -48,7 +48,6 @@ static void setup_main_signals(int cleanup) sigaction(SIGQUIT, &a, NULL); } - /* * start_cmd forks the command given on the command line * with the "-c" option. It will not exec that command @@ -75,7 +74,7 @@ void start_cmd(void) a.sa_handler = SIG_IGN; sigaction(SIGINT, &a, NULL); - dbug (1, "execing target_cmd %s\n", target_cmd); + dbug(1, "execing target_cmd %s\n", target_cmd); if ((pid = fork()) < 0) { _perr("fork"); exit(1); @@ -86,8 +85,8 @@ void start_cmd(void) sigaction(SIGINT, &a, NULL); /* commands we fork need to run at normal priority */ - setpriority (PRIO_PROCESS, 0, 0); - + setpriority(PRIO_PROCESS, 0, 0); + /* wait here until signaled */ sigwait(&usrset, &signum); @@ -107,11 +106,11 @@ void system_cmd(char *cmd) { pid_t pid; - dbug (2, "system %s\n", cmd); + dbug(2, "system %s\n", cmd); if ((pid = fork()) < 0) { _perr("fork"); } else if (pid == 0) { - setpriority (PRIO_PROCESS, 0, 0); + setpriority(PRIO_PROCESS, 0, 0); if (execl("/bin/sh", "sh", "-c", cmd, NULL) < 0) perr("%s", cmd); _exit(1); @@ -128,7 +127,7 @@ static void read_buffer_info(void) if (!use_old_transport) return; - if (statfs("/sys/kernel/debug", &st) == 0 && (int) st.f_type == (int) DEBUGFS_MAGIC) + if (statfs("/sys/kernel/debug", &st) == 0 && (int)st.f_type == (int)DEBUGFS_MAGIC) return; if (sprintf_chk(buf, "/proc/systemtap/%s/bufsize", modname)) @@ -152,7 +151,6 @@ static void read_buffer_info(void) return; } - /** * init_stapio - initialize the app * @print_summary: boolean, print summary or not at end of run @@ -177,7 +175,7 @@ int init_stapio(void) if (init_oldrelayfs() < 0) { close_ctl_channel(); return -1; - } + } } else { if (init_relayfs() < 0) { close_ctl_channel(); @@ -192,7 +190,6 @@ int init_stapio(void) if (target_cmd) start_cmd(); - return 0; } @@ -202,7 +199,7 @@ int init_stapio(void) * 2 - disconnected * 3 - initialized */ -void cleanup_and_exit (int closed) +void cleanup_and_exit(int closed) { pid_t err; static int exiting = 0; @@ -219,7 +216,7 @@ void cleanup_and_exit (int closed) err = waitpid(-1, NULL, WNOHANG); if (err >= 0) err("\nWaiting for processes to exit\n"); - while(wait(NULL) > 0) ; + while (wait(NULL) > 0) ; if (use_old_transport) close_oldrelayfs(closed == 2); @@ -230,8 +227,7 @@ void cleanup_and_exit (int closed) close_ctl_channel(); if (initialized == 2 && closed == 2) { - err("\nDisconnecting from systemtap module.\n" \ - "To reconnect, type \"staprun -A %s\"\n", modname); + err("\nDisconnecting from systemtap module.\n" "To reconnect, type \"staprun -A %s\"\n", modname); } else if (initialized) closed = 3; else @@ -247,7 +243,7 @@ int stp_main_loop(void) { ssize_t nb; void *data; - int type; + uint32_t type; FILE *ofp = stdout; char recvbuf[8196]; @@ -257,80 +253,93 @@ int stp_main_loop(void) dbug(2, "in main loop\n"); send_request(STP_READY, NULL, 0); - while (1) { /* handle messages from control channel */ + while (1) { /* handle messages from control channel */ nb = read(control_channel, recvbuf, sizeof(recvbuf)); if (nb <= 0) { if (errno != EINTR) _perr("Unexpected EOF in read (nb=%ld)", (long)nb); continue; } - - type = *(int *)recvbuf; - data = (void *)(recvbuf + sizeof(int)); - switch (type) { + type = *(uint32_t *)recvbuf; + data = (void *)(recvbuf + sizeof(uint32_t)); + nb -= sizeof(uint32_t); + + switch (type) { #ifdef STP_OLD_TRANSPORT case STP_REALTIME_DATA: - { - ssize_t bw = write(out_fd[0], data, nb - sizeof(int)); - if (bw >= 0 && bw != (nb - (ssize_t)sizeof(int))) { - nb = nb - bw; - bw = write(out_fd[0], data, nb - sizeof(int)); - } - if (bw != (nb - (ssize_t)sizeof(int))) { - _perr("write error (nb=%ld)", (long)nb); - cleanup_and_exit(1); + { + ssize_t bw = write(out_fd[0], data, nb); + if (bw >= 0 && bw != nb) { + nb = nb - bw; + bw = write(out_fd[0], data, nb); + } + if (bw != nb) { + _perr("write error (nb=%ld)", (long)nb); + cleanup_and_exit(1); + } + break; } - break; - } #endif case STP_OOB_DATA: - fputs ((char *)data, stderr); - break; - case STP_EXIT: - { - /* module asks us to unload it and exit */ - int *closed = (int *)data; - dbug(2, "got STP_EXIT, closed=%d\n", *closed); - cleanup_and_exit(*closed); - break; - } - case STP_START: - { - struct _stp_msg_start *t = (struct _stp_msg_start *)data; - dbug(2, "probe_start() returned %d\n", t->res); - if (t->res < 0) { - if (target_cmd) - kill (target_pid, SIGKILL); - cleanup_and_exit(1); - } else if (target_cmd) - kill (target_pid, SIGUSR1); + fputs((char *)data, stderr); break; - } + case STP_EXIT: + { + /* module asks us to unload it and exit */ + int *closed = (int *)data; + dbug(2, "got STP_EXIT, closed=%d\n", *closed); + cleanup_and_exit(*closed); + break; + } + case STP_START: + { + struct _stp_msg_start *t = (struct _stp_msg_start *)data; + dbug(2, "probe_start() returned %d\n", t->res); + if (t->res < 0) { + if (target_cmd) + kill(target_pid, SIGKILL); + cleanup_and_exit(1); + } else if (target_cmd) + kill(target_pid, SIGUSR1); + break; + } case STP_SYSTEM: - { - struct _stp_msg_cmd *c = (struct _stp_msg_cmd *)data; - dbug(2, "STP_SYSTEM: %s\n", c->cmd); - system_cmd(c->cmd); - break; - } + { + struct _stp_msg_cmd *c = (struct _stp_msg_cmd *)data; + dbug(2, "STP_SYSTEM: %s\n", c->cmd); + system_cmd(c->cmd); + break; + } case STP_TRANSPORT: - { - struct _stp_msg_start ts; - if (use_old_transport) { - if (init_oldrelayfs() < 0) - cleanup_and_exit(1); - } else { - if (init_relayfs() < 0) - cleanup_and_exit(1); + { + struct _stp_msg_start ts; + if (use_old_transport) { + if (init_oldrelayfs() < 0) + cleanup_and_exit(1); + } else { + if (init_relayfs() < 0) + cleanup_and_exit(1); + } + ts.target = target_pid; + initialized = 2; + send_request(STP_START, &ts, sizeof(ts)); + if (load_only) + cleanup_and_exit(2); + break; + } + case STP_UNWIND: + { + int len; + char *ptr = (char *)data; + while (nb > 0) { + send_unwind_data(ptr); + len = strlen(ptr) + 1; + ptr += len; + nb -= len; + } + break; } - ts.target = target_pid; - initialized = 2; - send_request(STP_START, &ts, sizeof(ts)); - if (load_only) - cleanup_and_exit(2); - break; - } default: err("WARNING: ignored message of type %d\n", (type)); } diff --git a/runtime/staprun/staprun.c b/runtime/staprun/staprun.c index f4e67fdb..8db2ac5b 100644 --- a/runtime/staprun/staprun.c +++ b/runtime/staprun/staprun.c @@ -181,8 +181,6 @@ static void cleanup(int rc) if (setpriority (PRIO_PROCESS, 0, 0) < 0) _perr("setpriority"); - stop_symbol_thread(); - /* rc == 2 means disconnected */ if (rc == 2) return; @@ -278,7 +276,6 @@ int main(int argc, char **argv) exit(1); setup_staprun_signals(); - start_symbol_thread(); rc = run_stapio(argv); cleanup(rc); diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 1128fb4c..08797a37 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -118,8 +118,7 @@ int init_stapio(void); int stp_main_loop(void); int send_request(int type, void *data, int len); void cleanup_and_exit (int); -int do_module(void *); -int do_kernel_symbols(void); +void send_unwind_data(const char *name); int init_ctl_channel(int); void close_ctl_channel(void); int init_relayfs(void); diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index 34e12c25..b95a9a5a 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -401,95 +401,3 @@ int check_permissions(void) * is in that directory. */ return check_path(); } - -pthread_t symbol_thread_id = (pthread_t)0; -int kernel_ptr_size = 0; - -/* Symbol handling thread */ -void *handle_symbols(void __attribute__((unused)) *arg) -{ - ssize_t nb; - void *data; - int32_t type; - char recvbuf[8192]; - - dbug(2, "waiting for symbol requests\n"); - - /* handle messages from control channel */ - while (1) { - nb = read(control_channel, recvbuf, sizeof(recvbuf)); - if (nb <= 0) { - if (errno != EINTR) - _perr("Unexpected EOF in read (nb=%ld)", (long)nb); - continue; - } - - type = *(int32_t *)recvbuf; - data = (void *)(recvbuf + sizeof(int32_t)); - - switch (type) { - case STP_MODULE: - { - dbug(2, "STP_MODULES request received\n"); - if (do_module(data) < 0) - goto done; - break; - } - case STP_SYMBOLS: - { - struct _stp_msg_symbol *req = (struct _stp_msg_symbol *)data; - dbug(2, "STP_SYMBOLS request received\n"); - if (req->endian != 0x1234) { - err("ERROR: staprun is compiled with different endianess than the kernel!\n"); - goto done; - } - kernel_ptr_size = req->ptr_size; - if (kernel_ptr_size != 4 && kernel_ptr_size != 8) { - err("ERROR: invalid kernel pointer size %d\n", kernel_ptr_size); - goto done; - } - if (do_kernel_symbols() < 0) - goto done; - break; - } - default: - err("WARNING: ignored message of type %d\n", (type)); - } - } - -done: - /* signal stapio we're done */ - kill(0, SIGINT); - - return NULL; -} - -void start_symbol_thread(void) -{ - int status; - - /* create symbol control channel */ - status = do_cap(CAP_DAC_OVERRIDE, init_ctl_channel, 1); - drop_cap(CAP_DAC_OVERRIDE); - if (status < 0) { - err("Failed to initialize control channel.\n"); - exit(1); - } - status = pthread_create(&symbol_thread_id, NULL, handle_symbols, NULL); - if (status) { - perr("Failed to create symbol thread.\n"); - exit(1); - } -} - -void stop_symbol_thread(void) -{ - - if (symbol_thread_id) { - dbug(2, "Stopping symbol thread.\n"); - pthread_cancel(symbol_thread_id); - pthread_join(symbol_thread_id, NULL); - } - close_ctl_channel(); -} - diff --git a/runtime/staprun/unwind_data.c b/runtime/staprun/unwind_data.c new file mode 100644 index 00000000..ed27cc20 --- /dev/null +++ b/runtime/staprun/unwind_data.c @@ -0,0 +1,97 @@ +/* -*- linux-c -*- + * Unwind data functions for staprun. + * + * Copyright (C) 2008 Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + */ + +#include "staprun.h" +#include <elfutils/libdwfl.h> +#include <dwarf.h> + +static char debuginfo_path_arr[] = "-:.debug:/usr/lib/debug"; +static char *debuginfo_path = debuginfo_path_arr; +static const Dwfl_Callbacks kernel_callbacks = { + .find_debuginfo = dwfl_standard_find_debuginfo, + .debuginfo_path = &debuginfo_path, + .find_elf = dwfl_linux_kernel_find_elf, + .section_address = dwfl_linux_kernel_module_section_address, +}; + +void *get_module_unwind_data(Dwfl * dwfl, const char *name, int *len) +{ + Dwarf_Addr bias = 0; + Dwarf *dw; + GElf_Ehdr *ehdr, ehdr_mem; + GElf_Shdr *shdr, shdr_mem; + Elf_Scn *scn = NULL; + Elf_Data *data = NULL; + + Dwfl_Module *mod = dwfl_report_module(dwfl, name, 0, 0); + dwfl_report_end(dwfl, NULL, NULL); + dw = dwfl_module_getdwarf(mod, &bias); + 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) { + *len = 0; + dbug(2, "module %s returns NULL\n", name); + return NULL; + } + dbug(2, "module %s returns %d\n", name, (int)data->d_size); + *len = data->d_size; + return data->d_buf; +} + +void send_unwind_data(const char *name) +{ + struct _stp_msg_unwind *un; + int unwind_data_len = 0; + void *unwind_data = NULL; + char *buf; + + dbug(2, "module %s\n", name); + if (strcmp(name, "*")) { + Dwfl *dwfl = dwfl_begin(&kernel_callbacks); + + if (name[0] == 0) + unwind_data = get_module_unwind_data(dwfl, "kernel", &unwind_data_len); + else + unwind_data = get_module_unwind_data(dwfl, name, &unwind_data_len); + + /* yuck */ + buf = (char *)malloc(unwind_data_len + sizeof(*un) + sizeof(uint32_t)); + if (!buf) { + err("malloc failed\n"); + return; + } + memcpy(buf + sizeof(*un) + sizeof(uint32_t), unwind_data, unwind_data_len); + dwfl_end(dwfl); + } else { + buf = (char *)malloc(sizeof(*un) + sizeof(uint32_t)); + if (!buf) { + err("malloc failed\n"); + return; + } + } + + un = (struct _stp_msg_unwind *)(buf + sizeof(uint32_t)); + strncpy(un->name, name, sizeof(un->name)); + un->unwind_len = unwind_data_len; + *(uint32_t *) buf = STP_UNWIND; + + /* send unwind data */ + if (write(control_channel, buf, unwind_data_len + sizeof(*un) + sizeof(uint32_t)) <= 0) + err("write failed\n"); +} diff --git a/runtime/sym.c b/runtime/sym.c index 3c2f859a..3d5ff01d 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -33,7 +33,7 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi return 0; } - dbug(DEBUG_SYMBOLS, "%s, %s, %lx\n", module, section, offset); + dbug_sym(1, "%s, %s, %lx\n", module, section, offset); STP_RLOCK_MODULES; if (!module || !strcmp(section, "") /* absolute, unrelocated address */ @@ -47,7 +47,7 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi if (!strcmp(module, last->name) && !strcmp(section, last_sec->symbol)) { offset += last_sec->addr; STP_RUNLOCK_MODULES; - dbug(DEBUG_SYMBOLS, "offset = %lx\n", offset); + dbug_sym(1, "offset = %lx\n", offset); return offset; } } @@ -72,7 +72,7 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi if (!strcmp(section, last_sec->symbol)) { offset += last_sec->addr; STP_RUNLOCK_MODULES; - dbug(DEBUG_SYMBOLS, "offset = %lx\n", offset); + dbug_sym(1, "offset = %lx\n", offset); return offset; } } diff --git a/runtime/sym.h b/runtime/sym.h index b124882a..631a5bbf 100644 --- a/runtime/sym.h +++ b/runtime/sym.h @@ -7,8 +7,8 @@ * later version. */ -#ifndef _STAP_SYMBOLS_H_ -#define _STAP_SYMBOLS_H_ +#ifndef _STP_SYM_H_ +#define _STP_SYM_H_ #define STP_MODULE_NAME_LEN 64 @@ -16,11 +16,6 @@ struct _stp_symbol { unsigned long addr; const char *symbol; }; -struct stap_symbol { - unsigned long addr; - const char *symbol; - const char *module; -}; DEFINE_RWLOCK(_stp_module_lock); #define STP_RLOCK_MODULES read_lock_irqsave(&_stp_module_lock, flags) @@ -50,8 +45,14 @@ struct _stp_module { /* how many sections this module has */ uint32_t num_sections; - /* how the symbol_data below was allocated */ - int32_t allocated; /* 0 = kmalloc, 1 = vmalloc */ + /* how the data below was allocated */ + /* 0 = kmalloc, 1 = vmalloc */ + struct { + unsigned symbols :1; + unsigned symbol_data :1; + unsigned unwind_data :1; + unsigned unwind_hdr :1; + } allocated; struct _stp_symbol *sections; @@ -63,7 +64,10 @@ struct _stp_module { /* the stack unwind data for this module */ void *unwind_data; + void *unwind_hdr; uint32_t unwind_data_len; + uint32_t unwind_hdr_len; + uint32_t unwind_is_ehframe; /* unwind data comes from .eh_frame */ rwlock_t lock; /* lock while unwinding is happening */ }; @@ -83,4 +87,4 @@ int _stp_num_modules = 0; unsigned long _stp_module_relocate (const char *module, const char *section, unsigned long offset); static struct _stp_module *_stp_get_unwind_info (unsigned long addr); -#endif /* _STAP_SYMBOLS_H_ */ +#endif /* _STP_SYM_H_ */ diff --git a/runtime/tests/Makefile b/runtime/tests/Makefile deleted file mode 100644 index 4e744d25..00000000 --- a/runtime/tests/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -tests: - tclsh all.tcl - diff --git a/runtime/tests/agg/Makefile b/runtime/tests/agg/Makefile deleted file mode 100644 index c396c132..00000000 --- a/runtime/tests/agg/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -default: tests - -tests: - tclsh all.tcl - diff --git a/runtime/tests/maps/Makefile b/runtime/tests/maps/Makefile deleted file mode 100644 index c396c132..00000000 --- a/runtime/tests/maps/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -default: tests - -tests: - tclsh all.tcl - diff --git a/runtime/tests/math/Makefile b/runtime/tests/math/Makefile deleted file mode 100644 index c396c132..00000000 --- a/runtime/tests/math/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -default: tests - -tests: - tclsh all.tcl - diff --git a/runtime/tests/pmaps/Makefile b/runtime/tests/pmaps/Makefile deleted file mode 100644 index c396c132..00000000 --- a/runtime/tests/pmaps/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -default: tests - -tests: - tclsh all.tcl - diff --git a/runtime/tests/string/Makefile b/runtime/tests/string/Makefile deleted file mode 100644 index c396c132..00000000 --- a/runtime/tests/string/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -default: tests - -tests: - tclsh all.tcl - diff --git a/runtime/transport/control.c b/runtime/transport/control.c index 6a5b272d..ed7725fa 100644 --- a/runtime/transport/control.c +++ b/runtime/transport/control.c @@ -14,80 +14,31 @@ static int _stp_current_buffers = STP_DEFAULT_BUFFERS; static _stp_mempool_t *_stp_pool_q; static struct list_head _stp_ctl_ready_q; -static struct list_head _stp_sym_ready_q; DEFINE_SPINLOCK(_stp_ctl_ready_lock); -DEFINE_SPINLOCK(_stp_sym_ready_lock); -static ssize_t _stp_sym_write_cmd(struct file *file, const char __user *buf, size_t count, loff_t *ppos) -{ - static int saved_type = 0; - int type; - - if (count < sizeof(int32_t)) - return 0; - - /* Allow sending of packet type followed by data in the next packet. */ - if (count == sizeof(int32_t)) { - if (get_user(saved_type, (int __user *)buf)) - return -EFAULT; - return count; - } else if (saved_type) { - type = saved_type; - saved_type = 0; - } else { - if (get_user(type, (int __user *)buf)) - return -EFAULT; - count -= sizeof(int); - buf += sizeof(int); - } - -#if DEBUG_TRANSPORT > 0 - if (type < STP_MAX_CMD) - _dbug("Got %s. len=%d\n", _stp_command_name[type], (int)count); -#endif - - switch (type) { - case STP_SYMBOLS: - count = _stp_do_symbols(buf, count); - break; - case STP_MODULE: - if (count > 1) - count = _stp_do_module(buf, count); - else { - /* count == 1 indicates end of initial modules list */ - _stp_ctl_send(STP_TRANSPORT, NULL, 0); - } - break; - case STP_EXIT: - _stp_exit_flag = 1; - break; - default: - errk("invalid symbol command type %d\n", type); - return -EINVAL; - } - - return count; -} static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - int type; + u32 type; static int started = 0; - if (count < sizeof(int)) + if (count < sizeof(u32)) return 0; - if (get_user(type, (int __user *)buf)) + if (get_user(type, (u32 __user *)buf)) return -EFAULT; -#if DEBUG_TRANSPORT > 0 + count -= sizeof(u32); + buf += sizeof(u32); + +#ifdef DEBUG_TRANS if (type < STP_MAX_CMD) _dbug("Got %s. len=%d\n", _stp_command_name[type], (int)count); #endif - count -= sizeof(int); - buf += sizeof(int); - switch (type) { + case STP_UNWIND: + _stp_do_unwind_data(buf, count); + break; case STP_START: if (started == 0) { struct _stp_msg_start st; @@ -110,7 +61,7 @@ static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, siz #endif case STP_READY: /* request symbolic information */ - _stp_ask_for_symbols(); + /* _stp_ask_for_symbols(); */ break; default: @@ -121,8 +72,6 @@ static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, siz return count; } -#define STP_CTL_BUFFER_SIZE 256 - struct _stp_buffer { struct list_head list; int len; @@ -131,9 +80,8 @@ struct _stp_buffer { }; static DECLARE_WAIT_QUEUE_HEAD(_stp_ctl_wq); -static DECLARE_WAIT_QUEUE_HEAD(_stp_sym_wq); -#if DEBUG_TRANSPORT > 0 +#ifdef DEBUG_TRANS static void _stp_ctl_write_dbug(int type, void *data, int len) { char buf[64]; @@ -155,20 +103,9 @@ static void _stp_ctl_write_dbug(int type, void *data, int len) case STP_TRANSPORT: _dbug("sending STP_TRANSPORT\n"); break; - default: - _dbug("ERROR: unknown message type: %d\n", type); - break; - } -} -static void _stp_sym_write_dbug(int type, void *data, int len) -{ - switch (type) { - case STP_SYMBOLS: - _dbug("sending STP_SYMBOLS\n"); - break; - case STP_MODULE: - _dbug("sending STP_MODULE\n"); - break; + case STP_UNWIND: + snprintf(buf, sizeof(buf), "%s", (char *)data); + _dbug("sending STP_UNWIND %s [len=%d]\n", buf, len); default: _dbug("ERROR: unknown message type: %d\n", type); break; @@ -181,7 +118,7 @@ static int _stp_ctl_write(int type, void *data, unsigned len) struct _stp_buffer *bptr; unsigned long flags; -#if DEBUG_TRANSPORT > 0 +#ifdef DEBUG_TRANS _stp_ctl_write_dbug(type, data, len); #endif @@ -206,96 +143,19 @@ static int _stp_ctl_write(int type, void *data, unsigned len) return len; } -static int _stp_sym_write(int type, void *data, unsigned len) -{ - struct _stp_buffer *bptr; - unsigned long flags; - -#if DEBUG_TRANSPORT > 0 - _stp_sym_write_dbug(type, data, len); -#endif - - /* make sure we won't overflow the buffer */ - if (unlikely(len > STP_CTL_BUFFER_SIZE)) - return 0; - - /* get a buffer from the free pool */ - bptr = _stp_mempool_alloc(_stp_pool_q); - if (unlikely(bptr == NULL)) - return -1; - - bptr->type = type; - memcpy(bptr->buf, data, len); - bptr->len = len; - - /* put it on the pool of ready buffers */ - spin_lock_irqsave(&_stp_sym_ready_lock, flags); - list_add_tail(&bptr->list, &_stp_sym_ready_q); - spin_unlock_irqrestore(&_stp_sym_ready_lock, flags); - - /* OK, it's queued. Now signal any waiters. */ - wake_up_interruptible(&_stp_sym_wq); - - return len; -} - /* send commands with timeout and retry */ static int _stp_ctl_send(int type, void *data, int len) { int err, trylimit = 50; - kbug(DEBUG_TRANSPORT, "ctl_send: type=%d len=%d\n", type, len); - if (unlikely(type == STP_SYMBOLS || type == STP_MODULE)) { - while ((err = _stp_sym_write(type, data, len)) < 0 && trylimit--) - msleep(5); - } else { - while ((err = _stp_ctl_write(type, data, len)) < 0 && trylimit--) - msleep(5); - if (err > 0) - wake_up_interruptible(&_stp_ctl_wq); - } - kbug(DEBUG_TRANSPORT, "returning %d\n", err); + dbug_trans(1, "ctl_send: type=%d len=%d\n", type, len); + while ((err = _stp_ctl_write(type, data, len)) < 0 && trylimit--) + msleep(5); + if (err > 0) + wake_up_interruptible(&_stp_ctl_wq); + dbug_trans(1, "returning %d\n", err); return err; } -static ssize_t _stp_sym_read_cmd(struct file *file, char __user *buf, size_t count, loff_t *ppos) -{ - struct _stp_buffer *bptr; - int len; - unsigned long flags; - - /* wait for nonempty ready queue */ - spin_lock_irqsave(&_stp_sym_ready_lock, flags); - while (list_empty(&_stp_sym_ready_q)) { - spin_unlock_irqrestore(&_stp_sym_ready_lock, flags); - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - if (wait_event_interruptible(_stp_sym_wq, !list_empty(&_stp_sym_ready_q))) - return -ERESTARTSYS; - spin_lock_irqsave(&_stp_sym_ready_lock, flags); - } - - /* get the next buffer off the ready list */ - bptr = (struct _stp_buffer *)_stp_sym_ready_q.next; - list_del_init(&bptr->list); - spin_unlock_irqrestore(&_stp_sym_ready_lock, flags); - - /* write it out */ - len = bptr->len + 4; - if (len > count || copy_to_user(buf, &bptr->type, len)) { - /* now what? We took it off the queue then failed to send it */ - /* we can't put it back on the queue because it will likely be out-of-order */ - /* fortunately this should never happen */ - /* FIXME need to mark this as a transport failure */ - errk("Supplied buffer too small. count:%d len:%d\n", (int)count, len); - return -EFAULT; - } - - /* put it on the pool of free buffers */ - _stp_mempool_free(bptr); - - return len; -} - static ssize_t _stp_ctl_read_cmd(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct _stp_buffer *bptr; @@ -335,29 +195,10 @@ static ssize_t _stp_ctl_read_cmd(struct file *file, char __user *buf, size_t cou return len; } -static int _stp_sym_opens = 0; -static int _stp_sym_open_cmd(struct inode *inode, struct file *file) -{ - /* only allow one reader */ - if (_stp_sym_opens) - return -1; - - _stp_sym_opens++; - return 0; -} - -static int _stp_sym_close_cmd(struct inode *inode, struct file *file) -{ - if (_stp_sym_opens) - _stp_sym_opens--; - return 0; -} - static int _stp_ctl_open_cmd(struct inode *inode, struct file *file) { if (_stp_attached) return -1; - _stp_attach(); return 0; } @@ -377,16 +218,7 @@ static struct file_operations _stp_ctl_fops_cmd = { .release = _stp_ctl_close_cmd, }; -static struct file_operations _stp_sym_fops_cmd = { - .owner = THIS_MODULE, - .read = _stp_sym_read_cmd, - .write = _stp_sym_write_cmd, - .open = _stp_sym_open_cmd, - .release = _stp_sym_close_cmd, -}; - static struct dentry *_stp_cmd_file = NULL; -static struct dentry *_stp_sym_file = NULL; static int _stp_register_ctl_channel(void) { @@ -400,7 +232,6 @@ static int _stp_register_ctl_channel(void) } INIT_LIST_HEAD(&_stp_ctl_ready_q); - INIT_LIST_HEAD(&_stp_sym_ready_q); /* allocate buffers */ _stp_pool_q = _stp_mempool_init(sizeof(struct _stp_buffer), STP_DEFAULT_BUFFERS); @@ -415,15 +246,9 @@ static int _stp_register_ctl_channel(void) _stp_cmd_file->d_inode->i_uid = _stp_uid; _stp_cmd_file->d_inode->i_gid = _stp_gid; - /* create [debugfs]/systemtap/module_name/.symbols */ - _stp_sym_file = debugfs_create_file(".symbols", 0600, _stp_utt->dir, NULL, &_stp_sym_fops_cmd); - if (_stp_sym_file == NULL) - goto err0; return 0; err0: - if (_stp_cmd_file) - debugfs_remove(_stp_cmd_file); _stp_mempool_destroy(_stp_pool_q); errk("Error creating systemtap debugfs entries.\n"); return -1; @@ -432,16 +257,10 @@ err0: static void _stp_unregister_ctl_channel(void) { struct list_head *p, *tmp; - if (_stp_sym_file) - debugfs_remove(_stp_sym_file); if (_stp_cmd_file) debugfs_remove(_stp_cmd_file); /* Return memory to pool and free it. */ - list_for_each_safe(p, tmp, &_stp_sym_ready_q) { - list_del(p); - _stp_mempool_free(p); - } list_for_each_safe(p, tmp, &_stp_ctl_ready_q) { list_del(p); _stp_mempool_free(p); diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c index 2afea1c9..750e1994 100644 --- a/runtime/transport/procfs.c +++ b/runtime/transport/procfs.c @@ -161,7 +161,7 @@ struct _stp_buffer { struct list_head list; int len; int type; - char buf[STP_BUFFER_SIZE]; + char buf[STP_CTL_BUFFER_SIZE]; }; static DECLARE_WAIT_QUEUE_HEAD(_stp_ctl_wq); diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c index 8c453a55..6406d6ad 100644 --- a/runtime/transport/symbols.c +++ b/runtime/transport/symbols.c @@ -12,8 +12,8 @@ * lib/sort.c of kernel 2.6.22-rc5. It was written by Matt Mackall. */ -#ifndef _SYMBOLS_C_ -#define _SYMBOLS_C_ +#ifndef _STP_SYMBOLS_C_ +#define _STP_SYMBOLS_C_ #include "../sym.h" static char *_stp_symbol_data = NULL; @@ -21,17 +21,12 @@ static int _stp_symbol_state = 0; static char *_stp_module_data = NULL; static int _stp_module_state = 0; - /* these are all the symbol types we are interested in */ static int _stp_sym_type_ok(int type) { - switch (type) { - case 'T': - case 't': + /* we only care about function symbols, which are in the text section */ + if (type == 'T' || type == 't') return 1; - default: - return 0; - } return 0; } @@ -41,10 +36,10 @@ static unsigned _stp_get_sym_sizes(struct module *m, unsigned *dsize) { unsigned int i; unsigned num = 0, datasize = 0; - for (i=0; i < m->num_symtab; i++) { + for (i = 0; i < m->num_symtab; i++) { char *str = (char *)(m->strtab + m->symtab[i].st_name); if (*str != '\0' && _stp_sym_type_ok(m->symtab[i].st_info)) { - datasize += strlen(str)+1; + datasize += strlen(str) + 1; num++; } } @@ -52,19 +47,23 @@ static unsigned _stp_get_sym_sizes(struct module *m, unsigned *dsize) return num; } -/* allocate space for a module and symbols */ -static struct _stp_module * _stp_alloc_module(unsigned num, unsigned datasize, unsigned unwindsize) +/* allocate space for a module, sections, and symbols */ +static struct _stp_module *_stp_alloc_module(unsigned sectsize, unsigned num, unsigned datasize) { struct _stp_module *mod = (struct _stp_module *)_stp_kzalloc(sizeof(struct _stp_module)); if (mod == NULL) goto bad; + mod->sections = (struct _stp_symbol *)_stp_kmalloc(sectsize); + if (mod->sections == NULL) + goto bad; + mod->symbols = (struct _stp_symbol *)_stp_kmalloc(num * sizeof(struct _stp_symbol)); if (mod->symbols == NULL) { mod->symbols = (struct _stp_symbol *)_stp_vmalloc(num * sizeof(struct _stp_symbol)); if (mod->symbols == NULL) goto bad; - mod->allocated = 1; + mod->allocated.symbols = 1; } mod->symbol_data = _stp_kmalloc(datasize); @@ -72,91 +71,63 @@ static struct _stp_module * _stp_alloc_module(unsigned num, unsigned datasize, u mod->symbol_data = _stp_vmalloc(datasize); if (mod->symbol_data == NULL) goto bad; - mod->allocated |= 2; + mod->allocated.symbol_data = 1; } - mod->unwind_data = _stp_kmalloc(unwindsize); - if (mod->unwind_data == NULL) { - mod->unwind_data = _stp_vmalloc(unwindsize); - if (mod->unwind_data == NULL) - goto bad; - mod->allocated |= 4; - } - mod->num_symbols = num; return mod; bad: if (mod) { + if (mod->sections) + _stp_kfree(mod->sections); if (mod->symbols) { - if (mod->allocated & 1) + if (mod->allocated.symbols) _stp_vfree(mod->symbols); else _stp_kfree(mod->symbols); - mod->symbols = NULL; } - if (mod->symbol_data) { - if (mod->allocated & 2) - _stp_vfree(mod->symbol_data); - else - _stp_kfree(mod->symbol_data); - mod->symbol_data = NULL; - } - _stp_kfree(mod); - if (mod->symbols) { - if (mod->allocated & 1) - _stp_vfree(mod->symbols); - else - _stp_kfree(mod->symbols); - mod->symbols = NULL; - } - _stp_kfree(mod); + _stp_kfree(mod); } return NULL; } -static struct _stp_module * _stp_alloc_module_from_module (struct module *m, uint32_t unwind_len) -{ - unsigned datasize, num = _stp_get_sym_sizes(m, &datasize); - return _stp_alloc_module(num, datasize, unwind_len); -} - static void _stp_free_module(struct _stp_module *mod) { /* The module write lock is held. Any prior readers of this */ /* module's data will have read locks and need to finish before */ /* the memory is freed. */ write_lock(&mod->lock); - write_unlock(&mod->lock); /* there will be no more readers */ + write_unlock(&mod->lock); /* there will be no more readers */ - /* free symbol memory */ - if (mod->symbols) { - if (mod->allocated & 1) - _stp_vfree(mod->symbols); - else - _stp_kfree(mod->symbols); - mod->symbols = NULL; - } + /* Free symbol memory */ + /* If symbol_data wasn't allocated, then symbols weren't either. */ if (mod->symbol_data) { - if (mod->allocated & 2) + if (mod->symbols) { + if (mod->allocated.symbols) + _stp_vfree(mod->symbols); + else + _stp_kfree(mod->symbols); + } + if (mod->allocated.symbol_data) _stp_vfree(mod->symbol_data); else _stp_kfree(mod->symbol_data); - mod->symbol_data = NULL; - } if (mod->unwind_data) { - if (mod->allocated & 4) + if (mod->allocated.unwind_data) _stp_vfree(mod->unwind_data); else _stp_kfree(mod->unwind_data); - mod->unwind_data = NULL; - } - if (mod->sections) { - _stp_kfree(mod->sections); - mod->sections = NULL; + if (mod->unwind_hdr) { + if (mod->allocated.unwind_hdr) + _stp_vfree(mod->unwind_hdr); + else + _stp_kfree(mod->unwind_hdr); } + if (mod->sections) + _stp_kfree(mod->sections); /* free module memory */ _stp_kfree(mod); @@ -168,7 +139,7 @@ static void _stp_del_module(struct _stp_module *mod) { int i, num; - // kbug(DEBUG_SYMBOLS, "deleting %s\n", mod->name); + dbug_sym(1, "deleting module %s\n", mod->name); /* signal relocation code to clear its cache */ _stp_module_relocate((char *)-1, NULL, 0); @@ -181,15 +152,15 @@ static void _stp_del_module(struct _stp_module *mod) if (num >= _stp_num_modules) return; - for (i = num; i < _stp_num_modules-1; i++) - _stp_modules[i] = _stp_modules[i+1]; + for (i = num; i < _stp_num_modules - 1; i++) + _stp_modules[i] = _stp_modules[i + 1]; for (num = 0; num < _stp_num_modules; num++) { if (_stp_modules_by_addr[num] == mod) break; } - for (i = num; i < _stp_num_modules-1; i++) - _stp_modules_by_addr[i] = _stp_modules_by_addr[i+1]; + for (i = num; i < _stp_num_modules - 1; i++) + _stp_modules_by_addr[i] = _stp_modules_by_addr[i + 1]; _stp_num_modules--; @@ -197,10 +168,8 @@ static void _stp_del_module(struct _stp_module *mod) } static void _stp_free_modules(void) -{ +{ int i; - unsigned long flags; - /* This only happens when the systemtap module unloads */ /* so there is no need for locks. */ for (i = _stp_num_modules - 1; i >= 0; i--) @@ -208,82 +177,120 @@ static void _stp_free_modules(void) } static unsigned long _stp_kallsyms_lookup_name(const char *name); +static void _stp_create_unwind_hdr(struct _stp_module *m); + +extern unsigned _stp_num_kernel_symbols; +extern struct _stp_symbol _stp_kernel_symbols[]; -/* process the KERNEL symbols */ -static int _stp_do_symbols(const char __user *buf, int count) +/* initialize the kernel symbols */ +static int _stp_init_kernel_symbols(void) { - struct _stp_symbol *s; - unsigned datasize, num, unwindsize; + _stp_modules[0] = (struct _stp_module *)_stp_kzalloc(sizeof(struct _stp_module)); + if (_stp_modules[0] == NULL) { + errk("cannot allocate memory\n"); + return -EFAULT; + } + _stp_modules[0]->symbols = _stp_kernel_symbols; + _stp_modules[0]->num_symbols = _stp_num_kernel_symbols; + rwlock_init(&_stp_modules[0]->lock); + _stp_num_modules = 1; + + /* Note: this mapping is used by kernel/_stext pseudo-relocations. */ + _stp_modules[0]->text = _stp_kallsyms_lookup_name("_stext"); + _stp_modules[0]->data = _stp_kallsyms_lookup_name("_etext"); + _stp_modules[0]->text_size = _stp_modules[0]->data - _stp_modules[0]->text; + _stp_modules_by_addr[0] = _stp_modules[0]; + return 0; +} + +static void _stp_do_unwind_data(const char __user *buf, size_t count) +{ + u64 unwind_len; + unsigned long flags; + char name[STP_MODULE_NAME_LEN]; int i; + struct _stp_module *m; - switch (_stp_symbol_state) { - case 0: - if (count != sizeof(struct _stp_msg_symbol_hdr)) { - errk("count=%d\n", count); - return -EFAULT; - } - if (get_user(num, (unsigned __user *)buf)) - return -EFAULT; - if (get_user(datasize, (unsigned __user *)(buf+4))) - return -EFAULT; - if (get_user(unwindsize, (unsigned __user *)(buf+8))) - return -EFAULT; - dbug(DEBUG_UNWIND, "num=%d datasize=%d unwindsize=%d\n", num, datasize, unwindsize); - - _stp_modules[0] = _stp_alloc_module(num, datasize, unwindsize); - if (_stp_modules[0] == NULL) { - errk("cannot allocate memory\n"); - return -EFAULT; + dbug_unwind(1, "got unwind data, count=%d\n", count); + + if (count < STP_MODULE_NAME_LEN + sizeof(u64)) { + dbug_unwind(1, "unwind message too short\n"); + return; + } + if (strncpy_from_user(name, buf, STP_MODULE_NAME_LEN) < 0) { + errk("userspace copy failed\n"); + return; + } + dbug_unwind(1, "name=%s\n", name); + if (!strcmp(name,"*")) { + /* OK, all initial unwind data received. Ready to go. */ + _stp_ctl_send(STP_TRANSPORT, NULL, 0); + return; + } + count -= STP_MODULE_NAME_LEN; + buf += STP_MODULE_NAME_LEN; + + if (get_user(unwind_len, (u64 __user *)buf)) { + errk("userspace copy failed\n"); + return; + } + count -= sizeof(u64); + buf += sizeof(u64); + if (count != unwind_len) { + dbug_unwind(1, "count=%d unwind_len=%d\n", (int)count, (int)unwind_len); + return; + } + + STP_RLOCK_MODULES; + for (i = 0; i < _stp_num_modules; i++) { + if (strcmp(name, _stp_modules[i]->name) == 0) + break; + } + if (unlikely(i == _stp_num_modules)) { + dbug_unwind(1, "module %s not found!\n", name); + STP_RUNLOCK_MODULES; + return; + } + m = _stp_modules[i]; + write_lock(&m->lock); + STP_RUNLOCK_MODULES; + + /* allocate space for unwind data */ + m->unwind_data = _stp_kmalloc(count); + if (unlikely(m->unwind_data == NULL)) { + m->unwind_data = _stp_vmalloc(count); + if (m->unwind_data == NULL) { + errk("kmalloc failed\n"); + goto done; } - rwlock_init(&_stp_modules[0]->lock); - _stp_symbol_state = 1; - break; - case 1: - dbug(DEBUG_SYMBOLS, "got stap_symbols, count=%d\n", count); - if (copy_from_user ((char *)_stp_modules[0]->symbols, buf, count)) - return -EFAULT; - _stp_symbol_state = 2; - break; - case 2: - dbug(DEBUG_SYMBOLS, "got symbol data, count=%d buf=%p\n", count, buf); - if (copy_from_user (_stp_modules[0]->symbol_data, buf, count)) - return -EFAULT; - _stp_num_modules = 1; - - s = _stp_modules[0]->symbols; - for (i = 0; i < _stp_modules[0]->num_symbols; i++) - s[i].symbol += (long)_stp_modules[0]->symbol_data; - - _stp_symbol_state = 3; - /* NB: this mapping is used by kernel/_stext pseudo-relocations. */ - _stp_modules[0]->text = _stp_kallsyms_lookup_name("_stext"); - _stp_modules[0]->data = _stp_kallsyms_lookup_name("_etext"); - _stp_modules[0]->text_size = _stp_modules[0]->data - _stp_modules[0]->text; - _stp_modules_by_addr[0] = _stp_modules[0]; - dbug(DEBUG_SYMBOLS, "Got kernel symbols. text=%p len=%u\n", - (int64_t)_stp_modules[0]->text, _stp_modules[0]->text_size); - break; - case 3: - dbug(DEBUG_UNWIND, "got unwind data, count=%d\n", count); - _stp_symbol_state = 4; - if (copy_from_user (_stp_modules[0]->unwind_data, buf, count)) { - _dbug("cfu failed\n"); - return -EFAULT; + m->allocated.unwind_data = 1; + } + + if (unlikely(copy_from_user(m->unwind_data, buf, count))) { + errk("userspace copy failed\n"); + if (m->unwind_data) { + if (m->allocated.unwind_data) + _stp_vfree(m->unwind_data); + else + _stp_kfree(m->unwind_data); + m->unwind_data = NULL; } - _stp_modules[0]->unwind_data_len = count; - break; - default: - errk("unexpected symbol data of size %d.\n", count); + goto done; } - return count; + m->unwind_data_len = count; + _stp_create_unwind_hdr(m); +done: + write_unlock(&m->lock); } static int _stp_compare_addr(const void *p1, const void *p2) { struct _stp_symbol *s1 = (struct _stp_symbol *)p1; struct _stp_symbol *s2 = (struct _stp_symbol *)p2; - if (s1->addr == s2->addr) return 0; - if (s1->addr < s2->addr) return -1; + if (s1->addr == s2->addr) + return 0; + if (s1->addr < s2->addr) + return -1; return 1; } @@ -332,18 +339,17 @@ static void generic_swap(void *a, void *b, int size) * it less suitable for kernel use. */ void _stp_sort(void *base, size_t num, size_t size, - int (*cmp)(const void *, const void *), - void (*swap)(void *, void *, int size)) + int (*cmp) (const void *, const void *), void (*swap) (void *, void *, int size)) { /* pre-scale counters for performance */ - int i = (num/2 - 1) * size, n = num * size, c, r; + int i = (num / 2 - 1) * size, n = num * size, c, r; if (!swap) swap = (size == 4 ? u32_swap : generic_swap); /* heapify */ - for ( ; i >= 0; i -= size) { - for (r = i; r * 2 + size < n; r = c) { + for (; i >= 0; i -= size) { + for (r = i; r * 2 + size < n; r = c) { c = r * 2 + size; if (c < n - size && cmp(base + c, base + c + size) < 0) c += size; @@ -367,65 +373,114 @@ void _stp_sort(void *base, size_t num, size_t size, } } +/* filter out section names we don't care about */ +static int _stp_section_is_interesting(const char *name) +{ + int ret = 1; + if (!strncmp("__", name, 2) + || !strncmp(".note", name, 5) + || !strncmp(".gnu", name, 4) + || !strncmp(".mod", name, 4)) + ret = 0; + return ret; +} + /* Create a new _stp_module and load the symbols */ -static struct _stp_module *_stp_load_module_symbols (struct _stp_module *imod, uint32_t unwind_len) +static struct _stp_module *_stp_load_module_symbols(struct module *mod) { - unsigned i, num=0; - struct module *m = (struct module *)imod->module; - struct _stp_module *mod = NULL; - char *dataptr; + int i, num, overflow = 0; + struct module_sect_attrs *sa; + unsigned sect_size = 0, sect_num = 0, sym_size, sym_num; + struct _stp_module *sm; + char *dataptr, *endptr; + + sa = mod->sect_attrs; + /* calculate how much space to allocate for section strings */ + for (i = 0; i < sa->nsections; i++) { + if (_stp_section_is_interesting(sa->attrs[i].name)) { + sect_num++; + sect_size += strlen(sa->attrs[i].name) + 1; + dbug_sym(2, "\t%s\t%lx\n", sa->attrs[i].name, sa->attrs[i].address); + } + } + sect_size += sect_num * sizeof(struct _stp_symbol); + + /* and how much space for symbols */ + sym_num = _stp_get_sym_sizes(mod, &sym_size); - if (m == NULL) { - kbug(DEBUG_SYMBOLS, "imod->module is NULL\n"); + sm = _stp_alloc_module(sect_size, sym_num, sym_size); + if (!sm) { + errk("failed to allocate memory for module.\n"); return NULL; } - if (try_module_get(m)) { - mod = _stp_alloc_module_from_module(m, unwind_len); - if (mod == NULL) { - module_put(m); - errk("failed to allocate memory for module.\n"); - return NULL; - } + strlcpy(sm->name, mod->name, STP_MODULE_NAME_LEN); + sm->module = (unsigned long)mod; + sm->text = (unsigned long)mod->module_core; + sm->text_size = mod->core_text_size; + sm->data = 0; /* fixme */ + sm->num_sections = sect_num; + rwlock_init(&sm->lock); - strlcpy(mod->name, imod->name, STP_MODULE_NAME_LEN); - mod->module = imod->module; - mod->text = imod->text; - mod->data = imod->data; - mod->num_sections = imod->num_sections; - mod->sections = imod->sections; - mod->text_size = m->core_text_size; - rwlock_init(&mod->lock); - - /* now copy all the symbols we are interested in */ - dataptr = mod->symbol_data; - for (i=0; i < m->num_symtab; i++) { - char *str = (char *)(m->strtab + m->symtab[i].st_name); - if (*str != '\0' && _stp_sym_type_ok(m->symtab[i].st_info)) { - mod->symbols[num].symbol = dataptr; - mod->symbols[num].addr = m->symtab[i].st_value; - while (*str) *dataptr++ = *str++; - *dataptr++ = 0; - num++; + /* copy in section data */ + dataptr = (char *)((long)sm->sections + sect_num * sizeof(struct _stp_symbol)); + endptr = (char *)((long)sm->sections + sect_size); + num = 0; + for (i = 0; i < sa->nsections; i++) { + size_t len, maxlen; + if (_stp_section_is_interesting(sa->attrs[i].name)) { + sm->sections[num].addr = sa->attrs[i].address; + sm->sections[num].symbol = dataptr; + maxlen = (size_t) (endptr - dataptr); + len = strlcpy(dataptr, sa->attrs[i].name, maxlen); + if (unlikely(len >= maxlen)) { + _dbug("dataptr=%lx endptr=%lx len=%d maxlen=%d\n", dataptr, endptr, len, maxlen); + overflow = 1; } + dataptr += len + 1; + num++; } - module_put(m); + } + if (unlikely(overflow)) { + errk("Section names truncated!!! Should never happen!!\n"); + *endptr = 0; + overflow = 0; + } - /* sort symbols by address */ - _stp_sort (mod->symbols, num, sizeof(struct _stp_symbol), _stp_compare_addr, _stp_swap_symbol); + /* now copy all the symbols we are interested in */ + dataptr = sm->symbol_data; + endptr = dataptr + sym_size - 1; + num = 0; + for (i = 0; i < mod->num_symtab; i++) { + char *str = (char *)(mod->strtab + mod->symtab[i].st_name); + if (*str != '\0' && _stp_sym_type_ok(mod->symtab[i].st_info)) { + sm->symbols[num].symbol = dataptr; + sm->symbols[num].addr = mod->symtab[i].st_value; + while (*str && (dataptr < endptr)) + *dataptr++ = *str++; + if (unlikely(*str)) + overflow = 1; + *dataptr++ = 0; + num++; + } } - return mod; + if (unlikely(overflow)) + errk("Symbol names truncated!!! Should never happen!!\n"); + + /* sort symbols by address */ + _stp_sort(sm->symbols, num, sizeof(struct _stp_symbol), _stp_compare_addr, _stp_swap_symbol); + + return sm; } -/* Remove any old module info from our database */ -static void _stp_module_exists_delete (struct _stp_module *mod) +/* Remove any old module info from our database. */ +static void _stp_module_exists_delete(struct _stp_module *mod) { int i, num; - /* remove any old modules with the same name */ for (num = 1; num < _stp_num_modules; num++) { if (strcmp(_stp_modules[num]->name, mod->name) == 0) { - dbug(DEBUG_SYMBOLS, "found existing module with name %s. Deleting.\n", mod->name); + dbug_sym(1, "found existing module with name %s. Deleting.\n", mod->name); _stp_del_module(_stp_modules[num]); break; } @@ -435,143 +490,61 @@ static void _stp_module_exists_delete (struct _stp_module *mod) for (num = 1; num < _stp_num_modules; num++) { if (mod->text + mod->text_size < _stp_modules_by_addr[num]->text) continue; - if (mod->text < _stp_modules_by_addr[num]->text - + _stp_modules_by_addr[num]->text_size) { - dbug(DEBUG_SYMBOLS, "New module %s overlaps with old module %s. Deleting old.\n", - mod->name, _stp_modules_by_addr[num]->name); + if (mod->text < _stp_modules_by_addr[num]->text + _stp_modules_by_addr[num]->text_size) { + dbug_sym(1, "New module %s overlaps with old module %s. Deleting old.\n", + mod->name, _stp_modules_by_addr[num]->name); _stp_del_module(_stp_modules_by_addr[num]); } } } -static int _stp_ins_module(struct _stp_module *mod) +static void _stp_ins_module(struct module *mod) { - int i, num, res, ret = 0; + int i, num, res; unsigned long flags; - - // kbug(DEBUG_SYMBOLS, "insert %s\n", mod->name); + struct _stp_module *m; + dbug_sym(1, "insert %s\n", mod->name); + m = _stp_load_module_symbols(mod); + if (m == NULL) + return; STP_WLOCK_MODULES; - - _stp_module_exists_delete(mod); - + _stp_module_exists_delete(m); /* check for overflow */ if (_stp_num_modules == STP_MAX_MODULES) { errk("Exceeded the limit of %d modules\n", STP_MAX_MODULES); - ret = -ENOMEM; goto done; } - + /* insert alphabetically in _stp_modules[] */ for (num = 1; num < _stp_num_modules; num++) - if (strcmp(_stp_modules[num]->name, mod->name) > 0) + if (strcmp(_stp_modules[num]->name, m->name) > 0) break; for (i = _stp_num_modules; i > num; i--) - _stp_modules[i] = _stp_modules[i-1]; - _stp_modules[num] = mod; - + _stp_modules[i] = _stp_modules[i - 1]; + _stp_modules[num] = m; /* insert by text address in _stp_modules_by_addr[] */ for (num = 1; num < _stp_num_modules; num++) - if (mod->text < _stp_modules_by_addr[num]->text) + if (m->text < _stp_modules_by_addr[num]->text) break; for (i = _stp_num_modules; i > num; i--) - _stp_modules_by_addr[i] = _stp_modules_by_addr[i-1]; - _stp_modules_by_addr[num] = mod; - + _stp_modules_by_addr[i] = _stp_modules_by_addr[i - 1]; + _stp_modules_by_addr[num] = m; _stp_num_modules++; - done: STP_WUNLOCK_MODULES; - return ret; + return; } - -/* Called from procfs.c when a STP_MODULE msg is received */ -static int _stp_do_module(const char __user *buf, int count) -{ - struct _stp_msg_module tmpmod; - struct _stp_module mod, *m; - unsigned i, section_len; - - if (count < (int)sizeof(tmpmod)) { - errk("expected %d and got %d\n", (int)sizeof(tmpmod), count); - return -EFAULT; - } - if (copy_from_user ((char *)&tmpmod, buf, sizeof(tmpmod))) - return -EFAULT; - - section_len = count - sizeof(tmpmod) - tmpmod.unwind_len; - if (section_len <= 0) { - errk("section_len = %d\n", section_len); - return -EFAULT; - } - dbug(DEBUG_SYMBOLS, "Got module %s, count=%d section_len=%d unwind_len=%d\n", - tmpmod.name, count, section_len, tmpmod.unwind_len); - - strcpy(mod.name, tmpmod.name); - mod.module = tmpmod.module; - mod.text = tmpmod.text; - mod.data = tmpmod.data; - mod.num_sections = tmpmod.num_sections; - - /* copy in section data */ - mod.sections = _stp_kmalloc(section_len); - if (mod.sections == NULL) { - errk("unable to allocate memory.\n"); - return -EFAULT; - } - if (copy_from_user ((char *)mod.sections, buf+sizeof(tmpmod), section_len)) { - _stp_kfree(mod.sections); - return -EFAULT; - } - for (i = 0; i < mod.num_sections; i++) { - mod.sections[i].symbol = - (char *)((long)mod.sections[i].symbol - + (long)((long)mod.sections + mod.num_sections * sizeof(struct _stp_symbol))); - } - - #if 0 - for (i = 0; i < mod.num_sections; i++) - _dbug("section %d (stored at %p): %s %lx\n", i, &mod.sections[i], mod.sections[i].symbol, mod.sections[i].addr); - #endif - - /* load symbols from tmpmod.module to mod */ - m = _stp_load_module_symbols(&mod, tmpmod.unwind_len); - if (m == NULL) { - _stp_kfree(mod.sections); - return 0; - } - - dbug(DEBUG_SYMBOLS, "module %s loaded. Text=%p text_size=%u\n", m->name, (int64_t)m->text, m->text_size); - /* finally copy unwind info */ - if (copy_from_user (m->unwind_data, buf+sizeof(tmpmod)+section_len, tmpmod.unwind_len)) { - _stp_free_module(m); - _stp_kfree(mod.sections); - return -EFAULT; - } - m->unwind_data_len = tmpmod.unwind_len; - - if (_stp_ins_module(m) < 0) { - _stp_free_module(m); - return -ENOMEM; - } - - return count; -} - -static int _stp_ctl_send (int type, void *data, int len); - -static int _stp_module_load_notify(struct notifier_block * self, unsigned long val, void * data) +static int _stp_module_load_notify(struct notifier_block *self, unsigned long val, void *data) { struct module *mod = (struct module *)data; struct _stp_module rmod; - switch (val) { case MODULE_STATE_COMING: - dbug(DEBUG_SYMBOLS, "module %s load notify\n", mod->name); - strlcpy(rmod.name, mod->name, STP_MODULE_NAME_LEN); - _stp_ctl_send(STP_MODULE, &rmod, sizeof(struct _stp_module)); + dbug_sym(1, "module %s load notify\n", mod->name); + _stp_ins_module(mod); break; default: errk("module loaded? val=%ld\n", val); @@ -583,4 +556,63 @@ static struct notifier_block _stp_module_load_nb = { .notifier_call = _stp_module_load_notify, }; -#endif /* _SYMBOLS_C_ */ +#include <linux/seq_file.h> +extern unsigned long _stp_modules_op; /* from stap */ +static int _stp_init_modules(void) +{ + loff_t pos = 0; + void *res; + struct module *mod; + + const struct seq_operations *modules_op = (const struct seq_operations *)_stp_modules_op; + /* Use the seq_file interface to safely get a list of installed modules */ + res = modules_op->start(NULL, &pos); + while (res) { + mod = list_entry(res, struct module, list); + _stp_ins_module(mod); + res = modules_op->next(NULL, res, &pos); + } + + if (register_module_notifier(&_stp_module_load_nb)) + errk("failed to load module notifier\n"); + + /* unlocks the list */ + modules_op->stop(NULL, NULL); + +#ifndef CONFIG_FRAME_POINTER + /* now that we have all the modules, ask for their unwind info */ + { + unsigned long flags; + int i, left = STP_CTL_BUFFER_SIZE; + char buf[STP_CTL_BUFFER_SIZE]; + char *ptr = buf; + *ptr = 0; + + STP_RLOCK_MODULES; + /* Loop through modules, sending module names packed into */ + /* messages of size STP_CTL_BUFFER. */ + for (i = 0; i < _stp_num_modules; i++) { + char *name = _stp_modules[i]->name; + int len = strlen(name); + if (len >= left) { + _stp_ctl_send(STP_UNWIND, buf, sizeof(buf) - left); + ptr = buf; + left = STP_CTL_BUFFER_SIZE; + } + strlcpy(ptr, name, left); + ptr += len + 1; + left -= len + 1; + } + STP_RUNLOCK_MODULES; + + /* Send terminator. When we get this back from stapio */ + /* that means all the unwind info has been sent. */ + strlcpy(ptr, "*", left); + left -= 2; + _stp_ctl_send(STP_UNWIND, buf, sizeof(buf) - left); + } +#endif + return 0; +} + +#endif /* _STP_SYMBOLS_C_ */ diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index 8335e44b..aa96a50e 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -23,83 +23,47 @@ #include "../procfs.c" static struct utt_trace *_stp_utt = NULL; - +static unsigned int utt_seq = 1; +static int _stp_probes_started = 0; +pid_t _stp_target = 0; +static int _stp_exit_called = 0; +int _stp_exit_flag = 0; #ifdef STP_OLD_TRANSPORT #include "relayfs.c" +#include "procfs.c" #else #include "utt.c" +#include "control.c" #endif -static unsigned int utt_seq = 1; - -static int _stp_probes_started = 0; - /* module parameters */ static int _stp_bufsize; module_param(_stp_bufsize, int, 0); MODULE_PARM_DESC(_stp_bufsize, "buffer size"); -pid_t _stp_target = 0; -static int _stp_exit_called = 0; -int _stp_exit_flag = 0; - /* forward declarations */ void probe_exit(void); int probe_start(void); void _stp_exit(void); -void _stp_handle_start (struct _stp_msg_start *st); -static void _stp_detach(void); -static void _stp_attach(void); /* check for new workqueue API */ -#ifdef DECLARE_DELAYED_WORK -static void _stp_work_queue (struct work_struct *data); +#ifdef DECLARE_DELAYED_WORK +static void _stp_work_queue(struct work_struct *data); static DECLARE_DELAYED_WORK(_stp_work, _stp_work_queue); #else -static void _stp_work_queue (void *data); +static void _stp_work_queue(void *data); static DECLARE_WORK(_stp_work, _stp_work_queue, NULL); #endif static struct workqueue_struct *_stp_wq; -static void _stp_ask_for_symbols(void); - -#ifdef STP_OLD_TRANSPORT -#include "procfs.c" -#else -#include "control.c" -#endif - -static void _stp_ask_for_symbols(void) -{ - struct _stp_msg_symbol req; - struct _stp_module mod; - static int sent_symbols = 0; - - if (sent_symbols == 0) { - /* ask for symbols and modules */ - kbug(DEBUG_SYMBOLS|DEBUG_TRANSPORT, "AFS\n"); - - req.endian = 0x1234; - req.ptr_size = sizeof(char *); - _stp_ctl_send(STP_SYMBOLS, &req, sizeof(req)); - - strcpy(mod.name, ""); - _stp_ctl_send(STP_MODULE, &mod, sizeof(mod)); - sent_symbols = 1; - } -} /* * _stp_handle_start - handle STP_START */ -void _stp_handle_start (struct _stp_msg_start *st) +void _stp_handle_start(struct _stp_msg_start *st) { - kbug (DEBUG_TRANSPORT, "stp_handle_start\n"); - - if (register_module_notifier(&_stp_module_load_nb)) - errk("failed to load module notifier\n"); - + dbug_trans(1, "stp_handle_start\n"); _stp_target = st->target; st->res = probe_start(); if (st->res >= 0) @@ -108,16 +72,15 @@ void _stp_handle_start (struct _stp_msg_start *st) _stp_ctl_send(STP_START, st, sizeof(*st)); } - /* common cleanup code. */ /* This is called from the kernel thread when an exit was requested */ /* by staprun or the exit() function. It is also called by transport_close() */ /* when the module is removed. In that case "dont_rmmod" is set to 1. */ /* We need to call it both times because we want to clean up properly */ /* when someone does /sbin/rmmod on a loaded systemtap module. */ -static void _stp_cleanup_and_exit (int dont_rmmod) +static void _stp_cleanup_and_exit(int dont_rmmod) { - kbug(DEBUG_TRANSPORT, "cleanup_and_exit (%d)\n", dont_rmmod); + dbug_trans(1, "cleanup_and_exit (%d)\n", dont_rmmod); if (!_stp_exit_called) { int failures; @@ -128,23 +91,24 @@ static void _stp_cleanup_and_exit (int dont_rmmod) _stp_exit_called = 1; if (_stp_probes_started) { - kbug(DEBUG_TRANSPORT, "calling probe_exit\n"); + dbug_trans(1, "calling probe_exit\n"); /* tell the stap-generated code to unload its probes, etc */ probe_exit(); - kbug(DEBUG_TRANSPORT, "done with probe_exit\n"); + dbug_trans(1, "done with probe_exit\n"); } failures = atomic_read(&_stp_transport_failures); if (failures) - _stp_warn ("There were %d transport failures.\n", failures); + _stp_warn("There were %d transport failures.\n", failures); - kbug(DEBUG_TRANSPORT, "************** calling startstop 0 *************\n"); - if (_stp_utt) utt_trace_startstop(_stp_utt, 0, &utt_seq); + dbug_trans(1, "************** calling startstop 0 *************\n"); + if (_stp_utt) + utt_trace_startstop(_stp_utt, 0, &utt_seq); - kbug(DEBUG_TRANSPORT, "ctl_send STP_EXIT\n"); + dbug_trans(1, "ctl_send STP_EXIT\n"); /* tell staprun to exit (if it is still there) */ _stp_ctl_send(STP_EXIT, &dont_rmmod, sizeof(int)); - kbug(DEBUG_TRANSPORT, "done with ctl_send STP_EXIT\n"); + dbug_trans(1, "done with ctl_send STP_EXIT\n"); } } @@ -153,7 +117,7 @@ static void _stp_cleanup_and_exit (int dont_rmmod) */ static void _stp_detach(void) { - kbug(DEBUG_TRANSPORT, "detach\n"); + dbug_trans(1, "detach\n"); _stp_attached = 0; _stp_pid = 0; @@ -169,10 +133,10 @@ static void _stp_detach(void) */ static void _stp_attach(void) { - kbug(DEBUG_TRANSPORT, "attach\n"); + dbug_trans(1, "attach\n"); _stp_attached = 1; _stp_pid = current->pid; - utt_set_overwrite(0); + utt_set_overwrite(0); queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER); } @@ -180,10 +144,10 @@ static void _stp_attach(void) * _stp_work_queue - periodically check for IO or exit * This is run by a kernel thread and may sleep. */ -#ifdef DECLARE_DELAYED_WORK -static void _stp_work_queue (struct work_struct *data) +#ifdef DECLARE_DELAYED_WORK +static void _stp_work_queue(struct work_struct *data) #else -static void _stp_work_queue (void *data) +static void _stp_work_queue(void *data) #endif { int do_io = 0; @@ -211,19 +175,19 @@ static void _stp_work_queue (void *data) */ void _stp_transport_close() { - kbug(DEBUG_TRANSPORT, "%d: ************** transport_close *************\n", current->pid); + dbug_trans(1, "%d: ************** transport_close *************\n", current->pid); _stp_cleanup_and_exit(1); destroy_workqueue(_stp_wq); _stp_unregister_ctl_channel(); - if (_stp_utt) utt_trace_remove(_stp_utt); + if (_stp_utt) + utt_trace_remove(_stp_utt); _stp_free_modules(); _stp_kill_time(); - _stp_print_cleanup(); /* free print buffers */ + _stp_print_cleanup(); /* free print buffers */ _stp_mem_debug_done(); - kbug(DEBUG_TRANSPORT, "---- CLOSED ----\n"); + dbug_trans(1, "---- CLOSED ----\n"); } - static struct utt_trace *_stp_utt_open(void) { struct utt_trace_setup utts; @@ -249,22 +213,22 @@ int _stp_transport_init(void) { int ret; - kbug(DEBUG_TRANSPORT, "transport_init\n"); + dbug_trans(1, "transport_init\n"); _stp_init_pid = current->pid; _stp_uid = current->uid; _stp_gid = current->gid; #ifdef RELAY_GUEST - /* Guest scripts use relay only for reporting warnings and errors */ - _stp_subbuf_size = 65536; - _stp_nsubbufs = 2; + /* Guest scripts use relay only for reporting warnings and errors */ + _stp_subbuf_size = 65536; + _stp_nsubbufs = 2; #endif if (_stp_bufsize) { unsigned size = _stp_bufsize * 1024 * 1024; _stp_subbuf_size = ((size >> 2) + 1) * 65536; _stp_nsubbufs = size / _stp_subbuf_size; - kbug(DEBUG_TRANSPORT, "Using %d subbufs of size %d\n", _stp_nsubbufs, _stp_subbuf_size); + dbug_trans(1, "Using %d subbufs of size %d\n", _stp_nsubbufs, _stp_subbuf_size); } /* initialize timer code */ @@ -286,41 +250,57 @@ int _stp_transport_init(void) if (_stp_print_init() < 0) goto err2; + /* start transport */ utt_trace_startstop(_stp_utt, 1, &utt_seq); /* create workqueue of kernel threads */ _stp_wq = create_workqueue("systemtap"); if (!_stp_wq) goto err3; + + _stp_transport_state = 1; + + dbug_trans(1, "calling init_kernel_symbols\n"); + if (_stp_init_kernel_symbols() < 0) + goto err4; + + dbug_trans(1, "calling init_modules\n"); + if (_stp_init_modules() < 0) + goto err4; + return 0; +err4: + errk("failed to initialize modules\n"); + _stp_free_modules(); + destroy_workqueue(_stp_wq); err3: _stp_print_cleanup(); err2: _stp_unregister_ctl_channel(); err1: - if (_stp_utt) utt_trace_remove(_stp_utt); + if (_stp_utt) + utt_trace_remove(_stp_utt); err0: _stp_kill_time(); return -1; } - static inline void _stp_lock_inode(struct inode *inode) { #ifdef DEFINE_MUTEX - mutex_lock(&inode->i_mutex); + mutex_lock(&inode->i_mutex); #else - down(&inode->i_sem); + down(&inode->i_sem); #endif } static inline void _stp_unlock_inode(struct inode *inode) { #ifdef DEFINE_MUTEX - mutex_unlock(&inode->i_mutex); + mutex_unlock(&inode->i_mutex); #else - up(&inode->i_sem); + up(&inode->i_sem); #endif } @@ -358,7 +338,8 @@ static void _stp_unlock_debugfs(void) /* utt.c and relayfs.c. Will not be necessary if utt is included */ /* in the kernel. */ -static struct dentry *_stp_get_root_dir(const char *name) { +static struct dentry *_stp_get_root_dir(const char *name) +{ struct file_system_type *fs; struct dentry *root; struct super_block *sb; @@ -377,7 +358,6 @@ static struct dentry *_stp_get_root_dir(const char *name) { errk("Couldn't lock transport directory.\n"); return NULL; } - #ifdef STP_OLD_TRANSPORT root = relayfs_create_dir(name, NULL); #else @@ -389,12 +369,12 @@ static struct dentry *_stp_get_root_dir(const char *name) { _stp_lock_inode(sb->s_root->d_inode); root = lookup_one_len(name, sb->s_root, strlen(name)); _stp_unlock_inode(sb->s_root->d_inode); - kbug(DEBUG_TRANSPORT, "root=%p\n", root); + errk("ERROR: root=%p\n", root); if (!IS_ERR(root)) dput(root); else { root = NULL; - kbug(DEBUG_TRANSPORT, "Could not create or find transport directory.\n"); + errk("Could not create or find transport directory.\n"); } } _stp_unlock_debugfs(); diff --git a/runtime/transport/transport.h b/runtime/transport/transport.h index 6dc00d2b..dc499961 100644 --- a/runtime/transport/transport.h +++ b/runtime/transport/transport.h @@ -7,21 +7,37 @@ #include "transport_msgs.h" -void _stp_warn (const char *fmt, ...); - +/* The size of print buffers. This limits the maximum */ +/* amount of data a print can send. */ #define STP_BUFFER_SIZE 8192 +/* STP_CTL_BUFFER_SIZE is the maximum size of a message */ +/* exchanged on the control channel. */ +#ifdef STP_OLD_TRANSPORT +/* Old transport sends print output on control channel */ +#define STP_CTL_BUFFER_SIZE STP_BUFFER_SIZE +#else +#define STP_CTL_BUFFER_SIZE 256 +#endif + /* how often the work queue wakes up and checks buffers */ #define STP_WORK_TIMER (HZ/100) static unsigned _stp_nsubbufs = 8; static unsigned _stp_subbuf_size = 65536*4; + +void _stp_warn (const char *fmt, ...); extern void _stp_transport_close(void); extern int _stp_print_init(void); extern void _stp_print_cleanup(void); static struct dentry *_stp_get_root_dir(const char *name); static int _stp_lock_debugfs(void); static void _stp_unlock_debugfs(void); +static int _stp_ctl_send(int type, void *data, int len); +static void _stp_attach(void); +static void _stp_detach(void); +void _stp_handle_start(struct _stp_msg_start *st); + int _stp_pid = 0; uid_t _stp_uid = 0; gid_t _stp_gid = 0; diff --git a/runtime/transport/transport_msgs.h b/runtime/transport/transport_msgs.h index 55de2d4a..0e65b63a 100644 --- a/runtime/transport/transport_msgs.h +++ b/runtime/transport/transport_msgs.h @@ -23,8 +23,7 @@ enum STP_EXIT, STP_OOB_DATA, STP_SYSTEM, - STP_SYMBOLS, - STP_MODULE, + STP_UNWIND, STP_TRANSPORT, STP_CONNECT, STP_DISCONNECT, @@ -36,18 +35,16 @@ enum STP_SUBBUFS_CONSUMED, STP_REALTIME_DATA, #endif - STP_MAX_CMD }; -#ifdef DEBUG_TRANSPORT +#ifdef DEBUG_TRANS static const char *_stp_command_name[] = { "STP_START", "STP_EXIT", "STP_OOB_DATA", "STP_SYSTEM", - "STP_SYMBOLS", - "STP_MODULE", + "STP_UNWIND", "STP_TRANSPORT", "STP_CONNECT", "STP_DISCONNECT", @@ -59,68 +56,34 @@ static const char *_stp_command_name[] = { "STP_REALTIME_DATA", #endif }; -#endif /* DEBUG_TRANSPORT */ +#endif /* DEBUG_TRANS */ /* control channel messages */ -/* command to execute: sent to staprun */ +/* command to execute: module->stapio */ struct _stp_msg_cmd { char cmd[128]; }; -/* request for symbol data. sent to staprun */ -struct _stp_msg_symbol +/* Unwind data. stapio->module */ +struct _stp_msg_unwind { - int32_t endian; - int32_t ptr_size; + /* the module name, or "*" for all */ + char name[STP_MODULE_NAME_LEN]; + /* length of unwind data */ + uint64_t unwind_len; + /* data ...*/ }; /* Request to start probes. */ -/* Sent from staprun. Then returned from module. */ +/* stapio->module->stapio */ struct _stp_msg_start { pid_t target; int32_t res; // for reply: result of probe_start() }; -struct _stp_symbol32 -{ - uint32_t addr; - uint32_t symbol; -}; - -struct _stp_symbol64 -{ - uint64_t addr; - uint64_t symbol; -}; - -struct _stp_msg_symbol_hdr -{ - uint32_t num_syms; - uint32_t sym_size; - uint32_t unwind_size; -}; - -struct _stp_msg_module { - /* the module name, or "" for kernel */ - char name[STP_MODULE_NAME_LEN]; - - /* A pointer to the struct module */ - uint64_t module; - - /* the start of the module's text and data sections */ - uint64_t text; - uint64_t data; - - /* how many sections this module has */ - uint32_t num_sections; - - /* length of unwind data */ - uint32_t unwind_len; -}; - #ifdef STP_OLD_TRANSPORT /**** for compatibility with old relayfs ****/ struct _stp_buf_info diff --git a/runtime/unwind.c b/runtime/unwind.c new file mode 100644 index 00000000..9a5d61e8 --- /dev/null +++ b/runtime/unwind.c @@ -0,0 +1,895 @@ +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich <jbeulich@novell.com> + * This code is released under version 2 of the GNU GPL. + * + * A simple API for unwinding kernel stacks. This is used for + * debugging and error reporting purposes. The kernel doesn't need + * full-blown stack unwinding with all the bells and whistles, so there + * is not much point in implementing the full Dwarf2 unwind API. + */ + +#include "unwind/unwind.h" + +struct eh_frame_hdr_table_entry { + unsigned long start, fde; +}; + +static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2) +{ + const struct eh_frame_hdr_table_entry *e1 = p1; + const struct eh_frame_hdr_table_entry *e2 = p2; + return (e1->start > e2->start) - (e1->start < e2->start); +} + +static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size) +{ + struct eh_frame_hdr_table_entry *e1 = p1; + struct eh_frame_hdr_table_entry *e2 = p2; + unsigned long v; + + v = e1->start; + e1->start = e2->start; + e2->start = v; + v = e1->fde; + e1->fde = e2->fde; + e2->fde = v; +} + +/* Build a binary-searchable unwind header. Also do some + * validity checks. In the future we might use */ +/* .eh_frame_hdr if it is already present. */ +static void _stp_create_unwind_hdr(struct _stp_module *m) +{ + const u8 *ptr; + unsigned long tableSize, hdrSize, last; + unsigned n = 0; + const u32 *fde; + int bad_order = 0; + struct { + u8 version; + u8 eh_frame_ptr_enc; + u8 fde_count_enc; + u8 table_enc; + unsigned long eh_frame_ptr; + unsigned int fde_count; + struct eh_frame_hdr_table_entry table[]; + } __attribute__ ((__packed__)) * header = NULL; + + /* already did this or no data? */ + if (m->unwind_hdr || m->unwind_data_len == 0) + return; + + tableSize = m->unwind_data_len; + if (tableSize & (sizeof(*fde) - 1)) { + dbug_unwind(1, "tableSize=0x%x not a multiple of 0x%x\n", (int)tableSize, (int)sizeof(*fde)); + goto bad; + } + + /* count the FDEs */ + for (fde = m->unwind_data; + tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; + tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { + signed ptrType; + const u32 *cie; + + /* check for extended length */ + if ((*fde & 0xfffffff0) == 0xfffffff0) { + dbug_unwind(1, "Module %s has extended-length CIE or FDE."); + dbug_unwind(1, "This is not supported at this time."); + goto bad; + } + cie = cie_for_fde(fde, m); + if (cie == ¬_fde) + continue; /* fde was a CIE. That's OK, just skip it. */ + if (cie == NULL || cie == &bad_cie || (ptrType = fde_pointer_type(cie)) < 0) + goto bad; + /* we have a real FDE */ + ptr = (const u8 *)(fde + 2); + if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType)) + goto bad; + ++n; + } + + if (tableSize || !n) { + dbug_unwind(1, "%s: tableSize=%ld, n=%d\n", m->name, tableSize, n); + goto bad; + } + + hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int) + 2 * n * sizeof(unsigned long); + header = _stp_kmalloc(hdrSize); + if (header == NULL) { + header = _stp_vmalloc(hdrSize); + if (header == NULL) + return; + m->allocated.unwind_hdr = 1; + } + + header->version = 1; + header->eh_frame_ptr_enc = DW_EH_PE_absptr; + header->fde_count_enc = DW_EH_PE_data4; + header->table_enc = DW_EH_PE_absptr; + _stp_put_unaligned((unsigned long)m->unwind_data, &header->eh_frame_ptr); + + BUILD_BUG_ON(offsetof(typeof(*header), fde_count) + % __alignof(typeof(header->fde_count))); + header->fde_count = n; + + BUILD_BUG_ON(offsetof(typeof(*header), table) % __alignof(typeof(*header->table))); + + n = 0; + last = 0; + tableSize = m->unwind_data_len; + for (fde = m->unwind_data; tableSize; tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { + const u32 *cie = cie_for_fde(fde, m); + if (cie == ¬_fde) + continue; + if (cie == NULL || cie == &bad_cie) + goto bad; + /* we have a real FDE */ + ptr = (const u8 *)(fde + 2); + header->table[n].start = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, fde_pointer_type(cie)); + header->table[n].fde = (unsigned long)fde; + if (header->table[n].start < last) + bad_order++; + last = header->table[n].start; + ++n; + } + WARN_ON(n != header->fde_count); + + /* Is sort ever necessary? */ + if (bad_order) + _stp_sort(header->table, n, sizeof(*header->table), cmp_eh_frame_hdr_table_entries, + swap_eh_frame_hdr_table_entries); + + m->unwind_hdr_len = hdrSize; + m->unwind_hdr = header; + return; + + /* unwind data is not acceptable. free it and return */ +bad: + dbug_unwind(1, "unwind data for %s is unacceptable. Freeing.", m->name); + if (header) { + if (m->allocated.unwind_hdr) { + m->allocated.unwind_hdr = 0; + _stp_vfree(header); + } else + _stp_kfree(header); + } + if (m->unwind_data) { + if (m->allocated.unwind_data) + _stp_vfree(m->unwind_data); + else + _stp_kfree(m->unwind_data); + m->unwind_data = NULL; + m->unwind_data_len = 0; + } + return; +} + +static uleb128_t get_uleb128(const u8 **pcur, const u8 *end) +{ + const u8 *cur = *pcur; + uleb128_t value = 0; + unsigned shift; + + for (shift = 0; cur < end; shift += 7) { + if (shift + 7 > 8 * sizeof(value) + && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { + cur = end + 1; + break; + } + value |= (uleb128_t)(*cur & 0x7f) << shift; + if (!(*cur++ & 0x80)) + break; + } + *pcur = cur; + + return value; +} + +static sleb128_t get_sleb128(const u8 **pcur, const u8 *end) +{ + const u8 *cur = *pcur; + sleb128_t value = 0; + unsigned shift; + + for (shift = 0; cur < end; shift += 7) { + if (shift + 7 > 8 * sizeof(value) + && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { + cur = end + 1; + break; + } + value |= (sleb128_t)(*cur & 0x7f) << shift; + if (!(*cur & 0x80)) { + value |= -(*cur++ & 0x40) << shift; + break; + } + } + *pcur = cur; + + return value; +} + +/* given an FDE, find its CIE */ +static const u32 *cie_for_fde(const u32 *fde, const struct _stp_module *m) +{ + const u32 *cie; + + /* check that length is proper */ + if (!*fde || (*fde & (sizeof(*fde) - 1))) + return &bad_cie; + + /* CIE id for eh_frame is 0, otherwise 0xffffffff */ + if (m->unwind_is_ehframe && fde[1] == 0) + return ¬_fde; + else if (fde[1] == 0xffffffff) + return ¬_fde; + + /* OK, must be an FDE. Now find its CIE. */ + + /* CIE_pointer must be a proper offset */ + if ((fde[1] & (sizeof(*fde) - 1)) || fde[1] > (unsigned long)(fde + 1) - (unsigned long)m->unwind_data) { + dbug_unwind(1, "fde[1]=%lx fde+1=%lx, unwind_data=%lx %lx\n", + (unsigned long)fde[1], (unsigned long)(fde + 1), + (unsigned long)m->unwind_data, (unsigned long)(fde + 1) - (unsigned long)m->unwind_data); + return NULL; /* this is not a valid FDE */ + } + + /* cie pointer field is different in eh_frame vs debug_frame */ + if (m->unwind_is_ehframe) + cie = fde + 1 - fde[1] / sizeof(*fde); + else + cie = m->unwind_data + fde[1]; + + if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde) + || (*cie & (sizeof(*cie) - 1)) + || (cie[1] != 0xffffffff && cie[1] != 0)) { + dbug_unwind(1, "cie is not valid %lx %x %x %x\n", cie, *cie, fde[1], cie[1]); + return NULL; /* this is not a (valid) CIE */ + } + + return cie; +} + +/* read an encoded pointer */ +static unsigned long read_pointer(const u8 **pLoc, const void *end, signed ptrType) +{ + unsigned long value = 0; + union { + const u8 *p8; + const u16 *p16u; + const s16 *p16s; + const u32 *p32u; + const s32 *p32s; + const unsigned long *pul; + } ptr; + + if (ptrType < 0 || ptrType == DW_EH_PE_omit) + return 0; + + ptr.p8 = *pLoc; + switch (ptrType & DW_EH_PE_FORM) { + case DW_EH_PE_data2: + if (end < (const void *)(ptr.p16u + 1)) + return 0; + if (ptrType & DW_EH_PE_signed) + value = _stp_get_unaligned(ptr.p16s++); + else + value = _stp_get_unaligned(ptr.p16u++); + break; + case DW_EH_PE_data4: +#ifdef CONFIG_64BIT + if (end < (const void *)(ptr.p32u + 1)) + return 0; + if (ptrType & DW_EH_PE_signed) + value = _stp_get_unaligned(ptr.p32s++); + else + value = _stp_get_unaligned(ptr.p32u++); + break; + case DW_EH_PE_data8: + BUILD_BUG_ON(sizeof(u64) != sizeof(value)); +#else + BUILD_BUG_ON(sizeof(u32) != sizeof(value)); +#endif + case DW_EH_PE_absptr: + if (end < (const void *)(ptr.pul + 1)) + return 0; + value = _stp_get_unaligned(ptr.pul++); + break; + case DW_EH_PE_leb128: + BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value)); + value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end) + : get_uleb128(&ptr.p8, end); + if ((const void *)ptr.p8 > end) + return 0; + break; + default: + return 0; + } + switch (ptrType & DW_EH_PE_ADJUST) { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + value += (unsigned long)*pLoc; + break; + default: + return 0; + } + if ((ptrType & DW_EH_PE_indirect) + && __stp_get_user(value, (unsigned long *)value)) + return 0; + *pLoc = ptr.p8; + + return value; +} + +static signed fde_pointer_type(const u32 *cie) +{ + const u8 *ptr = (const u8 *)(cie + 2); + unsigned version = *ptr; + + if (version != 1) + return -1; /* unsupported */ + if (*++ptr) { + const char *aug; + const u8 *end = (const u8 *)(cie + 1) + *cie; + uleb128_t len; + + /* check if augmentation size is first (and thus present) */ + if (*ptr != 'z') + return -1; + /* check if augmentation string is nul-terminated */ + if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL) + return -1; + ++ptr; /* skip terminator */ + get_uleb128(&ptr, end); /* skip code alignment */ + get_sleb128(&ptr, end); /* skip data alignment */ + /* skip return address column */ + version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end); + len = get_uleb128(&ptr, end); /* augmentation length */ + if (ptr + len < ptr || ptr + len > end) + return -1; + end = ptr + len; + while (*++aug) { + if (ptr >= end) + return -1; + switch (*aug) { + case 'L': + ++ptr; + break; + case 'P':{ + signed ptrType = *ptr++; + + if (!read_pointer(&ptr, end, ptrType) || ptr > end) + return -1; + } + break; + case 'R': + return *ptr; + default: + return -1; + } + } + } + return DW_EH_PE_absptr; +} + +static int advance_loc(unsigned long delta, struct unwind_state *state) +{ + state->loc += delta * state->codeAlign; + dbug_unwind(1, "state->loc=%lx\n", state->loc); + return delta > 0; +} + +static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value, struct unwind_state *state) +{ + dbug_unwind(1, "reg=%d, where=%d, value=%lx\n", reg, where, value); + if (reg < ARRAY_SIZE(state->regs)) { + state->regs[reg].where = where; + state->regs[reg].value = value; + } +} + +static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, signed ptrType, struct unwind_state *state) +{ + union { + const u8 *p8; + const u16 *p16; + const u32 *p32; + } ptr; + int result = 1; + + if (start != state->cieStart) { + state->loc = state->org; + result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state); + if (targetLoc == 0 && state->label == NULL) + return result; + } + + for (ptr.p8 = start; result && ptr.p8 < end;) { + switch (*ptr.p8 >> 6) { + uleb128_t value; + case 0: + switch (*ptr.p8++) { + case DW_CFA_nop: + dbug_unwind(1, "DW_CFA_nop\n"); + break; + case DW_CFA_set_loc: + if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0) + result = 0; + dbug_unwind(1, "DW_CFA_set_loc %lx (result=%d)\n", state->loc, result); + break; + case DW_CFA_advance_loc1: + result = ptr.p8 < end && advance_loc(*ptr.p8++, state); + dbug_unwind(1, "DW_CFA_advance_loc1 %d\n", result); + break; + case DW_CFA_advance_loc2: + result = ptr.p8 <= end + 2 && advance_loc(*ptr.p16++, state); + dbug_unwind(1, "DW_CFA_advance_loc2 %d\n", result); + break; + case DW_CFA_advance_loc4: + result = ptr.p8 <= end + 4 && advance_loc(*ptr.p32++, state); + dbug_unwind(1, "DW_CFA_advance_loc4 %d\n", result); + break; + case DW_CFA_offset_extended: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); + dbug_unwind(1, "DW_CFA_offset_extended\n"); + break; + case DW_CFA_val_offset: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Value, get_uleb128(&ptr.p8, end), state); + dbug_unwind(1, "DW_CFA_val_offset\n"); + break; + case DW_CFA_offset_extended_sf: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Memory, get_sleb128(&ptr.p8, end), state); + dbug_unwind(1, "DW_CFA_offset_extended_sf\n"); + break; + case DW_CFA_val_offset_sf: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Value, get_sleb128(&ptr.p8, end), state); + dbug_unwind(1, "DW_CFA_val_offset_sf\n"); + break; + case DW_CFA_restore_extended: + case DW_CFA_undefined: + case DW_CFA_same_value: + set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state); + dbug_unwind(1, "DW_CFA_undefined\n"); + break; + case DW_CFA_register: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Register, get_uleb128(&ptr.p8, end), state); + dbug_unwind(1, "DW_CFA_register\n"); + break; + case DW_CFA_remember_state: + dbug_unwind(1, "DW_CFA_remember_state\n"); + if (ptr.p8 == state->label) { + state->label = NULL; + return 1; + } + if (state->stackDepth >= MAX_STACK_DEPTH) + return 0; + state->stack[state->stackDepth++] = ptr.p8; + break; + case DW_CFA_restore_state: + dbug_unwind(1, "DW_CFA_restore_state\n"); + if (state->stackDepth) { + const uleb128_t loc = state->loc; + const u8 *label = state->label; + + state->label = state->stack[state->stackDepth - 1]; + memcpy(&state->cfa, &badCFA, sizeof(state->cfa)); + memset(state->regs, 0, sizeof(state->regs)); + state->stackDepth = 0; + result = processCFI(start, end, 0, ptrType, state); + state->loc = loc; + state->label = label; + } else + return 0; + break; + case DW_CFA_def_cfa: + state->cfa.reg = get_uleb128(&ptr.p8, end); + dbug_unwind(1, "DW_CFA_def_cfa reg=%ld\n", state->cfa.reg); + /*nobreak */ + case DW_CFA_def_cfa_offset: + state->cfa.offs = get_uleb128(&ptr.p8, end); + dbug_unwind(1, "DW_CFA_def_cfa_offset offs=%lx\n", state->cfa.offs); + break; + case DW_CFA_def_cfa_sf: + state->cfa.reg = get_uleb128(&ptr.p8, end); + dbug_unwind(1, "DW_CFA_def_cfa_sf reg=%ld\n", state->cfa.reg); + /*nobreak */ + case DW_CFA_def_cfa_offset_sf: + state->cfa.offs = get_sleb128(&ptr.p8, end) * state->dataAlign; + dbug_unwind(1, "DW_CFA_def_cfa_offset_sf offs=%lx\n", state->cfa.offs); + break; + case DW_CFA_def_cfa_register: + state->cfa.reg = get_uleb128(&ptr.p8, end); + dbug_unwind(1, "DW_CFA_def_cfa_register reg=%ld\n", state->cfa.reg); + break; + /*todo case DW_CFA_def_cfa_expression: */ + /*todo case DW_CFA_expression: */ + /*todo case DW_CFA_val_expression: */ + case DW_CFA_GNU_args_size: + get_uleb128(&ptr.p8, end); + dbug_unwind(1, "DW_CFA_GNU_args_size\n"); + break; + case DW_CFA_GNU_negative_offset_extended: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Memory, (uleb128_t)0 - get_uleb128(&ptr.p8, end), state); + dbug_unwind(1, "DW_CFA_GNU_negative_offset_extended\n"); + break; + case DW_CFA_GNU_window_save: + default: + dbug_unwind(1, "unimplemented call frame instruction: 0x%x\n", *(ptr.p8 - 1)); + result = 0; + break; + } + break; + case 1: + result = advance_loc(*ptr.p8++ & 0x3f, state); + dbug_unwind(1, "case 1\n"); + break; + case 2: + value = *ptr.p8++ & 0x3f; + set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); + dbug_unwind(1, "case 2\n"); + break; + case 3: + set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state); + dbug_unwind(1, "case 3\n"); + break; + } + if (ptr.p8 > end) + result = 0; + if (result && targetLoc != 0 && targetLoc < state->loc) + return 1; + } + return result && ptr.p8 == end && (targetLoc == 0 || state->label == NULL); +} + +/* 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) +{ + const u8 *ptr, *end, *hdr = m->unwind_hdr; + unsigned long startLoc; + u32 *fde = NULL; + unsigned num, tableSize, t2; + + /* TOTO: only really need to test hdr == NULL */ + /* The rest should be validated at load time */ + + if (hdr == NULL || hdr[0] != 1) + return NULL; + + dbug_unwind(1, "search for %lx", pc); + + /* table_enc */ + switch (hdr[3] & DW_EH_PE_FORM) { + case DW_EH_PE_absptr: + tableSize = sizeof(unsigned long); + break; + case DW_EH_PE_data2: + tableSize = 2; + break; + case DW_EH_PE_data4: + tableSize = 4; + break; + case DW_EH_PE_data8: + tableSize = 8; + break; + default: + dbug_unwind(1, "bad table encoding"); + return NULL; + } + ptr = hdr + 4; + end = hdr + m->unwind_hdr_len; + + if (read_pointer(&ptr, end, hdr[1]) != (unsigned long)m->unwind_data) { + dbug_unwind(1, "eh_frame_ptr not valid"); + return NULL; + } + + num = read_pointer(&ptr, end, hdr[2]); + if (num == 0 || num != (end - ptr) / (2 * tableSize) || (end - ptr) % (2 * tableSize)) { + dbug_unwind(1, "Bad num=%d end-ptr=%ld 2*tableSize=%d", num, end - ptr, 2 * tableSize); + return NULL; + } + + do { + const u8 *cur = ptr + (num / 2) * (2 * tableSize); + startLoc = read_pointer(&cur, cur + tableSize, hdr[3]); + if (pc < startLoc) + num /= 2; + else { + ptr = cur - tableSize; + num = (num + 1) / 2; + } + } while (startLoc && num > 1); + + if (num == 1 && (startLoc = read_pointer(&ptr, ptr + tableSize, hdr[3])) != 0 && pc >= startLoc) + fde = (void *)read_pointer(&ptr, ptr + tableSize, hdr[3]); + + dbug_unwind(1, "returning %lx", fde); + return fde; +} + +/* Unwind to previous to frame. Returns 0 if successful, negative + * number in case of an error. */ +int unwind(struct unwind_frame_info *frame) +{ +#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) + const u32 *fde, *cie = NULL; + const u8 *ptr = NULL, *end = NULL; + unsigned long pc = UNW_PC(frame) - frame->call_frame; + unsigned long tableSize, startLoc = 0, endLoc = 0, cfa; + unsigned i; + signed ptrType = -1; + uleb128_t retAddrReg = 0; + struct _stp_module *m; + struct unwind_state state; + + dbug_unwind(1, "pc=%lx, %lx", pc, UNW_PC(frame)); + + if (UNW_PC(frame) == 0) + return -EINVAL; + + m = _stp_get_unwind_info(pc); + if (unlikely(m == NULL)) { + dbug_unwind(1, "No module found for pc=%lx", pc); + return -EINVAL; + } + + if (unlikely(m->unwind_data_len == 0 || m->unwind_data_len & (sizeof(*fde) - 1))) { + dbug_unwind(1, "Module %s: unwind_data_len=%d", m->name, m->unwind_data_len); + goto done; + } + + fde = _stp_search_unwind_hdr(pc, m); + dbug_unwind(1, "%s: fde=%lx\n", m->name, fde); + + if (fde != NULL) { + cie = cie_for_fde(fde, m); + ptr = (const u8 *)(fde + 2); + if (cie != NULL + && cie != &bad_cie + && cie != ¬_fde + && (ptrType = fde_pointer_type(cie)) >= 0 + && read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType) == startLoc) { + if (!(ptrType & DW_EH_PE_indirect)) + ptrType &= DW_EH_PE_FORM | DW_EH_PE_signed; + endLoc = startLoc + read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); + if (pc >= endLoc) + fde = NULL; + } else + fde = NULL; + } + if (fde == NULL) { + for (fde = m->unwind_data, tableSize = m->unwind_data_len; cie = NULL, tableSize > sizeof(*fde) + && tableSize - sizeof(*fde) >= *fde; tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { + // dbug_unwind(1,"fde=%lx tableSize=%d\n", (long)*fde, (int)tableSize); + cie = cie_for_fde(fde, m); + if (cie == &bad_cie) { + cie = NULL; + break; + } + if (cie == NULL || cie == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) + continue; + + ptr = (const u8 *)(fde + 2); + startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); + // dbug_unwind(1,"startLoc=%p\n",(u64)startLoc); + if (!startLoc) + continue; + if (!(ptrType & DW_EH_PE_indirect)) + ptrType &= DW_EH_PE_FORM | DW_EH_PE_signed; + endLoc = startLoc + read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); + // dbug_unwind(1,"endLoc=%p\n",(u64)endLoc); + if (pc >= startLoc && pc < endLoc) + break; + } + } + + dbug_unwind(1, "cie=%lx fde=%lx startLoc=%lx endLoc=%lx\n", cie, fde, startLoc, endLoc); + if (cie == NULL || fde == NULL) + goto done; + + /* found the CIE and FDE */ + + memset(&state, 0, sizeof(state)); + state.cieEnd = ptr; /* keep here temporarily */ + ptr = (const u8 *)(cie + 2); + end = (const u8 *)(cie + 1) + *cie; + frame->call_frame = 1; + if ((state.version = *ptr) != 1) { + dbug_unwind(1, "CIE version number is %d. 1 is supported.\n", state.version); + goto done; /* unsupported version */ + } + if (*++ptr) { + /* check if augmentation size is first (and thus present) */ + if (*ptr == 'z') { + while (++ptr < end && *ptr) { + switch (*ptr) { + /* check for ignorable (or already handled) + * nul-terminated augmentation string */ + case 'L': + case 'P': + case 'R': + continue; + case 'S': + frame->call_frame = 0; + continue; + default: + break; + } + break; + } + } + if (ptr >= end || *ptr) { + dbug_unwind(1, "Problem parsing the augmentation string.\n"); + goto done; + } + } + ++ptr; + + /* get code aligment factor */ + state.codeAlign = get_uleb128(&ptr, end); + /* get data aligment factor */ + state.dataAlign = get_sleb128(&ptr, end); + if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end) + goto done;; + + retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end); + + /* skip augmentation */ + if (((const char *)(cie + 2))[1] == 'z') { + uleb128_t augSize = get_uleb128(&ptr, end); + ptr += augSize; + } + if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info) + || REG_INVALID(retAddrReg) + || reg_info[retAddrReg].width != sizeof(unsigned long)) + goto done; + + state.cieStart = ptr; + ptr = state.cieEnd; + state.cieEnd = end; + end = (const u8 *)(fde + 1) + *fde; + + /* skip augmentation */ + if (((const char *)(cie + 2))[1] == 'z') { + uleb128_t augSize = get_uleb128(&ptr, end); + if ((ptr += augSize) > end) + goto done; + } + + state.org = startLoc; + memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); + /* process instructions */ + if (!processCFI(ptr, end, pc, ptrType, &state) + || state.loc > endLoc || state.regs[retAddrReg].where == Nowhere || state.cfa.reg >= ARRAY_SIZE(reg_info) + || reg_info[state.cfa.reg].width != sizeof(unsigned long) + || state.cfa.offs % sizeof(unsigned long)) + goto done; + + /* update frame */ + dbug_unwind(1, "cie=%lx fde=%lx\n", cie, fde); +#ifndef CONFIG_AS_CFI_SIGNAL_FRAME + if (frame->call_frame && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign)) + frame->call_frame = 0; +#endif + cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; + startLoc = min((unsigned long)UNW_SP(frame), cfa); + endLoc = max((unsigned long)UNW_SP(frame), cfa); + dbug_unwind(1, "cfa=%lx SP startLoc=%lx, endLoc=%lx\n", cfa, startLoc, endLoc); + if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) { + startLoc = min(STACK_LIMIT(cfa), cfa); + endLoc = max(STACK_LIMIT(cfa), cfa); + dbug_unwind(1, "SP startLoc=%p, endLoc=%p\n", (u64)startLoc, (u64)endLoc); + } +#ifndef CONFIG_64BIT +# define CASES CASE(8); CASE(16); CASE(32) +#else +# define CASES CASE(8); CASE(16); CASE(32); CASE(64) +#endif + dbug_unwind(1, "cie=%p fde=%p\n", (u64)cie, (u64)fde); + for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { + if (REG_INVALID(i)) { + if (state.regs[i].where == Nowhere) + continue; + dbug_unwind(1, "REG_INVALID %d\n", i); + goto done; + } + dbug_unwind(1, "register %d. where=%d\n", i, state.regs[i].where); + switch (state.regs[i].where) { + default: + break; + case Register: + if (state.regs[i].value >= ARRAY_SIZE(reg_info) + || REG_INVALID(state.regs[i].value) + || reg_info[i].width > reg_info[state.regs[i].value].width) { + dbug_unwind(1, "case Register bad\n"); + goto done; + } + switch (reg_info[state.regs[i].value].width) { +#define CASE(n) \ + case sizeof(u##n): \ + state.regs[i].value = FRAME_REG(state.regs[i].value, \ + const u##n); \ + break + CASES; +#undef CASE + default: + dbug_unwind(1, "default\n"); + goto done; + } + break; + } + } + for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { + dbug_unwind(1, "register %d. invalid=%d\n", i, REG_INVALID(i)); + if (REG_INVALID(i)) + continue; + dbug_unwind(1, "register %d. where=%d\n", i, state.regs[i].where); + switch (state.regs[i].where) { + case Nowhere: + if (reg_info[i].width != sizeof(UNW_SP(frame)) + || &FRAME_REG(i, __typeof__(UNW_SP(frame))) + != &UNW_SP(frame)) + continue; + UNW_SP(frame) = cfa; + break; + case Register: + switch (reg_info[i].width) { +#define CASE(n) case sizeof(u##n): \ + FRAME_REG(i, u##n) = state.regs[i].value; \ + break + CASES; +#undef CASE + default: + dbug_unwind(1, "default\n"); + goto done; + } + break; + case Value: + if (reg_info[i].width != sizeof(unsigned long)) { + dbug_unwind(1, "Value\n"); + goto done; + } + FRAME_REG(i, unsigned long) = cfa + state.regs[i].value * state.dataAlign; + break; + case Memory:{ + unsigned long addr = cfa + state.regs[i].value * state.dataAlign; + dbug_unwind(1, "addr=%lx width=%d\n", addr, reg_info[i].width); + switch (reg_info[i].width) { +#define CASE(n) case sizeof(u##n): \ + if (unlikely(__stp_get_user(FRAME_REG(i, u##n), (u##n *)addr))) \ + goto copy_failed;\ + dbug_unwind(1, "set register %d to %lx\n", i, (long)FRAME_REG(i,u##n));\ + break + CASES; +#undef CASE + default: + dbug_unwind(1, "default\n"); + goto done; + } + } + break; + } + } + read_unlock(&m->lock); + dbug_unwind(1, "returning 0 (%lx)\n", UNW_PC(frame)); + return 0; + +copy_failed: + dbug_unwind(1, "_stp_get_user failed to access memory\n"); +done: + read_unlock(&m->lock); + return -EIO; +#undef CASES +#undef FRAME_REG +} diff --git a/runtime/uprobes/Makefile b/runtime/uprobes/Makefile deleted file mode 100644 index 40af7aa2..00000000 --- a/runtime/uprobes/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -obj-m := uprobes.o -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) -DEPENDENCIES := $(shell echo uprobes_arch.[ch] uprobes.[ch] uprobes_*.[ch]) -DEPENDENCIES += Makefile $(KDIR)/Module.symvers - -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - -# This target is used with "make -q" to see whether a "real" build is needed. -uprobes.ko: $(DEPENDENCIES) - @echo uprobes.ko is not a valid target. See Makefile. - -clean: - rm -f *.mod.c *.ko *.o .*.cmd *~ - rm -rf .tmp_versions diff --git a/safety/README b/safety/README deleted file mode 100644 index 61eda4a2..00000000 --- a/safety/README +++ /dev/null @@ -1,10 +0,0 @@ -This is a static safety-checker for SystemTap modules. It attempts to -validate modules by checking the opcodes used and the external references -against a whitelist. - -The script relies on external data files to provide the whitelists, which by -default are in the <script-dir>/data directory. The 'references' file -provides a plain list of allowed references. The 'opcodes' file provides a -list of regular expressions that match allowed opcodes. Either data file may -have an optional kernel and/or architecture suffix, as in 'opcodes-i686' or -'references-2.6.9-32.ELsmp-x86_64'. diff --git a/safety/data/opcodes-i686 b/safety/data/opcodes-i686 deleted file mode 100644 index 123fa2b0..00000000 --- a/safety/data/opcodes-i686 +++ /dev/null @@ -1,107 +0,0 @@ -aaa -aad -aam -aas -adc[bwl]? -add[bwl]? -and[bwl]? -bound[wl]? -bsf[wl]? -bsr[wl]? -bswapl? -btc[wl]? -btr[wl]? -bts[wl]? -bt[wl]? -call -cbtw -cbw -cdq -clc -cld -cli -cltd -cmc -cmovn?(?:a|ae|b|be|c|e|g|ge|l|le|o|p|pe|po|s|z)[wl]? -cmp[bwl]? -cmps[bwl]? -cmpxchg8b -cmpxchg[bwl]? -cpuid -cwd -cwde -cwtd -cwtl -daa -das -dec[bwl]? -div[bwl]? -enter -idiv[bwl]? -imul[bwl]? -inc[bwl]? -je?cxz -jmp -jn?(?:a|ae|b|be|c|e|g|ge|l|le|o|p|pe|po|s|z) -lcall -lds[wl]? -leave -lea[wl]? -les[wl]? -lfence -lfs[wl]? -lgs[wl]? -lods[bwl]? -loopn?[ze]? -lret -lss[wl]? -mfence -movaps -mov[bwl]? -movs[bwl]? -movsb[wl]? -movswl? -movzb[wl]? -movzwl? -mul[bwl]? -neg[bwl]? -nop -not[bwl]? -or[bwl]? -pause -popa[wl]? -popf[wl]? -pop[wl]? -prefetch(?:t[012]|nta) -pusha[wl]? -pushf[wl]? -push[wl]? -rcl[bwl]? -rcr[bwl]? -rdmsr -rdtsc -ret -rol[bwl]? -ror[bwl]? -sahf -sal[bwl]? -sar[bwl]? -sbb[bwl]? -scas[bwl]? -setn?(?:a|ae|b|be|c|e|g|ge|l|le|o|p|pe|po|s|z) -shl[bwl]? -shld[bwl]? -shr[bwl]? -shrd[bwl]? -smov[lw]? -stc -std -sti -stos[bwl]? -sub[bwl]? -test[bwl]? -xadd[bwl]? -xchg[bwl]? -xlat -xlatb -xor[bwl]? diff --git a/safety/data/opcodes-ia64 b/safety/data/opcodes-ia64 deleted file mode 100644 index edb1792e..00000000 --- a/safety/data/opcodes-ia64 +++ /dev/null @@ -1,89 +0,0 @@ -add[sl]? -addp4 -alloc -and -andcm -br(?:\.cond)?(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.cond(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.call(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.ret(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.cloop(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.ctop(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.cexit(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.wtop(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -br\.wexit(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -brl(?:\.cond)?(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -brl\.call(?:\.(?:spnt|sptk|dpnt|dptk))?(?:\.(?:few|many))?(?:\.clr)? -brp(?:\.(?:sptk|loop|exit|dptk))(?:\.imp)? -brp\.ret(?:\.(?:sptk|loop|exit|dptk))(?:\.imp)? -chk\.s(?:\.[im])? -chk\.a\.(?:clr|nc) -clrrrb -cmp\.(?:eq|ne|l[te]u?|g[te]u?)(?:\.(?:unc|or|and|or.andcm|orcm|andcm|and.orcm))? -cmp4\.(?:eq|ne|l[te]u?|g[te]u?)(?:\.(?:unc|or|and|or.andcm|orcm|andcm|and.orcm))? -cmpxchg[1248]\.(?:acq|rel)(?:\.nt[1a])? -cmp8xchg16\.(?:acq|rel)(?:\.nt[1a])? -cover -czx[12]\.[lr] -dep(?:\.z)? -extr(?:\.u)? -fetchadd[48]\.(?:acq|rel)(?:\.nt[1a])? -getf\.(?:s|d|exp|sig) -hint(?:\.[ibmfx])? -ld[1248](?:\.(?:s|a|sa|c\.nc|c\.clr|c\.clr\.acq|acq|bias))?(?:\.nt[1a])? -ld8\.fill(?:\.nt[1a])? -ld16(?:\.acq)?(?:\.nt[1a])? -ldf8(?:\.(?:s|a|sa|c\.nc|c\.clr))?(?:\.nt[1a])? -lfetch(?:.fault)?(?:\.excl)?(?:\.nt[12a])? -mf -mix[124]\.[lr] -mov(?:\.[im])? -mov(?:\.ret)?(?:\.sptk|\.dptk)?(?:\.imp)? -movl -mux[12] -nop(?:\.[ibmfx])? -or -pack2\.[us]ss -pack4.sss -padd[124] -padd[12]\.(?:sss|uus|uuu) -pavg[12](?:\.raz) -pavgsub[12] -pcmp[124]\.(?:eq|gt) -pmax1\.u -pmax2 -pmin1\.u -pmin2 -pmpy2\.[rl] -pmpyshr2(?:\.u)? -popcnt -psad1 -pshl[24] -pshladd2 -pshr[24](?:\.u)? -pshradd2 -psub[124] -psub[12]\.(?:sss|uus|uuu) -rsm -setf\.(?:s|d|exp|sig) -shl -shladd -shladdp4 -shr(?:\.u)? -shrp -srlz\.[id] -ssm -st[1248](?:\.rel)?(?:\.nta)? -st16(?:\.rel)?(?:\.nta)? -st8\.spill(?:\.nta)? -stf8(?:\.nta)? -sub -sxt[124] -tbit\.n?z(?:\.(?:unc|or|and|or.andcm|orcm|andcm|and.orcm))? -tnat\.n?z(?:\.(?:unc|or|and|or.andcm|orcm|andcm|and.orcm))? -unpack[124]\.[hl] -xchg[1248](?:\.nt[1a])? -xma\.[lh]u? -xmpy\.[lh]u? -xor -zxt[124] diff --git a/safety/data/opcodes-x86_64 b/safety/data/opcodes-x86_64 deleted file mode 100644 index b89df879..00000000 --- a/safety/data/opcodes-x86_64 +++ /dev/null @@ -1,104 +0,0 @@ -adc[bwlq]? -add[bwlq]? -and[bwlq]? -boundl? -bsf[wlq]? -bsr[wlq]? -bswap[lq]? -btc[wlq]? -btr[wlq]? -bts[wlq]? -bt[wlq]? -callq? -cbtw -cbw -cdq -cdqe -clc -cld -cli -cltd -cltq -cmc -cmovn?(?:a|ae|b|be|c|e|g|ge|l|le|o|p|pe|po|s|z)[wlq]? -cmp[bwlq]? -cmps[bwlq]? -cmpxchg16b -cmpxchg8b -cmpxchg[bwlq]? -cpuid -cqo -cqtd -cqto -cwd -cwde -cwtd -cwtl -dec[bwlq]? -div[bwlq]? -enterq? -idiv[bwlq]? -imul[bwlq]? -inc[bwlq]? -jcxz -jmpq? -jn?(?:a|ae|b|be|c|e|g|ge|l|le|o|p|pe|po|s|z) -lcallq? -leaveq? -lea[wlq]? -lfence -lfs[wl]? -lgs[wl]? -lods[bwlq]? -loopn?[ze]? -lretq? -lss[wl]? -mfence -movaps -mov[bwlq]? -movs[bwlq]? -movsb[wlq]? -movslq? -movsw[lq]? -movzb[wlq]? -movzw[lq]? -mul[bwlq]? -neg[bwlq]? -nop -not[bwlq]? -or[bwlq]? -pause -popf[wlq]? -pop[wlq]? -prefetch(?:t[012]|nta) -pushf[wlq]? -push[wlq]? -rcl[bwlq]? -rcr[bwlq]? -rdmsr -rdtsc -retq? -rol[bwlq]? -ror[bwlq]? -sahf -sal[bwlq]? -sar[bwlq]? -sbb[bwlq]? -scas[bwlq]? -setn?(?:a|ae|b|be|c|e|g|ge|l|le|o|p|pe|po|s|z) -shl[bwlq]? -shld[bwlq]? -shr[bwlq]? -shrd[bwlq]? -smov[lw]? -stc -std -sti -stos[bwlq]? -sub[bwlq]? -test[bwlq]? -xadd[bwlq]? -xchg[bwlq]? -xlat -xlatb -xor[bwlq]? diff --git a/safety/data/references b/safety/data/references deleted file mode 100644 index bfea8e86..00000000 --- a/safety/data/references +++ /dev/null @@ -1,94 +0,0 @@ -__alloc_percpu -autoremove_wake_function -__bitmap_weight -cond_resched -__const_udelay -copy_from_user -__copy_from_user_ll -copy_to_user -__copy_user -copy_user_generic -cpu_callout_map -cpu_online_map -cpu_possible_map -cpu_to_node -create_proc_entry -del_timer_sync -__divdi3 -do_gettimeofday -__down_failed -__find_next_bit -find_next_bit -finish_wait -free_percpu -__get_user_4 -init_timer -__init_timer_base -jiffies -kallsyms_lookup_name -kfree -__kmalloc -kmalloc_node -kmem_cache_alloc -malloc_sizes -memcmp -memcpy -memset -__might_sleep -__moddi3 -__mod_timer -mod_timer -msleep -node_online_map -param_get_int -param_get_long -param_get_string -param_set_copystring -param_set_int -param_set_long -per_cpu__cpu_info -prepare_to_wait -printk -proc_mkdir -proc_root -_read_lock -_read_trylock -_read_unlock -register_kprobe -register_kretprobe -register_profile_notifier -register_timer_hook -remove_proc_entry -schedule -schedule_delayed_work -scnprintf -simple_strtol -snprintf -_spin_lock -_spin_lock_irqsave -_spin_trylock -_spin_unlock -_spin_unlock_irqrestore -sprintf -strcmp -strlcat -strlcpy -strlen -strncmp -strncpy -__strncpy_from_user -strsep -__udivdi3 -__umoddi3 -unregister_kprobe -unregister_kretprobe -unregister_profile_notifier -unregister_timer_hook -unw_init_running -unw_unwind -__up_wakeup -vscnprintf -vsnprintf -__wake_up -_write_trylock -_write_unlock diff --git a/safety/safety.py b/safety/safety.py deleted file mode 100755 index 8607ce75..00000000 --- a/safety/safety.py +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# vim: noet sw=4 ts=4 enc=utf-8 -"A static safety-checker for SystemTap modules." - -# Copyright (C) 2006 Intel Corporation. -# -# This file is part of systemtap, and is free software. You can -# redistribute it and/or modify it under the terms of the GNU General -# Public License (GPL); either version 2, or (at your option) any -# later version. - - -# in python 2.4, set & frozenset are builtins -# in python 2.3, the equivalents live in the 'sets' module -from sys import hexversion as __hexversion -if __hexversion < 0x020400f0: - from sets import Set as set, ImmutableSet as frozenset - - -def main(argv): - """ - CLI to the SystemTap static safety-checker. - - Provides a command-line interface for running the SystemTap module - safety checker. Use '-h' or '--help' for a description of the - command-line options. - - Returns the number of modules that failed the check. - """ - bad = 0 - (options, args) = __parse_args(argv[1:]) - safe = StaticSafety(options.arch, options.release, options.datapath) - for m in args: - if not safe.check_module(m): - bad += 1 - return bad - - -def __parse_args(argv): - from optparse import OptionParser - parser = OptionParser(usage="usage: %prog [options] [module]...", - description=__doc__) - parser.add_option('--data-path', dest='datapath', metavar='PATH', - help='specify the whitelist data files [default: <script-dir>/data]') - parser.add_option('-m', '--machine', '--architecture', dest='arch', - help='specify the machine architecture of the target') - parser.add_option('-r', '--kernel-release', dest='release', - help='specify the kernel release running on the target') - return parser.parse_args(argv) - - -class StaticSafety: - "Manage a safety-checking session." - - def __init__(self, arch=None, release=None, datapath=None): - from os import uname - self.__arch = arch or uname()[4] - self.__release = release or uname()[2] - self.__build_data_path(datapath) - self.__build_search_suffixes() - self.__load_allowed_references() - self.__load_allowed_opcodes() - - def __build_data_path(self, datapath): - "Determine where the data directory resides." - from sys import argv - from os.path import dirname, isdir, realpath - if datapath is None: - local = dirname(realpath(argv[0])) - self.__data_path = local + '/data' - else: - self.__data_path = datapath - - if not isdir(self.__data_path): - raise StandardError( - "Can't find the data directory! (looking in %s)" - % self.__data_path) - - def __build_search_suffixes(self): - "Construct arch & kernel-versioning search suffixes." - ss = set() - - # add empty string - ss.add('') - - # add architecture search path - archsfx = '-%s' % self.__arch - ss.add(archsfx) - - # add full kernel-version-release (2.6.NN-FOOBAR) + arch - relsfx = '-%s' % self.__release - ss.add(relsfx) - ss.add(relsfx + archsfx) - - # add kernel version (2.6.NN) + arch - dash_i = relsfx.find('-') - if dash_i > 0: - ss.add(relsfx[:dash_i]) - ss.add(relsfx[:dash_i] + archsfx) - - # start dropping decimals - dot_i = relsfx.rfind('.', 0, dash_i) - while dot_i > 0: - ss.add(relsfx[:dot_i]) - ss.add(relsfx[:dot_i] + archsfx) - dot_i = relsfx.rfind('.', 0, dot_i) - - self.__search_suffixes = frozenset(ss) - - def __load_allowed_references(self): - "Build the list of allowed external references from the data files." - wr = set() - for sfx in self.__search_suffixes: - try: - refs = open(self.__data_path + '/references' + sfx) - for line in refs: - wr.add(line.rstrip()) - refs.close() - except IOError: - pass - if not len(wr): - raise StandardError("No whitelisted references found!") - self.__white_references = frozenset(wr) - - def __load_allowed_opcodes(self): - "Build the regular expression matcher for allowed opcodes from the data files." - from re import compile - wo = [] - for sfx in self.__search_suffixes: - try: - opcs = open(self.__data_path + '/opcodes' + sfx) - for line in opcs: - wo.append(line.rstrip()) - opcs.close() - except IOError: - pass - if not len(wo): - raise StandardError("No whitelisted opcodes found!") - self.__white_opcodes_re = compile(r'^(?:' + r'|'.join(wo) + r')$') - - def __check_references(self, module): - "Check that all unresolved references in the module are allowed." - from os import popen - from re import compile - - sym_re = compile(r'^([\w@.]+) [Uw]\s+$') - def check(line): - m = sym_re.match(line) - if m: - ref = m.group(1) - if ref not in self.__white_references: - print 'ERROR: Invalid reference to %s' % ref - return False - return True - print 'WARNING: Unmatched line:\n %s' % `line` - return True - - command = 'nm --format=posix --no-sort --undefined-only ' + `module` - ok = True - nm = popen(command) - for line in nm: - ok &= check(line) - if nm.close(): - ok = False - return ok - - def __check_opcodes(self, module): - "Check that all disassembled opcodes in the module are allowed." - from os import popen - from re import compile - - skip_ud2a = [0] - - ignore_re = compile(r'^$|^\s+\.{3}$|^.*Disassembly of section|^.*file format') - if self.__arch == 'ia64': - opc = r'(?:\[[IBFLMX]{3}\]\s+)?(?:\(p\d\d\)\s+)?([\w.]+)\b' - elif self.__arch == 'x86_64' or self.__arch == 'i686': - opc = r'(?:lock\s+)?|(?:repn?[ze]?\s+)?|(?:rex\w+\s+)?(\w+)\b' - else: - opc = r'(\w+)\b' - opc_re = compile(r'^[A-Fa-f\d]+\s+<([^>]+)>\s+%s' % opc) - def check(line): - m = ignore_re.match(line) - if m: - return True - m = opc_re.match(line) - if m: - loc, opc = m.groups() - if opc == 'ud2a': - # The kernel abuses ud2a for BUG checks by following it - # directly with __LINE__ and __FILE__. Objdump doesn't - # know this though, so it tries to interpret the data as - # real instructions. Because x86(-64) instructions are - # variable-length, it's hard to tell when objdump is synced - # up again. We'll fast-forward to the next function - # boundary and hope things are better there. - for skip in objdump: - mskip = opc_re.match(skip) - if mskip: - locskip = mskip.group(1) - # a loc without an offset marks a new function - if '+' not in locskip: - return check(skip) - skip_ud2a[0] += 1 - return True - elif not self.__white_opcodes_re.match(opc): - print "ERROR: Invalid opcode '%s' at <%s>" % (opc, loc) - return False - return True - print 'WARNING: Unmatched line:\n %s' % `line` - return True - - command = 'objdump --disassemble --prefix-addresses ' + `module` - ok = True - objdump = popen(command) - for line in objdump: - ok &= check(line) - if objdump.close(): - ok = False - - if skip_ud2a[0]: - #print 'WARNING: Skipped %d lines due to ud2a corruption' % skip_ud2a[0] - pass - - return ok - - def check_module(self, module): - "Check a module for exclusively safe opcodes and external references." - from os.path import isfile - if not isfile(module): - print 'ERROR: %s is not a file!' % `module` - return False - res = self.__check_references(module) and self.__check_opcodes(module) - if res: - print 'PASS: %s' % module - else: - print 'FAIL: %s' % module - return res - - -if __name__ == '__main__': - from sys import exit, argv - exit(main(argv)) - @@ -467,12 +467,11 @@ For prologue style alias, the statement block that follows an alias definition is implicitly added as a prologue to any probe that refers to the alias. While for the epilogue style alias, the statement block that follows an alias definition is implicitly added as an epilogue to -any probe that refers to the alias. For example: +any probe that refers to the alias. For example: .SAMPLE probe syscall.read = kernel.function("sys_read") { fildes = $fd - if (execname == "init") next # skip rest of probe } .ESAMPLE defines a new probe point @@ -483,23 +482,19 @@ which expands to .nh .IR kernel.function("sys_read") , .hy -with the given statement as a prologue, which is useful to predefine -some variables for the alias user and/or to skip probe processing -entirely based on some conditions. And +with the given statement as a prologue. And .SAMPLE probe syscall.read += kernel.function("sys_read") { - if (tracethis) println ($fd) + fildes = $fd } .ESAMPLE -defines a new probe point with the given statement as an epilogue, which -is useful to take actions based upon variables set or left over by the -the alias user. +defines a new probe point with the given statement as an epilogue. -An alias is used just like a built-in probe type. +Another probe definition +may use the alias like this: .SAMPLE probe syscall.read { printf("reading fd=%d\n", fildes) - if (fildes > 10) tracethis = 1 } .ESAMPLE diff --git a/stapfuncs.5.in b/stapfuncs.5.in index 9bca845d..85a00b37 100644 --- a/stapfuncs.5.in +++ b/stapfuncs.5.in @@ -92,60 +92,6 @@ fault, return instead the err_msg value. user_string_warn:string (addr:long) Copy a string from user space at given address. If the access would fault, signal a warning and return "<unknown>". -.TP -user_string_quoted:string (addr:long) -Copy a string from user space at given address. Any ASCII characters -that are not printable are replaced by the corresponding escape -sequence in the returned string. -.TP -user_string_n:string (addr:long, n:long) -Copy a string of n bytes from user space at given address. If the access -would fault, return "<unknown>". -.TP -user_string_n2:string (addr:long, n:long, err_msg:string) -Copy a string of n bytes from user space at given address. If the access -would fault, return the err_msg value. -.TP -user_string_n_warn:string (addr:long, n:long) -Copy a string of n bytes from user space at given address. If the access -would fault, signal a warning and return "<unknown>". -.TP -user_string_n_quoted:string (addr:long, n:long) -Copy a string of n bytes from user space at given address. Any ASCII -characters that are not printable are replaced by the corresponding escape -sequence in the returned string. If the access would fault, return "<unknown>". -.TP -user_short:long (addr:long) -Copy a short from user space at given address. If the access would fault, -return 0. -.TP -user_short_warn:long (addr:long) -Copy a short from user space at given address. If the access would fault, -signal a warning and return 0. -.TP -user_int:long (addr:long) -Copy an int from user space at given address. If the access would fault, -return 0. -.TP -user_int_warn:long (addr:long) -Copy an int from user space at given address. If the access would fault, -signal a warning and return 0. -.TP -user_long:long (addr:long) -Copy a long from user space at given address. If the access would fault, -return 0. -.TP -user_long_warn:long (addr:long) -Copy a long from user space at given address. If the access would fault, -signal a warning and return 0. -.TP -user_char:long (addr:long) -Copy a char from user space at given address. If the access would fault, -return 0. -.TP -user_char_warn:long (addr:long) -Copy a char from user space at given address. If the access would fault, -signal a warning and return 0. .SS STRING .TP strlen:long (str:string) diff --git a/tapset/ChangeLog b/tapset/ChangeLog index dae8b452..da21a5ff 100644 --- a/tapset/ChangeLog +++ b/tapset/ChangeLog @@ -1,11 +1,3 @@ -2008-03-21 Eugene Teo <eugeneteo@kernel.sg> - - PR 5528 - * conversions.stp (user_string_n, user_string_n2, user_string_n_warn, - user_string_n_quoted, user_short, user_short_warn, user_int, - user_int_warn, user_long, user_long_warn, user_char, user_char_warn): - New user_* functions. - 2008-03-20 Frank Ch. Eigler <fche@elastic.org> PR 5956. diff --git a/tapset/conversions.stp b/tapset/conversions.stp index 70725e9d..af993992 100644 --- a/tapset/conversions.stp +++ b/tapset/conversions.stp @@ -1,5 +1,5 @@ // conversions tapset -// Copyright (C) 2005-2008 Red Hat Inc. +// Copyright (C) 2005-2007 Red Hat Inc. // Copyright (C) 2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can @@ -108,131 +108,3 @@ function user_string_quoted:string (addr:long) %{ /* pure */ _stp_text_str(THIS->__retvalue, (char *)(uintptr_t)THIS->addr, MAXSTRINGLEN, 1, 1); %} - -function user_string_n:string (addr:long, n:long) { - return user_string_n2(addr, n, "<unknown>") -} - -function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */ - long len = THIS->n + 1; - len = (len > MAXSTRINGLEN) ? MAXSTRINGLEN : len; - if (_stp_strncpy_from_user(THIS->__retvalue, - (char __user *) (uintptr_t) THIS->addr, - len) < 0) - strlcpy(THIS->__retvalue, THIS->err_msg, MAXSTRINGLEN); -%} - -function user_string_n_warn:string (addr:long, n:long) %{ /* pure */ - long len = THIS->n + 1; - long rc; - - len = (len > MAXSTRINGLEN) ? MAXSTRINGLEN : len; - rc = _stp_strncpy_from_user(THIS->__retvalue, - (char __user *) (uintptr_t) THIS->addr, len); - if (rc < 0) { - // NB: using error_buffer to get local space for the warning, but we're - // not aborting, so leave last_error alone. - snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), - "user string copy fault %ld at %p", rc, - (void *) (uintptr_t) THIS->addr); - _stp_warn(CONTEXT->error_buffer); - strlcpy (THIS->__retvalue, "<unknown>", MAXSTRINGLEN); - } -%} - -function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */ - long len = THIS->n + 1; - if (THIS->addr == 0) - strlcpy(THIS->__retvalue, "NULL", MAXSTRINGLEN); - else - /* XXX: stp_text_str uses sleepy __get_user() => unsafe ?! */ - _stp_text_str(THIS->__retvalue, (char *)(uintptr_t)THIS->addr, - len, 1, 1); -%} - -// When userspace data is not accessible, the following functions return 0 - -function user_short:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (short *) (intptr_t) THIS->addr, sizeof(short))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (short *) (intptr_t) THIS->addr)) { -fault: - THIS->__retvalue = 0; - } -%} - -function user_short_warn:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (short *) (intptr_t) THIS->addr, sizeof(short))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (short *) (intptr_t) THIS->addr)) { -fault: - snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), - "user short copy fault %p", (void *) (uintptr_t) THIS->addr); - _stp_warn(CONTEXT->error_buffer); - THIS->__retvalue = 0; - } -%} - -function user_int:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (int *) (intptr_t) THIS->addr, sizeof(int))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (int *) (intptr_t) THIS->addr)) { -fault: - THIS->__retvalue = 0; - } -%} - -function user_int_warn:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (int *) (intptr_t) THIS->addr, sizeof(int))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (int *) (intptr_t) THIS->addr)) { -fault: - snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), - "user int copy fault %p", (void *) (uintptr_t) THIS->addr); - _stp_warn(CONTEXT->error_buffer); - THIS->__retvalue = 0; - } -%} - -function user_long:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (long *) (intptr_t) THIS->addr, sizeof(long))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (long *) (intptr_t) THIS->addr)) { -fault: - THIS->__retvalue = 0; - } -%} - -function user_long_warn:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (long *) (intptr_t) THIS->addr, sizeof(long))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (long *) (intptr_t) THIS->addr)) { -fault: - snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), - "user long copy fault %p", (void *) (uintptr_t) THIS->addr); - _stp_warn(CONTEXT->error_buffer); - THIS->__retvalue = 0; - } -%} - -function user_char:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (char *) (intptr_t) THIS->addr, sizeof(char))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (char *) (intptr_t) THIS->addr)) { -fault: - THIS->__retvalue = 0; - } -%} - -function user_char_warn:long (addr:long) %{ /* pure */ - if (!access_ok(VERIFY_READ, (char *) (intptr_t) THIS->addr, sizeof(char))) - goto fault; - if (__stp_get_user(THIS->__retvalue, (char *) (intptr_t) THIS->addr)) { -fault: - snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), - "user char copy fault %p", (void *) (uintptr_t) THIS->addr); - _stp_warn(CONTEXT->error_buffer); - THIS->__retvalue = 0; - } -%} - diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index a54e80bd..16f7af57 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,21 +1,3 @@ -2008-03-23 Frank Ch. Eigler <fche@elastic.org> - - * lib/stap_run.exp (stap_run): Ignore missing debuginfo warnings. - Try harder to kill stap child in case of timeouts and errors. - -2008-03-23 Frank Ch. Eigler <fche@elastic.org> - - PR 5980. - * lib/systemtap.exp: Set default Snapshot: value from "stap -V" - output. - -2008-03-21 Eugene Teo <eugeneteo@kernel.sg> - - PR 5528 - * systemtap.stress/conversions.stp: Test new user_* functions. - * buildok/conversions.stp: Test new user_* functions. - * buildok/conversions-embedded.stp: Test new user_* functions. - 2008-03-20 Frank Ch. Eigler <fche@elastic.org> PR 5956. diff --git a/testsuite/buildok/conversions-embedded.stp b/testsuite/buildok/conversions-embedded.stp index 55f6cdb7..7aa5a0b4 100755 --- a/testsuite/buildok/conversions-embedded.stp +++ b/testsuite/buildok/conversions-embedded.stp @@ -9,18 +9,5 @@ probe begin { print (user_string2 (0, "")) print (user_string_warn (0)) print (user_string_quoted (0)) - - print (user_string_n(0, 5)) - print (user_string_n2(0, 5, "foobar")) - print (user_string_n_warn(0, 0)) - print (user_string_n_quoted(0, 0)) - print (user_short(0)) - print (user_short_warn(0)) - print (user_int(0)) - print (user_int_warn(0)) - print (user_long(0)) - print (user_long_warn(0)) - print (user_char(0)) - print (user_char_warn(0)) } diff --git a/testsuite/buildok/conversions.stp b/testsuite/buildok/conversions.stp index 5f151f1d..e83bd968 100755 --- a/testsuite/buildok/conversions.stp +++ b/testsuite/buildok/conversions.stp @@ -12,17 +12,4 @@ probe begin { print (user_string(2342)) print (user_string2(2342,"foobar")) print (user_string_warn(2342)) - - print (user_string_n(2342, 5)) - print (user_string_n2(2342, 5, "foobar")) - print (user_string_n_warn(2342, 5)) - print (user_string_n_quoted(2342, 5)) - print (user_short(2342)) - print (user_short_warn(2342)) - print (user_int(2342)) - print (user_int_warn(2342)) - print (user_long(2342)) - print (user_long_warn(2342)) - print (user_char(2342)) - print (user_char_warn(2342)) } diff --git a/testsuite/lib/stap_run.exp b/testsuite/lib/stap_run.exp index 42efa4f8..c2b4e74d 100644 --- a/testsuite/lib/stap_run.exp +++ b/testsuite/lib/stap_run.exp @@ -34,7 +34,6 @@ proc stap_run { TEST_NAME {LOAD_GEN_FUNCTION ""} {OUTPUT_CHECK_STRING ""} args } expect { -timeout 180 -re {^Warning: using '-m' disables cache support.\r\n} {exp_continue} - -re {^WARNING: cannot find module [^\r]*DWARF[^\r]*\r\n} {exp_continue} -re {^Pass\ ([1234]):[^\r]*\ in\ ([0-9]+)usr/([0-9]+)sys/([0-9]+)real\ ms\.\r\n} {set pass$expect_out(1,string) "\t$expect_out(2,string)\t$expect_out(3,string)\t$expect_out(4,string)"; exp_continue} -re {^Pass\ ([34]): using cached [^\r]+\r\n} @@ -74,22 +73,15 @@ proc stap_run { TEST_NAME {LOAD_GEN_FUNCTION ""} {OUTPUT_CHECK_STRING ""} args } set skipped_probes $expect_out(2,string)} } } - timeout { - fail "$TEST_NAME shutdown (timeout)" - exec kill -INT -[exp_pid] - } + timeout { fail "$TEST_NAME shutdown (timeout)" } eof { fail "$TEST_NAME shutdown (eof)" } } } -re "semantic error:" { fail "$TEST_NAME compilation" } - timeout { - fail "$TEST_NAME startup (timeout)" - exec kill -INT -[exp_pid] - } + timeout { fail "$TEST_NAME startup (timeout)" + exec kill -INT [exp_pid] } eof { fail "$TEST_NAME startup (eof)" } } - # again for good measure - exec kill -INT -[exp_pid] catch close wait } diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp index d458e98f..baed0e41 100644 --- a/testsuite/lib/systemtap.exp +++ b/testsuite/lib/systemtap.exp @@ -58,9 +58,8 @@ proc get_system_info {} { } elseif [file exists $env(SRCDIR)/../SNAPSHOT] { set Snapshot [exec /bin/cat $env(SRCDIR)/../SNAPSHOT] } else { - regexp {version [^)]*} [exec stap -V 2>@ stdout] version - set Snapshot $version - } + set Snapshot "unknown" + } set Distro "Linux" if [file exists /etc/fedora-release] {set Distro [exec /bin/cat /etc/fedora-release]} if [file exists /etc/redhat-release] {set Distro [exec /bin/cat /etc/redhat-release]} diff --git a/testsuite/systemtap.stress/conversions.stp b/testsuite/systemtap.stress/conversions.stp index 34bd0c28..07795a6d 100644 --- a/testsuite/systemtap.stress/conversions.stp +++ b/testsuite/systemtap.stress/conversions.stp @@ -13,16 +13,4 @@ probe begin { print (user_string ($1)) } probe begin { print (user_string2 ($1,"<only suspected, not known>")) } probe begin { print (user_string_warn ($1)) } probe begin { print (user_string_quoted ($1)) } -probe begin { print (user_string_n ($1, 5)) } -probe begin { print (user_string_n2 ($1, 5, "<only suspected, not known>")) } -probe begin { print (user_string_n_warn ($1, 5)) } -probe begin { print (user_string_n_quoted ($1, 5)) } -probe begin { print (user_short ($1)) } -probe begin { print (user_short_warn ($1)) } -probe begin { print (user_int ($1)) } -probe begin { print (user_int_warn ($1)) } -probe begin { print (user_long ($1)) } -probe begin { print (user_long_warn ($1)) } -probe begin { print (user_char ($1)) } -probe begin { print (user_char_warn ($1)) } probe begin(1) { print ("\n") exit () } diff --git a/translate.cxx b/translate.cxx index 2bfacefc..8b9dee54 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4356,80 +4356,43 @@ c_unparser::visit_hist_op (hist_op*) int emit_symbol_data (systemtap_session& s) { - int rc = 0; - // Instead of processing elf symbol tables, for now we just snatch - // /proc/kallsyms and convert it to our use. We need it sorted by - // address (so we can binary search) , and filtered (to show text - // symbols only), a task that we defer to grep(1) and sort(1). It - // may be useful to cache the symbols.sorted file, perhaps indexed - // by md5sum(/proc/modules), but let's not until this simple method - // proves too costly. LC_ALL=C is already set to avoid the - // excessive penalty of i18n code in some glibc/coreutils versions. - - string sorted_kallsyms = s.tmpdir + "/symbols.sorted"; - string sortcmd = "grep \" [AtT] \" /proc/kallsyms | "; - - if (s.symtab == false) - { - s.op->newline() << "/* filled in by runtime */"; - s.op->newline() << "struct stap_symbol *stap_symbols;"; - s.op->newline() << "unsigned stap_num_symbols;\n"; - return 0; - } + // /proc/kallsyms and convert it to our use. - sortcmd += "sort "; -#if __LP64__ - sortcmd += "-k 1,16 "; -#else - sortcmd += "-k 1,8 "; -#endif - sortcmd += "-s -o " + sorted_kallsyms; + unsigned i=0; + ifstream kallsyms("/proc/kallsyms"); + char kallsyms_outbuf [4096]; + ofstream kallsyms_out ((s.tmpdir + "/stap-symbols.h").c_str()); + kallsyms_out.rdbuf()->pubsetbuf (kallsyms_outbuf, + sizeof(kallsyms_outbuf)); - if (s.verbose>1) clog << "Running " << sortcmd << endl; - rc = system(sortcmd.c_str()); - if (rc == 0) + s.op->newline() << "\n\n#include \"stap-symbols.h\""; + kallsyms_out << "struct _stp_symbol _stp_kernel_symbols [] = {"; + string lastaddr, modules_op_addr; + + while (! kallsyms.eof()) { - ifstream kallsyms (sorted_kallsyms.c_str()); - char kallsyms_outbuf [4096]; - ofstream kallsyms_out ((s.tmpdir + "/stap-symbols.h").c_str()); - kallsyms_out.rdbuf()->pubsetbuf (kallsyms_outbuf, - sizeof(kallsyms_outbuf)); - - s.op->newline() << "\n\n#include \"stap-symbols.h\""; + string addr, type, sym; + kallsyms >> addr >> type >> sym >> ws; - unsigned i=0; - kallsyms_out << "struct stap_symbol _stp_stap_symbols [] = {"; - string lastaddr; - while (! kallsyms.eof()) + if (kallsyms.peek() == '[') + break; + + // NB: kallsyms includes some duplicate addresses + if ((type == "t" || type == "T" || type == "A") && lastaddr != addr) { - string addr, type, sym, module; - kallsyms >> addr >> type >> sym; - kallsyms >> ws; - if (kallsyms.peek() == '[') - { - string bracketed; - kallsyms >> bracketed; - module = bracketed.substr (1, bracketed.length()-2); - } - - // NB: kallsyms includes some duplicate addresses - if ((type == "t" || type == "T" || type == "A") && lastaddr != addr) - { - kallsyms_out << " { 0x" << addr << ", " - << "\"" << sym << "\", " - << "\"" << module << "\" }," - << "\n"; - lastaddr = addr; - i ++; - } + kallsyms_out << " { 0x" << addr << ", " << "\"" << sym << "\" },\n"; + lastaddr = addr; + i ++; } - kallsyms_out << "};\n"; - kallsyms_out << "struct stap_symbol *stap_symbols = _stp_stap_symbols;"; - kallsyms_out << "unsigned stap_num_symbols = " << i << ";\n"; + else if (sym == "modules_op") + modules_op_addr = addr; } + kallsyms_out << "};\n"; + kallsyms_out << "unsigned _stp_num_kernel_symbols = " << i << ";\n"; + kallsyms_out << "unsigned long _stp_modules_op = 0x" << modules_op_addr << ";\n"; - return rc; + return (i == 0); } @@ -4515,7 +4478,7 @@ translate_pass (systemtap_session& s) s.op->newline() << "#include <linux/random.h>"; s.op->newline() << "#include <linux/utsname.h>"; s.op->newline() << "#include \"loc2c-runtime.h\" "; - + // XXX: old 2.6 kernel hack s.op->newline() << "#ifndef read_trylock"; s.op->newline() << "#define read_trylock(x) ({ read_lock(x); 1; })"; diff --git a/vim/filetype.vim b/vim/filetype.vim deleted file mode 100644 index 8c1fdfbd..00000000 --- a/vim/filetype.vim +++ /dev/null @@ -1,10 +0,0 @@ -" Vim support file to detect file types -" Language: SystemTap -" Maintainer: Josh Stone <joshua.i.stone@intel.com> -" Last Change: 2005 Dec 16 -" Note: this overrides the default *.stp mapping to "Stored Procedures" -" It would be nice to find a way to intelligently detect this. - -" SystemTap scripts -au BufNewFile,BufRead *.stp setf stap - diff --git a/vim/ftplugin/stap.vim b/vim/ftplugin/stap.vim deleted file mode 100644 index de49a4f1..00000000 --- a/vim/ftplugin/stap.vim +++ /dev/null @@ -1,25 +0,0 @@ -" Vim filetype plugin file -" Language: SystemTap -" Maintainer: Josh Stone <joshua.i.stone@intel.com> -" Last Change: 2005 Dec 15 - -" Only do this when not done yet for this buffer -if exists("b:did_ftplugin") - finish -endif - -" Don't load another plugin for this buffer -let b:did_ftplugin = 1 - -set cpo-=C - -let b:undo_ftplugin = "setl cin< fo< com<" - -setlocal cindent - -" Set 'formatoptions' to break comment lines but not other lines, -" and insert the comment leader when hitting <CR> or using "o". -setlocal fo-=t fo+=croql - -" Set 'comments' to format dashed lists in comments. -setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://,:# diff --git a/vim/indent/stap.vim b/vim/indent/stap.vim deleted file mode 100644 index 16658d6c..00000000 --- a/vim/indent/stap.vim +++ /dev/null @@ -1,35 +0,0 @@ -" Vim indent file -" Language: SystemTap -" Maintainer: Josh Stone <joshua.i.stone@intel.com> -" Last Change: 2005 Dec 15 - -" Only load this indent file when no other was loaded. -if exists("b:did_indent") - finish -endif -let b:did_indent = 1 - -" SystemTap indenting works *mostly* the same as C, so this gets things pretty -" close. For 'real' SystemTap indenting, we would have to write a custom -" indentexpr function. - -" indenting is similar to C, so start there... -setlocal cindent - -" Statements don't require a ';', so don't indent following lines -setlocal cino=+0 - -" Known issues: -" - need to detect when following lines are a continuation of the previous -" statement, and indent appropriately. -" - one-liners with control flow try to indent the next line if there's no -" ';'. For example: -" if (my_condition) break -" do_work() -" The second line should not be indented. -" - The embedded-C braces do not line up correctly -" - Preprocessor braces don't line up correctly, and internals of the -" preprocessor aren't getting any special handling. -" - Embedded-C statements across multiple lines don't indent -" - '#' comments don't maintain indenting (they get treated like C -" preprocessor statements) diff --git a/vim/syntax/stap.vim b/vim/syntax/stap.vim deleted file mode 100644 index 86c7d260..00000000 --- a/vim/syntax/stap.vim +++ /dev/null @@ -1,97 +0,0 @@ -" Vim syntax file -" Language: SystemTap -" Maintainer: Josh Stone <joshua.i.stone@intel.com> -" Last Change: 2005 Dec 20 - -" For version 5.x: Clear all syntax items -" For version 6.x: Quit when a syntax file was already loaded -if version < 600 - syn clear -elseif exists("b:current_syntax") - finish -endif - -syn keyword stapStatement contained break continue return next delete containedin=stapBlock -syn keyword stapRepeat contained while for foreach in containedin=stapBlock -syn keyword stapConditional contained if else containedin=stapBlock -syn keyword stapDeclaration global probe function -syn keyword stapType string long - -syn region stapProbeDec start="\<probe\>"lc=5 end="{"me=s-1 contains=stapString,stapNumber -syn match stapProbe contained "\<\w\+\>" containedin=stapProbeDec - -syn region stapFuncDec start="\<function\>"lc=8 end=":\|("me=s-1 contains=stapString,stapNumber -syn match stapFuncCall contained "\<\w\+\ze\(\s\|\n\)*(" containedin=stapBlock -syn match stapFunc contained "\<\w\+\>" containedin=stapFuncDec,stapFuncCall - -syn match stapStat contained "@\<\w\+\ze\(\s\|\n\)*(" containedin=stapBlock - -" decimal number -syn match stapNumber "\<\d\+\>" containedin=stapBlock -" octal number -syn match stapNumber "\<0\o\+\>" contains=stapOctalZero containedin=stapBlock -" Flag the first zero of an octal number as something special -syn match stapOctalZero contained "\<0" -" flag an octal number with wrong digits -syn match stapOctalError "\<0\o*[89]\d*" containedin=stapBlock -" hex number -syn match stapNumber "0x\x\+\>" containedin=stapBlock - -syn region stapString oneline start=+"+ skip=+\\"+ end=+"+ containedin=stapBlock - -syn region stapPreProc fold start="%(" end="%)" contains=stapNumber,stapString containedin=ALL -syn keyword stapPreProcCond contained kernel_v kernel_vr arch containedin=stapPreProc - -syn include @C syntax/c.vim -syn keyword stapCMacro contained THIS CONTEXT containedin=@C,stapCBlock -syn region stapCBlock fold matchgroup=stapCBlockDelims start="%{"rs=e end="%}"re=s contains=@C - -syn region stapBlock fold matchgroup=stapBlockEnds start="{"rs=e end="}"re=s containedin=stapBlock - -syn keyword stapTodo contained TODO FIXME XXX - -syn match stapComment "#.*" contains=stapTodo containedin=stapBlock -syn match stapComment "//.*" contains=stapTodo containedin=stapBlock -syn region stapComment matchgroup=stapComment start="/\*" end="\*/" contains=stapTodo,stapCommentBad containedin=stapBlock -syn match stapCommentBad contained "/\*" - -" treat ^#! as special -syn match stapSharpBang "^#!.*" - - -" define the default highlighting -" For version 5.7 and earlier: only when not done already -" For version 5.8 and later: only when an item doesn't have highlightling yet -if version >= 508 || !exists("did_stap_syn_inits") - if version < 508 - let did_stap_syn_inits = 1 - command -nargs=+ HiLink hi link <args> - else - command -nargs=+ HiLink hi def link <args> - endif - - HiLink stapNumber Number - HiLink stapOctalZero PreProc " c.vim does it this way... - HiLink stapOctalError Error - HiLink stapString String - HiLink stapTodo Todo - HiLink stapComment Comment - HiLink stapCommentBad Error - HiLink stapSharpBang PreProc - HiLink stapCBlockDelims Special - HiLink stapCMacro Macro - HiLink stapStatement Statement - HiLink stapConditional Conditional - HiLink stapRepeat Repeat - HiLink stapType Type - HiLink stapProbe Function - HiLink stapFunc Function - HiLink stapStat Function - HiLink stapPreProc PreProc - HiLink stapPreProcCond Special - HiLink stapDeclaration Typedef - - delcommand HiLink -endif - -let b:current_syntax = "stap" |