Tapset Development Guidelines
This chapter describes the upstream guidelines on proper tapset documentation. It also contains
information on how to properly document your tapsets, to ensure that they are properly
defined in this guide.
Writing Good Tapsets
The first step to writing good tapsets is to create a simple model of your subject area. For
example, a model of the process subsystem might include the following:
Key Data
process ID
parent process ID
process group ID
State Transitions
forked
exec'd
running
stopped
terminated
Note
Both lists are examples, and are not meant to represent a complete list.
Use your subsystem expertise to find probe points (function entries and
exits) that expose the elements of the model, then define probe aliases
for those points. Be aware that some state transitions can occur in more
than one place. In those cases, an alias can place a probe in multiple
locations.
For example, process execs can occur in either the do_execve() or the
compat_do_execve() functions. The following alias inserts probes at the
beginning of those functions:
probe kprocess.exec = kernel.function("do_execve"),
kernel.function("compat_do_execve")
{probe body}
Try to place probes on stable interfaces (i.e., functions
that are unlikely to change at the interface level) whenever possible. This will
make the tapset less likely to break due to kernel changes. Where
kernel version or architecture dependencies are unavoidable, use
preprocessor conditionals (see the stap(1) man page for details).
Fill in the probe bodies with the key data available at the probe points.
Function entry probes can access the entry parameters specified to
the function, while exit probes can access the entry parameters and the
return value. Convert the data into meaningful forms where appropriate
(e.g., bytes to kilobytes, state values to strings, etc).
You may need to use auxiliary functions to access or convert some of the data. Auxiliary
functions often use embedded C to do things that cannot be done in the
SystemTap language, like access structure fields in some contexts, follow
linked lists, etc. You can use auxiliary functions defined in other tapsets
or write your own.
In the following example, copy_process() returns a
pointer to the task_struct for the new process. Note
that the process ID of the new process is retrieved by calling
task_pid() and passing it the task_struct
pointer. In this case, the auxiliary function is an embedded C function
defined in task.stp.
probe kprocess.create = kernel.function("copy_process").return
{
task = $return
new_pid = task_pid(task)
}
It is not advisable to write probes for every function. Most SystemTap users
will not need or understand them. Keep your tapsets simple and high-level.
info from here:http://sources.redhat.com/git/?p=systemtap.git;a=blob_plain;f=tapset/DEVGUIDE
Elements of a Tapset
The following sections describe the most important aspects of writing a tapset. Most of
the content herein is suitable for developers who wish to contribute to
SystemTap's upstream library of tapsets.
Tapset Files
Tapset files are stored in src/tapset/
of the SystemTap GIT directory. Most tapset files are kept at that level. If you have
code that only works with a specific architecture or kernel version, you may
choose to put your tapset in the appropriate subdirectory.
Installed tapsets are located in /usr/share/systemtap/tapset/
or /usr/local/share/systemtap/tapset.
Personal tapsets can be stored anywhere. However, to ensure that SystemTap
can use them, use -I tapset_directory
to specify their location when invoking stap.
Namespace
Probe alias names should take the form
tapset_name.probe_name.
For example, the probe for sending a signal could be named
signal.send.
Global symbol names (probes, functions, and variables) should be unique
accross all tapsets. This helps avoid namespace collisions in scripts
that use multiple tapsets. To ensure this, use tapset-specific
prefixes in your global symbols.
Internal symbol names should be prefixed with an underscore
(_).