Systemtap Preprocessor macros

2 minute read

背景

上一篇讲了预处理阶段的条件预编译, 本文要讲的也是stap预处理阶段的事务: 宏定义.  
宏定义在stap中算是个实验特性, 前面我们提到的规则表达式匹配操作也是实验特性.  
另外要注意宏定义的顺序, 它在条件预编译前完成. 所以如果宏定义出错的话不会进行后面的条件预编译解析.  
宏定义类似C里面的宏定义#define.  
语法如下, 可以定义参数, 也可以不定义参数 :   
@define NAME %( BODY %)  
@define NAME(PARAM_1, PARAM_2, ...) %( BODY %)  
如果定义了参数, 那么在BODY中引用参数时在变量名前加@, 例如  
@define foo %( x %)  
@define add(a,b) %( ((@a)+(@b)) %)  
   @foo = @add(2,2)  
宏的使用也要在NAME前面加@  
  
前面提到的宏定义的顺序, 它在条件预编译前完成. 所以如果宏定义出错的话不会进行后面的条件预编译解析.  
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.  
使用举例 :   
在1.8的stap中未测试成功.  
[root@db-172-16-3-39 ~]# stap -e '@define add(x, y) %( ((@x)+(@y)) %) probe begin {printf("%d\n", @add($1,$2)); exit();}' 2 3  
parse error: expected 'probe', 'global', 'function', or '%{'  
        saw: identifier '@define' at <input>:1:1  
     source: @define add(x, y) %( ((@x)+(@y)) %) probe begin {printf("%d\n", @add($1,$2)); exit();}  
             ^  
parse error: expected 'arch' or 'kernel_v' or 'kernel_vr' or 'CONFIG_...'  
             or comparison between strings or integers  
        at: operator '(' at <input>:1:22  
     source: @define add(x, y) %( ((@x)+(@y)) %) probe begin {printf("%d\n", @add($1,$2)); exit();}  
                                  ^  
parse error: incomplete conditional - missing '%('  
        at: operator '%)' at <input>:1:34  
     source: @define add(x, y) %( ((@x)+(@y)) %) probe begin {printf("%d\n", @add($1,$2)); exit();}  
                                              ^  
parse error: unknown operator @add  
        saw: identifier '@add' at <input>:1:65  
     source: @define add(x, y) %( ((@x)+(@y)) %) probe begin {printf("%d\n", @add($1,$2)); exit();}  
                                                                             ^  
4 parse errors.  
Pass 1: parse failed.  Try again with another '--vp 1' option.  
使用stap2.4正常 :   
[root@db-172-16-3-150 ~]# /opt/systemtap/bin/stap -e '@define add(x, y) %( ((@x)+(@y)) %) probe begin {printf("%d\n", @add($1,$2)); exit();}' 2 3  
5  

参考 :

http://blog.163.com/digoal@126/blog/static/163877040201391391613269/

上面提到的宏是在stap脚本中使用的, 下面提到的是宏库. 前面我们提到过stap库在一堆.stp文件中.   
自定义的stp文件可以使用stap的-I参数加入到检索路径中.  
man stap  
-I DIR Add the given directory to the tapset search directory.  See the description of pass 2 for details.  
默认的stp库目录  
/usr/share/systemtap/tapset  
宏定义文件则以.stpm结尾. 同样可以使用-I加入到检索路径.  
Library macros  
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.  
举例 :   
[root@db-172-16-3-39 ~]# cd /tmp  
[root@db-172-16-3-39 tmp]# vi test.stpm  
@define add(x, y) %( ((@x)+(@y)) %)  
同样测试失败 :   
[root@db-172-16-3-39 ~]# stap -I /tmp -e 'probe begin {printf("%d\n", @add($1,$2)); exit();}' 2 3  
parse error: unknown operator @add  
        saw: identifier '@add' at <input>:1:29  
     source: probe begin {printf("%d\n", @add($1,$2)); exit();}  
                                         ^  
1 parse error.  
Pass 1: parse failed.  Try again with another '--vp 1' option.  
使用systemtap 2.4测试正常 :   
[root@db-172-16-3-150 tmp]# /opt/systemtap/bin/stap -I /tmp -e 'probe begin {printf("%d\n", @add($1,$2)); exit();}' 2 3  
5  

参考

1. http://blog.163.com/digoal@126/blog/static/16387704020139831157191/

2. https://sourceware.org/systemtap/langref/Language_elements.html

3. http://blog.163.com/digoal@126/blog/static/163877040201391391613269/

Flag Counter

digoal’s 大量PostgreSQL文章入口