利用systemtap脚本打印变量或参数

本文介绍了如何使用SystemTap脚本获取和修改C程序中数据结构的成员,包括打印整个数据结构、修改函数变量及获取结构体数组的值。通过实例详细解析了SystemTap语法,如使用`->`访问结构成员,以及`$`用于获取基本类型值的字符串表示。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

1、获取数据结构成员

   比如数据结构如下:

root@jusse ~/develop# cat -n cc_stap_test.c  

#include <stdio.h>  

typedef struct str {  

     int    len;  

     char *data;  

 } str_t;  

   

 typedef struct policy {  

     str_t    name;  

     int     id;  

 } policy_t;  

   

 int main(int argc, char *argv[])  

 {  

     policy_t policy;  

     policy_t *p = &policy;  

   

     p->id = 111;  

     p->name.data = "test";  

     p->name.len = sizeof("test")-1;  

   

     printf("p->id: %d, p->name.data: %s, p->name.len: %d\n", p->id, p->name.data, p->name.len);  

   

     return 0;  

 }  

 

root@jusse ~/develop# gcc -Wall -g -o cc_stap_test ./cc_stap_test.c  

   如果要在第22行设置个statement探测点获取局部变量p中name的data,那怎么写stp呢,这个问题在刚学SystemTap时困扰了我两天,不过后来仔细看官方文档时才知道,最直觉的写法就像下面这个:

probe process("./cc_stap_test").statement("main@./cc_stap_test.c:22")  

{  

   printf("policy name: %s\n", $p->name.data);  

}  

$p是指针,通过->箭头可以直接访问name,这个没有问题,但name不是指针而是一个结构啊,难道不是像C语言一样用点号来访问它里面的成员吗。这是C语言的思路,可惜是不对的,SystemTap已经把点号用来做字符串连接符了,所以 SystemTap把结构变量或者结构指针变量统一对待,都是通过->来访问结构里面或者结构指针所指结构里面的成员 ,上面例子正确写法如下:

probe process("./cc_stap_test").statement("main@./cc_stap_test.c:22")  

{  

   printf("policy name: %s\n", $p->name->data);  

}  

2、打印整个数据结构

    在调试的时候,有时我们需要输出整个数据结构,看看结构里面变量的值到底是什么。比如上面的例子中我们想打印变量p中所有成员的值,应该是这样:

root@jusse ~/develop# cat cc_stap_test.stp  

probe process("./cc_stap_test").statement("main@./cc_stap_test.c:22")  

{  

       printf("$p$: %s", $p$$);

}  

 

root@jusse ~/develop# stap cc_stap_test.stp -c './cc_stap_test'          

p->id: 111, p->name.data: test, p->name.len: 4  

$p$: {.name={...}, .id=111}, $p$$: {.name={.len=4, .data="test"}, .id=111}  

root@jusse ~/develop#  

    就是在 变量的后面加$,   或者,其中 加$是表示获取结构中基本数据类型的字符串值 ,像上面$p$就只输出id的值,name就省略了;变量后面加功能与加一个$类似,只是它要展开结构里面的结构,上面的输出已经很明显了。

问题:

[root@localhost stap_test]# stap cc_stap_test.stp -c './cc_stap_test'

semantic error: type mismatch (long vs. string) : identifier '$p' at cc_stap_test.stp:3:30

       source:        printf("policy name: %s\n", $p->name->data);

                                                   ^

Pass 2: analysis failed.  [man error::pass2]

Number of similar error messages suppressed: 1.

Rerun with -v to see them.

原因:

printf("policy name: %s\n", $p->name->data);  

这里要打印的是字符串,但$p->name->data后面没有加$符号,所以报type mismatch (long vs. string)这种错误

解决:

$p->name->data$,这样就是打印字符串了,其中 加$是表示获取结构中基本数据类型的字符串值 ,若打印数值则不用加$

3、修改函数变量

    还是上面的例子,cc_stap_test.c第18行给id赋了值111,在第20行,我们也可以用SystamTap修改id的值:

root@jusse ~/develop# cat cc_stap_set_var.stp  

probe process("./cc_stap_test").statement("main@./cc_stap_test.c:20")  

{  

   $p->id = 222;  

   printf("$p$: %s, $p$);  

}  

 

root@jusse ~/develop# stap -g cc_stap_set_var.stp -c './cc_stap_test'  

p->id: 222, p->name.data: test, p->name.len: 4  

$p$: {.name={...}, .id=222}, $p$$: {.name={.len=0, .data="test"}, .id=222}  

    直接赋值即可,只是需要注意的是stap要加-g参数在guru模式下才能修改变量的值。

4、获取结构体数组的值

probe module("md_mod").function("md_open").call

{

       printf("-----\n")

       printf("%s\n",$gdisk[2]->node->node_id$)

       printf("%s\n",@var("gdisk@md.c")[2]->node->disk_id$)

       printf("%s\n",@var("gdisk@md.c")[2]->node->disk_major$)

       printf("%s\n",@var("gdisk@md.c")[2]->node->disk_minor$)

       printf("%s\n",$gdisk[2]$$)

}

引用结构的成员变量:

@var("varname@file.c")->fild

引用数组的元素:

@var("var@file.c")[N]

变量的地址:

&@var("var@file.c")

变量的引用有两种风格:

$varname // 引用变量varname

$var->field // 引用结构的成员变量

$var[N] // 引用数组的元素

&$var // 变量的地址


@var("varname") // 引用变量varname

@var("var@src/file.c") // 引用src/file.c在被编译时的全局变量varname

@var("varname@file.c")->field // 引用结构的成员变量

@var("var@file.c")[N] // 引用数组的元素

&@var("var@file.c") // 变量的地址


$var$ // provide a string that includes the values of basic type values

$var$$ // provide a string that includes all values of nested data types


$$vars // 一个包含所有函数参数、局部变量的字符串

$$locals // 一个包含所有局部变量的字符串

$$params // 一个包含所有函数参数的字符串

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值