Strings are enclosed in quotation marks (``string''), and pass through standard C escape codes with backslashes. A string literal may be split into several pieces, which are glued together, as follows.
str1 = "foo" "bar"
/* --> becomes "foobar" */
str2 = "a good way to do a multi-line\n"
"string literal"
/* --> becomes "a good way to do a multi-line\nstring literal" */
str3 = "also a good way to " @1 " splice command line args"
/* --> becomes "also a good way to foo splice command line args",
assuming @1 is given as foo on the command line */
Observe that script arguments can also be glued into a string literal.
Strings are limited in length to MAXSTRINGLEN. For more information
about this and other limits, see Section
.
# ... shell style, to the end of line // ... C++ style, to the end of line /* ... C style ... */
= .=
=~ !~
The regular expression matching (=~ and !~) is
currently an experimental feature. The second operand must be a string
literal containing a syntactically valid regular expression. The
regular expression syntax supports most of the features of POSIX
Extended Regular Expressions, aside from subexpression reuse
(\1) and named character classes ([:digit:],
[:alpha:], ...). The ability to capture and extract the
contents of the matched string and subexpressions has not yet been
implemented.
fn ([ arg1, arg2, ... ])
Typecasting is supported using the @cast() operator. A script can define a pointer type for a long value, then access type members using the same syntax as with $target variables. After a pointer is saved into a script integer variable, the translator loses the necessary type information to access members from that pointer. The @cast() operator tells the translator how to read a pointer.
The following statement interprets p as a pointer to a struct or union named type_name and dereferences the member value:
@cast(p, "type_name"[, "module"])->member
The optional module parameter tells the translator where to look for information about that type. You can specify multiple modules as a list with colon (:) separators. If you do not specify the module parameter, the translator defaults to either the probe module for dwarf probes or to kernel for functions and all other probe types.
The following statement retrieves the parent PID from a kernel task_struct:
@cast(pointer, "task_struct", "kernel")->parent->tgid
The translator can create its own module with type information from a header surrounded by angle brackets (< >) if normal debugging information is not available. For kernel headers, prefix it with kernel to use the appropriate build system. All other headers are built with default GCC parameters into a user module. The following statements are examples.
@cast(tv, "timeval", "<sys/time.h>")->tv_sec @cast(task, "task_struct", "kernel<linux/sched.h>")->tgid
In guru mode, the translator allows scripts to assign new values to members of typecasted pointers.
Typecasting is also useful in the case of void* members whose type might be determinable at run time.
probe foo {
if ($var->type == 1) {
value = @cast($var->data, "type1")->bar
} else {
value = @cast($var->data, "type2")->baz
}
print(value)
}
The number of index values must match the number of indexes previously specified.
.
For information about strings, see Section
.
Script arguments at the end of a command line are expanded as literals. You can use these in all contexts where literals are accepted. A reference to a nonexistent argument number is an error.
Use @1 ... @<NN> for casting an entire argument as a string literal.
For example, if the following script named example.stp
probe begin { printf("%d, %s\n", $1, @2) }
# stap example.stp '5+5' mystring
10, mystring
).
%( CONDITION %? TRUE-TOKENS %) %( CONDITION %? TRUE-TOKENS %: FALSE-TOKENS %)
%( <condition> %? <code> [ %: <code> ] %)
probe foo { if (@defined($bar)) log ("$bar is available here") }
kernel_v refers to the kernel version number only, such as ``2.6.13".
kernel_vr refers to the kernel version number including the release code suffix, such as ``2.6.13-1.322FC3smp''.
If the first part of the conditional expression is the identifier
systemtap_privilege which refers to the privilege level the
systemtap script is being compiled with, then the second part is a
string comparison operator ''=='' or ''!='', and the third part is a
string literal for matching it. This comparison is a simple string
equality or inequality. The possible privilege strings to consider
are "stapusr" for unprivileged scripts, and "stapsys" or
"stapdev" for privileged scripts. (In general, to test for a
privileged script it is best to use != "stapusr".)
This condition can be used to write scripts that can be run in both privileged and unprivileged modes, with additional functionality made available in the privileged case.
%( kernel_v <= "2.6.5" %? **ERROR** %) # invalid token sequence
probe kernel.function (
%( kernel_v <= "2.6.12" %? "__mm_do_fault" %:
%( kernel_vr == "2.6.13-1.8273FC3smp" %? "do_page_fault" %: UNSUPPORTED %)
%)) { /* ... */ }
%( arch == "ia64" %?
probe syscall.vliw = kernel.function("vliw_widget") {}
%)
The following code adapts to the presence of a kernel CONFIG option.
%( CONFIG_UTRACE == "y" %?
probe process.syscall {}
%)
This is an experimental feature whose semantics are subject to change.
The preprocessor also supports a simple macro facility.
Macros taking zero or more arguments are defined using the following construct:
@define NAME %( BODY %) @define NAME(PARAM_1, PARAM_2, ...) %( BODY %)
Macro arguments are referred to in the body by prefixing the argument name with an @ symbol. Likewise, once defined, macros are invoked by prefixing the macro name with an @ symbol:
@define foo %( x %) @define add(a,b) %( ((@a)+(@b)) %) @foo = @add(2,2)
Macro expansion is currently performed in a separate pass before conditional compilation. Therefore, both TRUE- and FALSE-tokens in conditional expressions will be macroexpanded regardless of how the condition is evaluated. This can sometimes lead to errors:
// The following results in a conflict:
%( CONFIG_UTRACE == "y" %?
@define foo %( process.syscall %)
%:
@define foo %( **ERROR** %)
%)
// The following works properly as expected:
@define foo %(
%( CONFIG_UTRACE == "y" %? process.syscall %: **ERROR** %)
%)
The first example is incorrect because both @defines are evaluated in a pass prior to the conditional being evaluated.
Normally, a macro definition is local to the file it occurs in. Thus, defining a macro in a tapset does not make it available to the user of the tapset.
Publically available library macros can be defined by including .stpm files on the tapset search path. These files may only contain @define constructs, which become visible across all tapsets and user scripts.