summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--ChangeLog16
-rw-r--r--Makefile.am13
-rw-r--r--Makefile.in49
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/langref.tex24
-rw-r--r--runtime/.gitignore1
-rw-r--r--runtime/Makefile15
-rw-r--r--runtime/bench2/Makefile7
-rw-r--r--runtime/debug.h60
-rw-r--r--runtime/lket/b2a/.cvsignore1
-rw-r--r--runtime/lket/b2a/Makefile.am18
-rw-r--r--runtime/lket/b2a/Makefile.in449
-rw-r--r--runtime/lket/b2a/lket_b2a.c1030
-rw-r--r--runtime/lket/b2a/lket_b2a.h101
-rw-r--r--runtime/map.c1
-rw-r--r--runtime/probes.c12
-rw-r--r--runtime/probes/bench/Makefile10
-rw-r--r--runtime/runtime.h1
-rw-r--r--runtime/stack-x86_64.c37
-rw-r--r--runtime/stack.c3
-rw-r--r--runtime/staprun/mainloop.c159
-rw-r--r--runtime/staprun/staprun.c3
-rw-r--r--runtime/staprun/staprun.h3
-rw-r--r--runtime/staprun/staprun_funcs.c92
-rw-r--r--runtime/staprun/unwind_data.c97
-rw-r--r--runtime/sym.c6
-rw-r--r--runtime/sym.h24
-rw-r--r--runtime/tests/Makefile3
-rw-r--r--runtime/tests/agg/Makefile5
-rw-r--r--runtime/tests/maps/Makefile5
-rw-r--r--runtime/tests/math/Makefile5
-rw-r--r--runtime/tests/pmaps/Makefile5
-rw-r--r--runtime/tests/string/Makefile5
-rw-r--r--runtime/transport/control.c225
-rw-r--r--runtime/transport/procfs.c2
-rw-r--r--runtime/transport/symbols.c606
-rw-r--r--runtime/transport/transport.c148
-rw-r--r--runtime/transport/transport.h20
-rw-r--r--runtime/transport/transport_msgs.h63
-rw-r--r--runtime/unwind.c895
-rw-r--r--runtime/uprobes/Makefile16
-rw-r--r--safety/README10
-rw-r--r--safety/data/opcodes-i686107
-rw-r--r--safety/data/opcodes-ia6489
-rw-r--r--safety/data/opcodes-x86_64104
-rw-r--r--safety/data/references94
-rwxr-xr-xsafety/safety.py245
-rw-r--r--stap.1.in17
-rw-r--r--stapfuncs.5.in54
-rw-r--r--tapset/ChangeLog8
-rw-r--r--tapset/conversions.stp130
-rw-r--r--testsuite/ChangeLog18
-rwxr-xr-xtestsuite/buildok/conversions-embedded.stp13
-rwxr-xr-xtestsuite/buildok/conversions.stp13
-rw-r--r--testsuite/lib/stap_run.exp14
-rw-r--r--testsuite/lib/systemtap.exp5
-rw-r--r--testsuite/systemtap.stress/conversions.stp12
-rw-r--r--translate.cxx95
-rw-r--r--vim/filetype.vim10
-rw-r--r--vim/ftplugin/stap.vim25
-rw-r--r--vim/indent/stap.vim35
-rw-r--r--vim/syntax/stap.vim97
63 files changed, 1693 insertions, 3747 deletions
diff --git a/.gitignore b/.gitignore
index 69bd5e97..1c02452b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,9 @@ systemtap.spec
testresults
stapio
stap_merge
+CVS
+.checkstyle
+.cproject
+.metadata
+.project
+.settings
diff --git a/ChangeLog b/ChangeLog
index 046804c7..c7bb82c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 == &not_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 == &not_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 &not_fde;
+ else if (fde[1] == 0xffffffff)
+ return &not_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 != &not_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 == &not_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))
-
diff --git a/stap.1.in b/stap.1.in
index acfc64c3..c557350a 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -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"