刚学systemtap不久,没有找到双指针或者多级指针的解引用api,只好自己实现一个了。
#include <stdio.h>
struct test {
char *a;
int b;
};
static void func(const char *pstr, const char **ppstr, struct test *pt, struct test **ppt, struct test ***pppt)
{
printf("pstr: %s, *ppstr: %s\n", pstr, *ppstr);
printf("pt->a: %s, pt->b: %d: \n", pt->a, pt->b);
printf("(*ppt)->a: %s, (*ppt)->b: %d: \n", (*ppt)->a, (*ppt)->b);
printf("(**pppt)->a: %s, (**pppt)->b: %d: \n", (**pppt)->a, (**pppt)->b);
}
int main(int argc, char *argv[])
{
const char *pstr = "Hello World!";
struct test t = {
.a = "aabbcc",
.b = 11
};
struct test *pt = &t;
struct test **ppt = &pt;
func(pstr, &pstr, pt, ppt, &ppt);
return 0;
}
文件名为cc_deref.c
编译:gcc -Wall -g -o cc_deref ./cc_deref.c
下面是cc_deref.stp脚本:
function deref:long(ptr:long)
%{
STAP_RETURN(*(void **)STAP_ARG_ptr);
%}
probe process("cc_deref").statement("func@./cc_deref.c:10")
{
printf("-------------------------------------------------------------\n");
printf("$$vars: %s\n", $$vars);
printf("$pstr: %p, user_string($pstr): %s\n", $pstr, user_string($pstr));
printf("$ppstr: %p, user_string($ppstr): %s, user_string(deref($ppstr)): %s\n", $ppstr, user_string($ppstr), user_string(deref($ppstr)));
pt1 = $pt;
pt2 = deref($ppt);
pt3 = deref(deref($pppt));
printf("pt1: %p, pt2: %p, pt3: %p\n", pt1, pt2, pt3);
printf("$pt=>a: %s, $pt->a: %s, $pt->b: %d\n", user_string(@cast($pt, "struct test")->a), user_string($pt->a), $pt->b);
printf("pt1=>a: %s, pt1->b: %d\n", user_string(@cast(pt1, "struct test")->a), pt1->b);
printf("$ppt=>a: %s, $ppt->a: %s, $ppt->b: %d\n", user_string(@cast($ppt, "struct test")->a), user_string($ppt->a), $ppt->b);
printf("pt2=>a: %s, pt2->b: %d\n", user_string(@cast(pt2, "struct test")->a), @cast(pt2, "struct test")->b);
printf("$pppt=>a: %s, $pppt->a: %s, $pppt->b: %d\n", user_string(@cast($pppt, "struct test")->a), user_string($pppt->a), $pppt->b);
printf("pt3=>a: %s, pt3->b: %d\n", user_string(@cast(pt3, "struct test")->a), @cast(pt3, "struct test")->b);
printf("-------------------------------------------------------------\n");
exit();
}
其实主要是嵌入C代码来达到解引用的目的,函数deref就一行代码,不过返回的是void *指针,需要用@cast来转换成你需要的类型。
运行:stap -gu -c ./cc_deref cc_deref.stp 注意别漏了-gu参数,这个参数是嵌入C代码必须的参数。
pt1为$pt,是一维指针,$ppt是二维指针,解引用后得到一维指针pt2,$pppt是三维指针,经过两次解引用后得到一维指针pt3,从运行结果可以看出pt1,pt2,pt3的值是一样的,用@cast转换指针后再用user_string读取a的内容也一样,结合cc_deref.c代码符合预期。
但,cc_deref.stp第18、20、22行直接user_string($pt->a)、user_string($ppt->a)、user_string($pppt->a)都能直接得到a的内容,这个就有点不好理解了,如果哪位大神知道,希望不吝赐教。
systemtap文章参考:
http://blog.csdn.net/justlinux2010/article/details/17653601