This is the mail archive of the systemtap@sources.redhat.com mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Sample tapset source file


In an effort to inject some new perspective into the tapset discussion,
I hereby enclose what I claim to be a complete, non-trivial tapset
source file.  I explain the enhancements to the systemtap language that
I felt obliged to postulate in order to code this tapset.  No, I have
not implemented these enhancements.  Comments welcome.  Sorry for any
formatting glitches.

Jim

What does a tapset provide?
1. It defines (and optionally names) probepoints of interest.
2. For a probepoint, it "exports" named values that are of interest in
that context, for use by client probepoint (handler) functions.
3. For a probepoint, it may define one or more handlers -- e.g., the
standard "trace" handler.
4. It may define SystemTap auxiliary functions for use by other
SystemTap authors.
5. It may define C functions for use by other SystemTap authors.
                                                                                                                             
Enclosed is a sample tapset source file, written in a somewhat enhanced
systemtap language.  (See "ENHANCEMENTS / NEW IDEAS" for a summary of
these enhancements.)
                                                                                                                             
The first part of the file consists mostly of C source code, set off by
%{ and %} lines as in yacc.  This C source serves the following
purposes:
a. It pulls in kernel headers that define macros of interest -- for
example, O_RDONLY and S_IROTH.
b. It provides support for SystemTap auxiliary functions.  For example,
the auxiliary function open_flags_string() calls the C function
fcntl_flags_string(), which in turn calls the (TBD) SystemTap runtime
function _stp_flags_string().
c. It provides support for accessing values in the context of the probed
function.  For example, the C functions
get_filename_from_locked_filetable() and
get_filename_from_possibly_locked_filetable() are used in contexts where
we have a valid struct file pointer and we want the associated filename.
                                                                                                                             
A tapset source file can have multiple sections of C code, each set off
by %{ and %}.  All this C code will show up in the .c file created by
SystemTap.  The systemtap compiler also copies it off to a temporary C
file and compiles it with cc -c -g3. (We include #line directives so
that any error messages refer to line numbers in the original tapset
source file.)  The systemtap compiler doesnât need to parse the C code,
but it will need to find the appropriate debug information for the
macros and functions referred to in the accompanying systemtap source
code.
                                                                                                                             
Aside from the aforementioned C code, the systemtap source code contains
the following constructs:
a. systemtap auxilary functions, as previously described in the language
reference section
b. systemtap probe-script definitions, pretty much as previously
described in the language reference section
c. probepoint export specifications.
                                                                                                                             
Probepoint export specifications are new.  Such a specification serves
the following purposes, as mentioned earlier:
1. It defines and names a probepoint.  The name, specified by the
probename("<name>") clause, can be used in this and other SystemTap
scripts as an alias for the full probepoint specification.
2. It exports named values that are of interest in that context, for use
by probepoint scripts.
3. It can define one or more handlers.
                                                                                                                             
For example, the following export
specification                                                                                                                           
export kernel.function("filp_open").entry
        .probename("open_with_filename")
{
        const {
                filename;
                flags;
                flags_string = open_flags_string(flags);
                mode;
                mode_string = open_mode_string(mode);
        }
        handler trace {
                _stp_log("%s (%s, %#o (%s), %#o (%s))\n", $probee,
                        filename, flags, flags_string, mode,
			mode_string);
        }
}
                                                                                                                             
defines a probepoint and assigns it the alias "open_with_filename".  It
specifies that a script for that probepoint has read-only access to the
values filename, flags, and mode in that context, using those same
names.  It also exports the manufactured values flags_string and
mode_string.  For example, the following client handler, when translated
to C,
                                                                                                                             
probe probename("open_with_filename").handler("mini_trace")
{
        _stp_log("open: path=%s, flags= %s\n", filename, flags_string)
}
                                                                                                                             
will include code to do the following:
a. Compute the value of the filename and flags args.
b. Call the auxiliary function open_flags_string(), passing it the flags
arg, to get a string representation of the flags.
c. Call the _stp_log function, passing it the filename and the result of
the open_flags_string() call.
d. Recycle the memory allocated by open_flags_string().
                                                                                                                             
