2013年8月18日星期日

SystemTap----常用变量、宏、函数和技巧

后面会持续更新,方便自己,方便大家.......
一、宏
1. kderef
从指定的地址处读取指定大小的值
格式为:
kderef(size, address);
其中address为要读取的地址值,size是要是读取的值的大小,返回值就是所读取的值。
2.kread
在嵌入的C代码中安全地读取指针值
格式为:
kread(&(address))
二、函数
1.execname()
获取当前进程的名称,即可执行文件的名称
2. pid()
获取当前进程的PID
3.pp()
获取当前的probe点。例如 probe process.syscall,process.end { /* scripts */},在块中调用pp()可能会返回"process.syscall"和"process.end"。
4.probefunc()
获取当前probe的函数名称。例如probe sys_read函数,在probe块中调用该函数就会返回sys_read。
三、技巧
1.@cast()操作
如果将一个获取的值(可能是一个类型的地址值)存储到SystemTap中定义的变量,但是在读取的时候需要根据特定的类型去读取,此时,可以使用@cast()操作来读取。
其格式为
@cast(p, "type_name"[,"module"])->member
在systemtap中使用cast来将指定的地址值转换为C语言中的类型,并且可以去获取相应的值(例如结构体成员)示例如下
function is_tcp_packet:long(iphdr) {
protocol = @cast(iphdr, "iphdr")->protocol
return (protocol == %{ IPPROTO_TCP %}) /* <-- expression */ }
如果是在probe内,还可以直接使用$ptr来获取成员的值,例如:
probe begin {
printf("SystemTap Scripts start.....\n");
}

probe kernel.function("tcp_v4_rcv") {
printf("skb->len = %d\n", $skb->len);
}

@cast()操作中还可以指定类型所在的头文件,示例如下:
@cast(tv, "timeval", "<sys/time.h>")->tv_sec
@cast(task, "task_struct", "kernel<linux/sched.h>")->tgid
2.在使用嵌入C代码作为函数体的辅助函数中获取参数和设置返回值
如果版本是1.8或更新的,则使用STAP_ARG_(参数名)来获取参数,例如STAP_ARG_arg,其中arg是参数名。设置返回值的形式是STAP_RETVALUE=value。
如果版本是1.7或更老的,则使用THIS->(参数名)来获取参数,例如THIS->arg,其中arg是参数名。设置返回值的形式是THIS->__retvalue=value。
3.获取probe函数的参数
如果带debuginfo,即DWARF probes,则可以直接使用参数的名称加'$'即可,例如sys_read()中的第一个参数fd,就可以通过$fd来获取其值。
如果缺少debuginfo,即DWARF-less probing,则需要通过uint_arg(),pointer_arg()和ulong_arg()等来获取,这些函数都需要指定当前要获取的参数是第几个参数,编号从1开始。例如asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)中,uint_arg(1)获取的是fd的值,pointer_arg(2)获取的是buf的地址值,ulong_arg(3)获取的是count参数。更多的获取参数的函数参见man page index
如果是通过process.syscall、process("PATH").syscall或者process(PID).syscall来probe系统调用,则可以通过$syscall来获取系统调用号,通过$arg1,$arg2等来获取相应的参数值。
在probe用户程序时,可以通过$$parms来获取所有的参数(是字符串,不是具体的值)。
4."."字符窜连接符
如果想将一个函数返回的字符串和一个常量字符串拼接,则在两者之间加入"."即可,例如probefunc()."123"。
"."运算符还支持".=",即拼接后赋值。
5、获取stap命令行参数
如果要获取命令行参数准确的值,则使用$1、$2....$<NN>来获取对应的参数。如果想将命令行参数转换为字符串,则使用@1、@2...@<NN>来获取参数对应的字符串。
6、next操作
如果在probe函数中,发现某个条件没有满足,则结束本次probe的执行,等待下次事件的到来。示例如下:


global i

probe begin {
printf("SystemTap Scripts start.....\n");
}

probe kernel.function("sys_read") {
++i;
if (i % 2) {
next;
}
printf("i = %d\n", i);
}

没有评论:

发表评论