try {
/* do something */
/* trigger error like kread(0), or divide by zero, or error("foo") */
} catch (msg) { /* omit (msg) entirely if not interested */
/* println("caught error ", msg) */
/* handle error */
}
/* execution continues */
foreach
// The array must not be modified within the statement. If you add a single plus (+) or minus (-) operator after the VAR or the ARRAY identifier, the iteration order will be sorted by the ascending or descending index or value
foreach (VAR in ARRAY) STMT
// The following statement behaves the same as the first example, except it is used when an array is indexed with a tuple of keys. Use a sorting suffix on at most one VAR or ARRAY identifier.
foreach ([VAR1, VAR2, ...] in ARRAY) STMT
// You can combine the first and second syntax to capture both the full tuple and the keys at the same time as follows.
foreach (VAR = [VAR1, VAR2, ...] in ARRAY) STMT
foreach (VAR in ARRAY limit EXP) STMT
limit keyword limits the number of loop iterations to EXP times
function
语法:
function <name>[:<type>] ( <arg1>[:<type>], ... )[:<priority>] { <stmts> }
ctime() convert number of seconds since UNIX epoch to date
pp() A string describing the probe point currently being handled.
thread_indent()
嵌入C
语法
function <name>:<type> ( <arg1>:<type>, ... )[:<priority>] %{ <C_stmts> %}
所有的在%{和%}之间的,都是C代码。在使用的时候,需要格外小心。
具体的例子:
%{
#include <linux/in.h>
#include <linux/ip.h>
%} /* <-- top level */
/* Reads the char value stored at a given address: */
function __read_char:long(addr:long) %{ /* pure */
STAP_RETURN(kderef(sizeof(char), STAP_ARG_addr));
CATCH_DEREF_FAULT ();
%} /* <-- function body */
/* Determines whether an IP packet is TCP, based on the iphdr: */
function is_tcp_packet:long(iphdr) {
protocol = @cast(iphdr, "iphdr")->protocol
return (protocol == %{ IPPROTO_TCP %}) /* <-- expression */
}
foo["tom"] = 23
foo["dict"] = 24
foo["harry"] = 25
device[pid(),execname(),uid(),ppid(),"W"] = devname // 关联了多个值作为key
global foo # foo gets the default size
global bar[100] # bar will have 100 slots
if (42 in foo) println("foo has 42")
if (["bar", 42] in foo) println("foo has [\"bar\", 42]")
foreach (x in foo) printf("foo[%d] = %d\n", x, foo[x])
foreach ([s, x] in foo)
printf("foo[%s, %d] = %d\n", s, x, foo[x])
The predicate @defined() is available for testing whether a particular $variable/expression is resolvable at translation time. The following is an example of its use:
preprocessor macros
语法:
@define NAME %( BODY %)
@define NAME(PARAM_1, PARAM_2, ...) %( BODY %)
资源
安装
查看某一行的值
探测点
统计
关系运算符
其中,The =~ and !~ operators 执行正则匹配,=~表示返回1,!~则表示相反。
Pointer typecasting
具体的使用:
try...catch
foreach
function
语法:
基本的例子:
嵌入C
语法
所有的在%{和%}之间的,都是C代码。在使用的时候,需要格外小心。
具体的例子:
嵌入的评论
嵌入C语言中访问全局变量
常见的probes
选项
资料来源
定位函数位置
可以看出printf是在printf.c第29行定义的。再比如要看内核中recv系统的调用是在哪里定义的:
同理,也可以用来定位用户进程的函数位置: 比如tengine的文件ngx_shmem.c里面为了兼容各个操作系统而实现了三个版本的ngx_shm_alloc,用#if (NGX_HAVE_MAP_ANON)、#elif (NGX_HAVE_MAP_DEVZERO)、#elif (NGX_HAVE_SYSVSHM)、#endif来做条件编译,那怎么知道编译出来的是哪个版本呢,用SystemTap的话就很简单了,否则要去grep一下这几宏有没有定义才知道了。
例子
使用
关联数组
命令行参数
使用:
kernel profiling
条件编译
condition条件
@defined
preprocessor macros
语法:
引用的时候,在符号的名称上加上@
所以下面的代码是错误的:
查看当前文件的探测点
target_variable
访问静态全局变量target_variable
一个简单的例子来练习stap
查看可用的探测点
打出函数调用栈