diff options
author | fche <fche> | 2005-08-30 01:54:44 +0000 |
---|---|---|
committer | fche <fche> | 2005-08-30 01:54:44 +0000 |
commit | ba4a90fd18a9c94624a38d660c6e7ca6230c271f (patch) | |
tree | 82a060bc5f9db3001c0e09db8372caf8bfdfc2dc | |
parent | 55a030a179fdfd1e887d95d5c0050004bee27fcf (diff) | |
download | systemtap-steved-ba4a90fd18a9c94624a38d660c6e7ca6230c271f.tar.gz systemtap-steved-ba4a90fd18a9c94624a38d660c6e7ca6230c271f.tar.xz systemtap-steved-ba4a90fd18a9c94624a38d660c6e7ca6230c271f.zip |
2005-08-29 Frank Ch. Eigler <fche@redhat.com>
* stapprobes.5.in, stapfuncs.5.in, stapex.5.in: New man pages.
* stap.1.in: Moved some content out.
* Makefile.am (man_MANS): Add new man pages.
* configure.ac (AC_CONFIG_FILES): Add them.
* systemtap.spec.in: Package them.
* Makefile.in, configure: Regenerated.
* buildrun.cxx (run_pass): Pass "-r" to stpd.
* translate.cxx (emit_common_header): Wrap try/catch around
variable decls, to improve exception particularity.
(visit_literal_number): Emit as unsigned literal, which is
actually a subtle correctness issue.
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | Makefile.in | 85 | ||||
-rw-r--r-- | buildrun.cxx | 1 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | stap.1.in | 222 | ||||
-rw-r--r-- | stapex.5.in | 118 | ||||
-rw-r--r-- | stapfuncs.5.in | 92 | ||||
-rw-r--r-- | stapprobes.5.in | 181 | ||||
-rw-r--r-- | systemtap.spec.in | 1 | ||||
-rw-r--r-- | translate.cxx | 38 |
12 files changed, 590 insertions, 171 deletions
@@ -1,3 +1,17 @@ +2005-08-29 Frank Ch. Eigler <fche@redhat.com> + + * stapprobes.5.in, stapfuncs.5.in, stapex.5.in: New man pages. + * stap.1.in: Moved some content out. + * Makefile.am (man_MANS): Add new man pages. + * configure.ac (AC_CONFIG_FILES): Add them. + * systemtap.spec.in: Package them. + * Makefile.in, configure: Regenerated. + * buildrun.cxx (run_pass): Pass "-r" to stpd. + * translate.cxx (emit_common_header): Wrap try/catch around + variable decls, to improve exception particularity. + (visit_literal_number): Emit as unsigned literal, which is + actually a subtle correctness issue. + 2005-08-28 Frank Ch. Eigler <fche@redhat.com> * tapsets.cxx (visit_target): Make target variable exceptions diff --git a/Makefile.am b/Makefile.am index ea26e4d6..660aae40 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ AM_CFLAGS = -std=gnu99 -D_GNU_SOURCE \ -Wall -Werror -Wshadow -Wunused -Wformat=2 -W AM_CXXFLAGS = -Wall -dist_man_MANS = stap.1 +dist_man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapex.5 bin_PROGRAMS = stap stap_SOURCES = main.cxx \ parse.cxx staptree.cxx elaborate.cxx translate.cxx \ diff --git a/Makefile.in b/Makefile.in index 74741bbe..cab17cba 100644 --- a/Makefile.in +++ b/Makefile.in @@ -43,9 +43,11 @@ noinst_PROGRAMS = stpd$(EXEEXT) loc2c-test$(EXEEXT) subdir = . DIST_COMMON = README $(am__configure_deps) $(dist_man_MANS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/config.in $(srcdir)/stap.1.in $(srcdir)/stp_check.in \ - $(srcdir)/systemtap.spec.in $(top_srcdir)/configure AUTHORS \ - COPYING ChangeLog INSTALL NEWS TODO depcomp install-sh missing + $(srcdir)/config.in $(srcdir)/stap.1.in $(srcdir)/stapex.5.in \ + $(srcdir)/stapfuncs.5.in $(srcdir)/stapprobes.5.in \ + $(srcdir)/stp_check.in $(srcdir)/systemtap.spec.in \ + $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ + TODO depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -54,8 +56,10 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno configure.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = systemtap.spec stp_check stap.1 -am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +CONFIG_CLEAN_FILES = systemtap.spec stp_check stap.1 stapprobes.5 \ + stapfuncs.5 stapex.5 +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ + "$(DESTDIR)$(man5dir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_loc2c_test_OBJECTS = loc2c-test.$(OBJEXT) loc2c.$(OBJEXT) @@ -85,6 +89,7 @@ CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ SOURCES = $(loc2c_test_SOURCES) $(stap_SOURCES) $(stpd_SOURCES) DIST_SOURCES = $(loc2c_test_SOURCES) $(stap_SOURCES) $(stpd_SOURCES) man1dir = $(mandir)/man1 +man5dir = $(mandir)/man5 NROFF = nroff MANS = $(dist_man_MANS) ETAGS = etags @@ -193,7 +198,7 @@ AM_CFLAGS = -std=gnu99 -D_GNU_SOURCE \ -Wall -Werror -Wshadow -Wunused -Wformat=2 -W AM_CXXFLAGS = -Wall -dist_man_MANS = stap.1 +dist_man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapex.5 stap_SOURCES = main.cxx \ parse.cxx staptree.cxx elaborate.cxx translate.cxx \ tapsets.cxx buildrun.cxx loc2c.c @@ -287,6 +292,12 @@ stp_check: $(top_builddir)/config.status $(srcdir)/stp_check.in cd $(top_builddir) && $(SHELL) ./config.status $@ stap.1: $(top_builddir)/config.status $(srcdir)/stap.1.in cd $(top_builddir) && $(SHELL) ./config.status $@ +stapprobes.5: $(top_builddir)/config.status $(srcdir)/stapprobes.5.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +stapfuncs.5: $(top_builddir)/config.status $(srcdir)/stapfuncs.5.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +stapex.5: $(top_builddir)/config.status $(srcdir)/stapex.5.in + cd $(top_builddir) && $(SHELL) ./config.status $@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @@ -540,6 +551,51 @@ uninstall-man1: echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ done +install-man5: $(man5_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man5dir)" || $(mkdir_p) "$(DESTDIR)$(man5dir)" + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \ + done +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man5dir)/$$inst"; \ + done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -797,7 +853,7 @@ check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) config.h installdirs: - for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-am @@ -852,7 +908,7 @@ install-exec-am: install-binPROGRAMS install-exec-local install-info: install-info-am -install-man: install-man1 +install-man: install-man1 install-man5 installcheck-am: @@ -878,7 +934,7 @@ ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-local \ uninstall-man -uninstall-man: uninstall-man1 +uninstall-man: uninstall-man1 uninstall-man5 .PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ clean clean-binPROGRAMS clean-generic clean-local \ @@ -890,11 +946,12 @@ uninstall-man: uninstall-man1 install-binPROGRAMS install-data install-data-am \ install-data-local install-exec install-exec-am \ install-exec-local install-info install-info-am install-man \ - install-man1 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 \ - uninstall-info-am uninstall-local uninstall-man uninstall-man1 + install-man1 install-man5 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 uninstall-info-am \ + uninstall-local uninstall-man uninstall-man1 uninstall-man5 dist-hook: find $(distdir) -name CVS -o -name '*~' -o -name '.#*' | xargs rm -rf diff --git a/buildrun.cxx b/buildrun.cxx index 06e2494c..867d0d0e 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -113,6 +113,7 @@ run_pass (systemtap_session& s) // for now, just spawn stpd string stpd_cmd = string("/usr/bin/sudo ") + string(PKGLIBDIR) + "/stpd " + + "-r " // disable relayfs + (s.verbose ? "" : "-q ") + s.tmpdir + "/" + s.module_name + ".ko"; @@ -5170,7 +5170,7 @@ DATE="$date" ac_config_headers="$ac_config_headers config.h:config.in" - ac_config_files="$ac_config_files Makefile systemtap.spec stp_check stap.1" + ac_config_files="$ac_config_files Makefile systemtap.spec stp_check stap.1 stapprobes.5 stapfuncs.5 stapex.5" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -5746,6 +5746,9 @@ do "systemtap.spec" ) CONFIG_FILES="$CONFIG_FILES systemtap.spec" ;; "stp_check" ) CONFIG_FILES="$CONFIG_FILES stp_check" ;; "stap.1" ) CONFIG_FILES="$CONFIG_FILES stap.1" ;; + "stapprobes.5" ) CONFIG_FILES="$CONFIG_FILES stapprobes.5" ;; + "stapfuncs.5" ) CONFIG_FILES="$CONFIG_FILES stapfuncs.5" ;; + "stapex.5" ) CONFIG_FILES="$CONFIG_FILES stapex.5" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 diff --git a/configure.ac b/configure.ac index cfdbd95e..6730879c 100644 --- a/configure.ac +++ b/configure.ac @@ -40,5 +40,5 @@ AC_DEFINE_UNQUOTED(DATE, "$date", [Configuration/build date]) AC_SUBST(DATE, "$date") AC_CONFIG_HEADERS([config.h:config.in]) -AC_CONFIG_FILES(Makefile systemtap.spec stp_check stap.1) +AC_CONFIG_FILES(Makefile systemtap.spec stp_check stap.1 stapprobes.5 stapfuncs.5 stapex.5) AC_OUTPUT @@ -2,6 +2,20 @@ .TH STAP 1 @DATE@ "Red Hat" .SH NAME stap \- systemtap script translator/driver + +.\" macros +.de SAMPLE +.br +.RS +.nf +.nh +.. +.de ESAMPLE +.hy +.fi +.RE +.. + .SH SYNOPSIS .br @@ -32,7 +46,11 @@ instructions (written in a simple scripting language), translates those instructions into C code, compiles this C code, and loads the resulting kernel module into a running Linux kernel to perform the requested system trace/probe functions. You can supply the script in -a named file, from standard input, or from the command line. +a named file, from standard input, or from the command line. The +program runs until it is interrupted by the user, or if the script +voluntarily invokes the +.I exit() +function, or by any fatal error. .PP The language, which is described in a later section, is strictly typed, declaration free, procedural, and inspired by @@ -234,126 +252,43 @@ function call .SS PROBES The main construct in the scripting language identifies probes. Probes associate abstract events with a statement block ("probe -handler") that is to be executed when those events occur. The +handler") that is to be executed when any of those events occur. The general syntax is as follows: -.RS -.br -.nh -.nf +.SAMPLE .BR probe " PROBEPOINT [" , " PROBEPOINT] " { " [STMT ...] " } -.hy -.fi -.RE -.PP -Events are specified in a special syntax called "probe points". One -family refers to specific points in a kernel, which are identified by -module, source file, line number, function name, C label name, or some -combination of these. This kind of "synchronous" event is deemed to -occur when any processor executes an instruction matched by the -specification. Other families of probe points refer to "asynchronous" -events such as timers/counters rolling over, where there is no fixed -execution point that is related. Each probe point specification may -match multiple physical locations, all of which are then probed. A -probe declaration may also contain several comma-separated -specifications, all of which are probed. -.PP -Here is a list of probe point families currently supported. The -.B .function -variant places a probe near the beginning of the named function, so that -parameters are available as context variables. The -.B .return -variant places a probe at the moment of return from the named function, so -the return value is available as the "$retvalue" context variable. -The -.B .statement -variant places a probe at the exact spot, exposing those local variables -that are visible there. -.RS -.nf -.br -kernel.function(PATTERN) -.br -kernel.function(PATTERN).return -.br -module(MPATTERN).function(PATTERN) -.br -module(MPATTERN).function(PATTERN).return -.br -kernel.statement(PATTERN) -.br -module(MPATTERN).statement(PATTERN) -.br -timer.jiffies(NUM) -.br -timer.jiffies(NUM).randomize(RAND) -.fi -.RE +.ESAMPLE .PP -In the above list, MPATTERN stands for a string literal that aims to -identify the loaded kernel module of interest. It may include "*" and -"?" wildcards. PATTERN stands for a string literal that aims to -identify a point in the program. It is made up of three parts. The -first part is the name of a function, as would appear in the -.I nm -program's output. This part may use the "*" and "?" wildcarding -operators to match multiple names. The second part is optional, and -begins with the "@" character. It is followed by a source file name -wildcard pattern, such as -.IR mm/slab* . -Finally, the third part is optional if the file name part was given, -and identifies the line number in the source file, preceded by a ":". -As an alternative, PATTERN may be a numeric constant, indicating an -(module-relative or kernel-absolute) address. -.PP -The timer-based asynchronous probe points run the given handler every -NUM jiffies. If given, the random value in the range [-RAND..RAND] is -added to NUM every time the handler is run. -.PP -Here are some example probe points: -.TP -kernel.function("*init*"), kernel.function("*exit*") -refers to all kernel functions with "init" or "exit" in the name. -.TP -kernel.function("*@kernel/sched.c:240") -refers to any functions within the "kernel/sched.c" file that span -line 240. -.TP -module("usb*").function("*sync*").return -refers to the moment of return from all functions with "sync" in the -name in any of the USB drivers. -.TP -kernel.statement(0xc0044852) -refers to the first byte of the statement whose compiled instructions -include the given address in the kernel. -.TP -timer.jiffies(1000).randomize(200) -refers to a periodic interrupt, every 1000 +/- 200 jiffies. - +Events are specified in a special syntax called "probe points". There +are several varieties of probe points defined by the translator, and +tapset scripts may define further ones using aliases. These are +listed in the +.IR stapprobes (5) +manual pages. .PP -When any matching event occurs, the probe handler is run within that -context. For events that are defined by execution of specific parts -of code, this context may include variables defined in the source code +The probe handler is interpreted relative to the context of each +event. For events associated with kernel code, this context may +include +.I variables +defined in the +.I source code at that spot. These "target variables" are presented to the script as -variables whose names are prefixed with "$". They may be read/written +variables whose names are prefixed with "$". They may be accessed only if the kernel's compiler preserved them despite optimization. This is the same constraint that a debugger user faces when working -with optimized code. Asynchronous probes have very little context. +with optimized code. Some other events have very little context. .PP -In addition, "probe aliases" may be defined. Probe aliases look -similar to probe definitions, but instead of activating a probe at the -given point, it defines a new probe point name to alias an existing -one. This is identified by the "=" assignment operator. In addition, -the probe handler defined with an alias is implicitly added as a -prologue to any probe that refers to the alias. For example: -.RS -.nf -.nh +New probe points may be defined using "aliases". Probe point aliases +look similar to probe definitions, but instead of activating a probe +at the given point, it just defines a new probe point name as an alias +to an existing one. This is identified by the "=" assignment +operator. In addition, the statement block that follows an alias +definition is implicitly added as a prologue to any probe that refers +to the alias. For example: +.SAMPLE probe syscall("read") = kernel.function("sys_read") { fildes = $fd } -.hy -.fi -.RE +.ESAMPLE defines a new probe point .nh .IR syscall("read") , @@ -364,26 +299,22 @@ which expands to .hy with the given assignment as a prologue. Another probe definition may use the alias like this: -.RS -.nf +.SAMPLE probe syscall("read") { printk ("reading fd=" . string (fildes)) } -.fi -.RE +.ESAMPLE .SS FUNCTIONS Systemtap scripts may define subroutines to factor out common work. Functions take any number of scalar (integer or string) arguments, and must return a single scalar (integer or string). An example function declaration looks like this: -.RS -.nf +.SAMPLE function thisfn (arg1, arg2) { return arg1 + arg2 } -.fi -.RE +.ESAMPLE Note the usual absence of type declarations, which are instead inferred by the translator. Functions may call others or themselves recursively, up to a fixed nesting limit. This limit is defined by @@ -416,9 +347,7 @@ The memory locations set aside for input and output values are made available to it using a macro .IR THIS . Here are some examples: -.RS -.br -.nf +.SAMPLE function add_one (val) %{ THIS->__retvalue = THIS->val + 1; %} @@ -426,20 +355,21 @@ function add_one_str (val) %{ strncpy (THIS->__retvalue, THIS->val, MAXSTRINGLEN); strncat (THIS->__retvalue, "one", MAXSTRINGLEN); %} -.fi -.RE +.ESAMPLE The function argument and return value types have to be inferred by the translator from the call sites in order for this to work. The user should examine C code generated for ordinary script-language functions in order to write compatible embedded-C ones. .SS BUILT-INS -A set of builtin functions and probe aliases are provided by the -scripts installed under the +A set of builtin functions and probe point aliases are provided +by the scripts installed under the .nh .IR /usr/share/systemtap/tapset .hy -directory. +directory. These are described in the +.IR stapfuncs "(5) and " stapprobes (5) +manual pages. .SH PROCESSING The translator begins pass 1 by parsing the given input script, @@ -448,9 +378,9 @@ and all scripts (files named found in a tapset directory. The directories listed with .BR -I -are processed in sequence. For each directory, a number of subdirectories -are also searched. These subdirectories are derived from the selected -kernel version (the +are processed in sequence, each processed in "guru mode". For each +directory, a number of subdirectories are also searched. These +subdirectories are derived from the selected kernel version (the .BR -R option), in order to allow more kernel-version-specific scripts to override less @@ -519,22 +449,10 @@ results in an error condition that prevents further probes from running. Finally, stpd unloads the module, and cleans up. .SH EXAMPLES -To trace entry and exit from a function, use a pair of probes: -.RS -.br -.nf -probe kernel.function("foo") { log ("enter") } -probe kernel.function("foo").return { log ("exit") } -.fi -.RE +See the +.IR stapex (5) +manual page for a collection of samples. -To list the probeable functions in the kernel, use -.RS -.br -.nf -stap -p2 -e 'probe kernel.function("*") {}' -.fi -.RE .SH SAFETY AND SECURITY Systemtap is an administrative tool. It exposes kernel internal data @@ -556,8 +474,17 @@ privileges to untrusted users. The translator asserts certain safety constraints. It aims to ensure that no handler routine can run for very long, allocate memory, perform unsafe operations, or in unintentionally interfere with the -kernel. Use of guru mode constructs such as embedded C can violate -these constraints, leading to kernel crash or data corruption. +kernel. Use of script global variables is suitably locked to protect +against manipulation by concurrent probe handlers. Use of guru mode +constructs such as embedded C can violate these constraints, leading +to kernel crash or data corruption. +.PP +In case something goes wrong with +.IR stap " or " stpd +after a probe has already started running, one may safely kill both +user processes, and remove the active probe kernel module with +.IR rmmod . +Any pending trace messages may be lost. .SH FILES .\" consider autoconf-substituting these directories @@ -590,6 +517,9 @@ The auxiliary program supervising module loading, interaction, and unloading. .SH SEE ALSO +.IR stapprobes (5), +.IR stapfuncs (5), +.IR stapex (5), .IR dtrace (1), .IR dprobes (1), .IR awk (1), diff --git a/stapex.5.in b/stapex.5.in new file mode 100644 index 00000000..f62eb112 --- /dev/null +++ b/stapex.5.in @@ -0,0 +1,118 @@ +.\" -*- nroff -*- +.TH STAPEX 5 @DATE@ "Red Hat" +.SH NAME +stapex \- systemtap examples + +.\" macros +.de SAMPLE +.br +.RS +.nf +.nh +.. +.de ESAMPLE +.hy +.fi +.RE +.. + +.SH LANGUAGE BASICS +These examples give a feel for basic systemtap syntax and +control structures. + +.SAMPLE +global odds, evens + +probe begin { + # "no" and "ne" are local integers + for (i=0; i<10; i++) { + if (i % 2) odds [no++] = i + else evens [ne++] = i + } + delete odds[2] + delete evens[3] + exit () +} + +probe end { + foreach (x in odds) { + log("odds[" . string(x) . "] = " . string(odds[x])) + } + foreach (x in evens) { + log("evens[" . string(x) . "] = " . string(evens[x])) + } +} +.ESAMPLE +This prints: +.SAMPLE +odds[1] = 1 +odds[3] = 5 +odds[4] = 7 +odds[5] = 9 +evens[2] = 2 +evens[4] = 6 +evens[5] = 8 +.ESAMPLE +Note that the evens[1] key is missing, since its value was zero. Any +array element with an "empty" value (zero or empty string) is +considered not present in the array, as if it was deleted. Note that +all variables types are inferred, and that all locals and globals are +initialized. + +.PP +This script prints the primes between 0 and 49. +.SAMPLE +function isprime (x) { + if (x < 2) return 0 + for (i=2; i<x; i++) { + if (x % i == 0) return 0 + if (i * i > x) break + } + return 1 +} +probe begin { + for (i=0; i<50; i++) + if (isprime (i)) log (string(i)) + exit() +} +.ESAMPLE + +.PP +This script demonstrates recursive functions. +.SAMPLE +function fibonacci(i) { + if (i < 1) error ("bad number") + if (i == 1) return 1 + if (i == 2) return 2 + return fibonacci (i-1) + fibonacci (i-2) +} +probe begin { + log ("11th fibonacci number: " . string (fibonacci (11))) + exit () +} +.ESAMPLE +Any larger number may exceed the MAXACTION or MAXNESTING +limits, and result in an error. + + +.SH PROBING + +To trace entry and exit from a function, use a pair of probes: +.SAMPLE +probe kernel.function("sys_mkdir") { log ("enter") } +probe kernel.function("sys_mkdir").return { log ("exit") } +.ESAMPLE + +To list the probeable functions in the kernel, use the last-pass +option to the translator. That output needs to be filtered because +each inlined function instance is listed separately. +.SAMPLE +% stap -p2 -e 'probe kernel.function("*") {}' | sort | uniq +.ESAMPLE + + +.SH SEE ALSO +.IR stap (1) +.IR stapprobes (5) +.IR stapfuncs (5) + diff --git a/stapfuncs.5.in b/stapfuncs.5.in new file mode 100644 index 00000000..597dc674 --- /dev/null +++ b/stapfuncs.5.in @@ -0,0 +1,92 @@ +.\" -*- nroff -*- +.TH STAPFUNCS 5 @DATE@ "Red Hat" +.SH NAME +stapfuncs \- systemtap functions + +.SH DESCRIPTION +The following sections enumerate the public functions provided by +standard tapsets installed under /usr/share/systemtap/tapset. Each +function is described with a signature, and its behavior/restrictions. +The signature line includes the name of the function, the type of +its return value (if any), and the names and types of all parameters. +The syntax is the same as printed with the +.IR stap " option " -p2 . +Examples: + +.TP +example1:long (v:string, k:long) +Function "example1" does something with the given string and integer. +It returns some integer. + +.TP +example2:unknown () +Function "example2" does something. There is no explicit return value +and it takes no parameters. + +.SS LOGGING + +.TP +printk:unknown (msg:string) +Log the given string to the kernel's printk buffer, at KERN_INFO severity. +Append an implicit end-of-line. + +.TP +log:unknown (msg:string) +Log the given string to the common trace buffer. Append an implicit +end-of-line. + +.TP +warn:unknown (msg:string) +Log the given string to the warning stream. Append an implicit end-of-line. +.I stpd +prepends the string "WARNING:". + +.TP +error:unknown (msg:string) +A fatal error has occurred. Log the given string to the error stream. +Append an implicit end-of-line. +.I stpd +prepends the string "ERROR:". +Block any further execution of statements in this probe, block +any new probe handlers, and end the systemtap session as soon +as possible. + +.TP +exit:unknown () +Enqueue a request to shut down the systemtap session. This does +.B not +unwind the current probe handler, nor block new probe handlers. +.I stpd +will shortly respond to the request and initiate an orderly shutdown. + +.SS CONVERSIONS + +.TP +hexstring:string (num:long) +Return a hexadecimal string representation of the given integer, including +the leading "0x". + +.TP +string:string (num:long) +Return a decimal string representation of the given integer. + +.SS TIMESTAMP + +.TP +gettimeofday_ms:long () +Return the number of milliseconds since the UNIX epoch. + +.TP +gettimeofday_s:long () +Return the number of seconds since the UNIX epoch. + +.\" .SS CONTEXTINFO + + +.SH FILES +.nh +.IR /usr/share/systemtap/tapset +.hy + +.SH SEE ALSO +.IR stap (1) diff --git a/stapprobes.5.in b/stapprobes.5.in new file mode 100644 index 00000000..f1a4451b --- /dev/null +++ b/stapprobes.5.in @@ -0,0 +1,181 @@ +.\" -*- nroff -*- +.TH STAPPROBES 5 @DATE@ "Red Hat" +.SH NAME +stapprobes \- systemtap probe points + +.\" macros +.de SAMPLE +.br +.RS +.nf +.nh +.. +.de ESAMPLE +.hy +.fi +.RE +.. + +.SH DESCRIPTION +The following sections enumerate the variety of probe points supported +by the systemtap translator, and additional aliases defined by +standard tapset scripts. +.PP +The general probe point syntax is a "dotted-functor" sequence. This +allows a breakdown of the event namespace into parts, somewhat like +the Domain Name System does on the Internet. Each component +identifier may be parametrized by a string or number literal. These +are all syntactically valid probe points: +.SAMPLE +kernel.function("foo").return +syscall(22) +user.inode("/bin/vi").statement(0x2222) +end +.ESAMPLE + +.SS BEGIN/END + +The probe points +.IR begin " and " end +are defined by the translator to refer to the time of session startup +and shutdown. All "begin" probe handlers are run, in some sequence, +during the startup of the session. All global variables will have +been initialized prior to this point. All "end" probes are run, in +some sequence, during the +.I normal +shutdown of a session, such as in the aftermath of an +.I exit () +function call, or an interruption from the user. In the case of an +error-triggered shutdown, "end" probes are not run. There are no +target variables available in either context. + +.SS TIMERS + +Intervals defined by the standard kernel "jiffies" timer may be used +to trigger probe handlers asynchronously. Two probe point variants +are supported by the translator: +.SAMPLE +timer.jiffies(N) +timer.jiffies(N).randomize(M) +.ESAMPLE +The probe handler is run every N jiffies (a kernel-defined unit of +time, typically between 1 and 60 ms). If the "randomize" component is +given, a linearly distributed random value in the range [-M..+M] is +added to N every time the handler is run. N is restricted to a +reasonable range (1 to around a million), and M is restricted to be +smaller than N. There are no target variables provided in either +context. It is possible for such probes to be run concurrently on +a multi-processor computer. + +.SS DWARF + +This family of probe points uses symbolic debugging information for +the target kernel/module/program, as may be found in unstripped +executables, or the separate +.I debuginfo +packages. They allow placement of probes logically into the execution +path of the target program, by specifying a set of points in the +source or object code. When a matching statement executes on any +processor, the probe handler is run in that context. +.PP +Points in a kernel, which are identified by +module, source file, line number, function name, C label name, or some +combination of these. This kind of "synchronous" event is deemed to +occur when any processor executes an instruction matched by the +specification. Other families of probe points refer to "asynchronous" +events such as timers/counters rolling over, where there is no fixed +execution point that is related. Each probe point specification may +match multiple physical locations, all of which are then probed. A +probe declaration may also contain several comma-separated +specifications, all of which are probed. +.PP +Here is a list of probe point families currently supported. The +.B .function +variant places a probe near the beginning of the named function, so that +parameters are available as context variables. The +.B .return +variant places a probe at the moment of return from the named function, so +the return value is available as the "$retvalue" context variable. +The +.B .statement +variant places a probe at the exact spot, exposing those local variables +that are visible there. +.SAMPLE +kernel.function(PATTERN) +.br +kernel.function(PATTERN).return +.br +module(MPATTERN).function(PATTERN) +.br +module(MPATTERN).function(PATTERN).return +.br +kernel.statement(PATTERN) +.br +module(MPATTERN).statement(PATTERN) +.ESAMPLE +In the above list, MPATTERN stands for a string literal that aims to +identify the loaded kernel module of interest. It may include "*" and +"?" wildcards. PATTERN stands for a string literal that aims to +identify a point in the program. It is made up of three parts. The +first part is the name of a function, as would appear in the +.I nm +program's output. This part may use the "*" and "?" wildcarding +operators to match multiple names. The second part is optional, and +begins with the "@" character. It is followed by a source file name +wildcard pattern, such as +.IR mm/slab* . +Finally, the third part is optional if the file name part was given, +and identifies the line number in the source file, preceded by a ":". +As an alternative, PATTERN may be a numeric constant, indicating an +(module-relative or kernel-absolute) address. +.PP +Some of the source-level variables, such as function parameters, +locals, globals visible in the compilation unit, may be visible to +probe handlers. They may refer to these variables by prefixing their +name with "$" within the scripts. In addition, a special syntax +allows limited traversal of structures, pointers, and arrays. +.TP +$var +refers to an in-scope variable "var". If it's an integer-like type, +it will be cast to a 64-bit int for systemtap script use. If it's +a string-like type (char *), it will be copied into a systemtap +string. +.TP +$var->field +traversal to a structure's field. The indirection operator +may be repeated to follow more levels of pointers. +.TP +$var[N] +indexes into an array. The index is given with a +literal number. + +.SH EXAMPLES +.PP +Here are some example probe points, defining the associated events. +.TP +begin, end, end +refers to the startup and normal shutdown of the session. In this +case, the handler would run once during startup and twice during +shutdown. +.TP +timer.jiffies(1000).randomize(200) +refers to a periodic interrupt, every 1000 +/- 200 jiffies. +.TP +kernel.function("*init*"), kernel.function("*exit*") +refers to all kernel functions with "init" or "exit" in the name. +.TP +kernel.function("*@kernel/sched.c:240") +refers to any functions within the "kernel/sched.c" file that span +line 240. +.TP +module("usb*").function("*sync*").return +refers to the moment of return from all functions with "sync" in the +name in any of the USB drivers. +.TP +kernel.statement(0xc0044852) +refers to the first byte of the statement whose compiled instructions +include the given address in the kernel. + + +.SH SEE ALSO +.IR stap (1) diff --git a/systemtap.spec.in b/systemtap.spec.in index 22dc7ba0..6711b35a 100644 --- a/systemtap.spec.in +++ b/systemtap.spec.in @@ -112,6 +112,7 @@ rm -rf ${RPM_BUILD_ROOT} %{_bindir}/stap %{_mandir}/man1/* +%{_mandir}/man5/* %{_libexecdir}/systemtap/* %dir %{_datadir}/systemtap diff --git a/translate.cxx b/translate.cxx index 71241d00..a8d768ae 100644 --- a/translate.cxx +++ b/translate.cxx @@ -564,8 +564,15 @@ c_unparser::emit_common_header () for (unsigned j=0; j<dp->locals.size(); j++) { vardecl* v = dp->locals[j]; - o->newline() << c_typename (v->type) << " " - << c_varname (v->name) << ";"; + try + { + o->newline() << c_typename (v->type) << " " + << c_varname (v->name) << ";"; + } catch (const semantic_error& e) { + semantic_error e2 (e); + if (e2.tok1 == 0) e2.tok1 = v->tok; + throw e2; + } } c_tmpcounter ct (this); dp->body->visit (& ct); @@ -580,15 +587,29 @@ c_unparser::emit_common_header () o->indent(1); for (unsigned j=0; j<fd->locals.size(); j++) { - vardecl* v = fd->locals[j]; - o->newline() << c_typename (v->type) << " " - << c_varname (v->name) << ";"; + vardecl* v = fd->locals[j]; + try + { + o->newline() << c_typename (v->type) << " " + << c_varname (v->name) << ";"; + } catch (const semantic_error& e) { + semantic_error e2 (e); + if (e2.tok1 == 0) e2.tok1 = v->tok; + throw e2; + } } for (unsigned j=0; j<fd->formal_args.size(); j++) { vardecl* v = fd->formal_args[j]; - o->newline() << c_typename (v->type) << " " - << c_varname (v->name) << ";"; + try + { + o->newline() << c_typename (v->type) << " " + << c_varname (v->name) << ";"; + } catch (const semantic_error& e) { + semantic_error e2 (e); + if (e2.tok1 == 0) e2.tok1 = v->tok; + throw e2; + } } c_tmpcounter ct (this); fd->body->visit (& ct); @@ -1590,7 +1611,8 @@ c_unparser::visit_literal_number (literal_number* e) { // This looks ugly, but tries to be warning-free on 32- and 64-bit // hosts. - o->line() << "((uint64_t)" << e->value << "LL)"; + // NB: this needs to be signed! + o->line() << "((int64_t)" << e->value << "LL)"; } |