I think that naming probepoints will be important because:
- it provides a convenient handle for use by other tapset code and
client probe handlers, especially where the probepoint is
not a simple function entry or return; and
- it provides a handle for external commands -- e.g., for enabling and
disabling specific handlers.
                                                                                                                          
Also included in this tapset are one or more standard "trace" handlers
for each probepoint.  Perhaps by default, when a tapset is enabled, all
the handlers named "trace" are enabled.  Since the tapset author and/or
users could define multiple handlers for the same probepoint, it seems
wise to allow for the naming of handlers.
                                                                                                                             
In this example, Iâve adopted a convenient shorthand for defining
handlers within a tapset.  Instead of having to write something like
                                                                                                                             
probe kernel.syscall("close").entry.handler("trace")
{
        _stp_log("%s (%d)\n", $probee, fd);
}
                                                                                                                             
outside the corresponding probepoint export specification, I write
                                                                                                                             
handler trace {
        _stp_log("%s (%d)\n", $probee, fd);
}
                                                                                                                             
within the probepoint export specification.
                                                                                                                             
A handler has access to the following types of identifiers:
1. systemtap variables of file scope (declared with the "global"
statement)
2. systemtap auxiliary functions
3. systemtap variables that are local to the handler
4. named values (in the context of the probed function) that have been
exported by the probepoint export specification
5. for expert scripts: variables in the context of the probed function. 
(Frank suggests that such a name be distinguished by one or more leading
dollar signs.  In this example, there are no such variables, because all
such values are exported.)
6. for expert scripts: file-scope variables, functions, macros, and
other identifiers that are defined in the accompanying C
code.
                                                                                                                             
There is currently no way, by looking solely at the text of a probepoint
script, to tell whether a variable is of type 1, 3,
4, or 6.
                                                                                                                             
Note that a probepoint export specification can define exports for
multiple probepoints -- e.g.,
                                                                                                                             
export
        kernel.syscall("creat").entry,
        kernel.syscall("open").entry
{
...
                                                                                                                             
This is based on an existing similar feature for probepoint definitions.
                                                                                                                             
ENHANCEMENTS / NEW IDEAS
1. A tapset source file may contain C code set off by %{ and %} lines. 
The systemtap compiler compiles a copy of this C code with cc âc âg3 so
it can find the necessary macro, function, and struct declarations
without having to parse the C code.

2. Systemtap source code in the tapset source file can refer to
identifiers in the accompanying C code.

3. Probepoint export specifications define which named values are
exported to client handler functions.

4. Probepoints can be named using the probename("<name>") clause. 
References to this probepoint can use the name instead of
the entire probepoint specification.

5. Handlers can be named using the handler("<name>") clause.

6. Certain handler names -- e.g., "trace" -- have special meanings.

7. A probepoint specification can include a context("<sourceline>")
clause, so that the probepoint stays on the right source
line even when the line number changes.

8. The systemtap language should support certain predefined values,
including at least the following:
	- $retval -- defined in function-return handlers; evaluates to the
probed function's return value, if any.
	- $probee -- defined in any handler the corresponds to a probepoint in
a function (or upon entry to or return from a function); evaluates to
the function's name.

9. The SystemTap runtime library should provide the following functions:
	- _stp_flags_string() takes a bitmap and an array of name-value pairs. 
Each name-value pair maps a bit to a name (e.g., O_CREAT to "O_CREAT"). 
This function creates a string that shows which bits are set in the
bitmap -- e.g., "O_WRONLY |O_CREAT |O_TRUNC".  This function may need to
be passed some sort of string or memory handle so that the memory
occupied by the return value can be freed at the appropriate time.
	- _stp_strerror() takes an int (or long long?) and returns the
corresponding error name.  E.g., _stp_strerror(-12) returns "-ENOMEM".

Attachment: io.stp
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]