1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
/** @mainpage SystemTap Runtime
@section intro_sec Introduction
This document describes the implementation of the SystemTap Runtime. It is intended for developers
of the SystemTap Language translator, TapSet authors or kprobes programmers.
These functions are not directly available from the SystemTap Language.
The SystemTap Runtime Library consists of all functions
and code fragments needed by the compiler/translator to
include in building a kernel module using kprobes. It
also include I/O code to transmit its output from the kernel to userspace.
In addition to the library, the runtime includes a SystemTap user-space daemon
(stpd). Stpd grabs data sent from the I/O code in the runtime and displays it
and/or saves it to files. Stpd will handle other issues like
inserting and removing modules.
Stpd and the I/O code make use of both relayfs and netlink for communication. For
kernels without relayfs builtin, it is provided as a standalone module under the runtime directory.
@section design_sec Design
@subsection impl_sec Implementation
The library is written in C and is really not a library but a collection of code
that can be conditionally included in a modules. This allows for a high degree of
customization and efficiency.
@subsection map_sec Maps (Associative Arrays)
Maps are implemented as hash lists. In order to efficiently handle maps with up to five keys of any combination
of int64s and strings, the functions to create maps, set keys, and set and get values
are all generated as needed. To do this, you must simply do some defines and
include the proper files. For example, if you need a map with 3 keys, int64, int64, and string
that stores strings, you need to do
@code
#define KEY1_TYPE INT64
#define KEY2_TYPE INT64
#define KEY3_TYPE STRING
#include "map-keys.c"
#define VALUE_TYPE STRING
#include "map-values.c"
#include "map.c"
@endcode
In the above example, maps are created with _stp_map_new_int64_int64_str(). All the
generated functions start with a base name (such as _stp_map_new) and add the key types separated
by underscores.
Each map can hold only one type of data; int64, string, or statistics. Each element belonging to a map can have up to
5 keys and a value. Implemented key types are strings and int64.
To simplify the implementation, the functions to set the key and the functions to set the data are separated.
The map remembers what the current key is.
For example, to continue our previous example,
@code
/* create a map with a max of 100 elements containing strings */
MAP mymap = _stp_map_new_int64_int64_str(100, STRING);
/* mymap[100, 300, "Ohio"] = "Columbus" */
_stp_map_key_int64_int64_str (mymap, 100, 300, "Ohio");
_stp_map_set_str (mymap, "Columbus");
@endcode
All elements have a default value of 0 (or NULL). Elements are only saved to the map when their value is set
to something nonzero.
For good examples, see the runtime/tests/maps directory or the example probes.
@subsection list_sec Lists
A list is a special map which has internally ascending int64 keys. Adding a value to
a list does not require setting a key first. Create a list with _stp_list_new(). Add to it
with _stp_list_add_str() and _stp_list_add_int64(). Clear it with _stp_list_clear().
@subsection string_sec Strings
One of the biggest restrictions the library has is that it cannot allocate things like strings off the stack.
It is also not a good idea to dynamically allocate space for strings with kmalloc(). That leaves us with
statically allocated space for strings. This is what is implemented in the String module. Strings use
preallocated per-cpu buffers and are safe to use (unlike C strings).
@subsection io_sec I/O
Generally things are written to a "print buffer" using the internal
functions _stp_print_xxx().
\code
_stp_print ("Output is: ");
_stp_printf ("pid is %d ", current->pid);
_stp_printf ("name is %s", current->comm);
\endcode
before the probe returns it must call _stp_print_flush(). This
timestamps the accumulated print buffer and sends it to relayfs.
When relayfs fills an internal buffer, the user-space daemon is notified
data is ready and reads a bug per-cpu chunk, which contains a line like:
\verbatim
[123456.000002] Output is: pid is 1234 name is bash
\endverbatim
The user-daemon (stpd) saves this data to a file named something like
"stpd_cpu2". When the user hits ^c, a timer expires, or the probe
module notifies stpd (through a netlink command channel) that it wants
to terminate, stpd does "system(rmmod)" then collects the last output
before exiting.
As an option, if we don't need bulk per-cpu data, we can put
\code
#define STP_NETLINK_ONLY
\endcode
at the top of the module and all output will go over a netlink channel.
In the SystemTap language, we will provide some simple functions to control the buffering policy, which
will control the use of netlink and parameters to relayfs and stpd.
@section started Getting Started
@verbatim
>cd stp/src/runtime
>cd stpd
> make
>cd ../relayfs
> make
> cd ../transport
make
> cd ../probes/shellsnoop
> make
> su
> ./stp shellsnoop.ko
@endverbatim
When building the example probes, ignore the warnings about relayfs and
_stp_ctrl_xxx functions undefined. These are in other modules.
Hit ^C to exit from a probe.
@section probe_sec Example Probes
Working sample probe code using the runtime is in runtime/probes.
<a href="dir_000000.html"> Browse probes.</a>
@section todo_sec ToDo
\link todo Click Here for Complete List \endlink
@section links Links
<a href="http://sources.redhat.com/systemtap/">SystemTap Project Page</a>
*/
|