分享

静态分析C语言生成函数调用关系的利器

 昵称51898798 2018-03-28

        除了《静态分析C语言生成函数调用关系的利器——calltree》一文中介绍的calltree,我们还可以借助cflow辅助我们阅读理解代码。(转载请指明出于breaksoftware的csdn博客)

cflow的说明和安装

        cflow是一款静态分析C语言代码的工具,通过它可以生成函数的调用关系。和calltree不一样,cflow有独立的网页介绍它(https://www./software/cflow/#TOCdocumentation)。而且在Ubuntu系统上,我们可以不用去编译cflow的源码,而直接使用下面命令获取

  1. apt-get install cflow  

cflow的使用

        安装完毕,我们可以使用下面指令看到cflow的参数说明

  1. cflow --help  
        我们可以得到如下提示
  1. Usage: cflow [OPTION...] [FILE]...  
  2. generate a program flowgraph  
  3.   
  4.  General options:  
  5.   -d, --depth=NUMBER         Set the depth at which the flowgraph is cut off  
  6.   -f, --format=NAME          Use given output format NAME. Valid names are  
  7.                              `gnu' (default) and `posix'  
  8.   -i, --include=CLASSES      Include specified classes of symbols (see below).  
  9.                              Prepend CLASSES with ^ or - to exclude them from  
  10.                              the output  
  11.   -o, --output=FILE          Set output file name (default -, meaning stdout)  
  12.   -r, --reverse              * Print reverse call tree  
  13.   -x, --xref                 Produce cross-reference listing only  
  14.   
  15.  Symbols classes for --include argument  
  16.   
  17.     _                        symbols whose names begin with an underscore  
  18.     s                        static symbols  
  19.     t                        typedefs (for cross-references only)  
  20.     x                        all data symbols, both external and static  
  21.   
  22.  Parser control:  
  23.   
  24.   -a, --ansi                 * Accept only sources in ANSI C  
  25.   -D, --define=NAME[=DEFN]   Predefine NAME as a macro  
  26.   -I, --include-dir=DIR      Add the directory DIR to the list of directories  
  27.                              to be searched for header files.  
  28.   -m, --main=NAME            Assume main function to be called NAME  
  29.   -p, --pushdown=NUMBER      Set initial token stack size to NUMBER  
  30.       --preprocess[=COMMAND], --cpp[=COMMAND]  
  31.                              * Run the specified preprocessor command  
  32.   -s, --symbol=SYMBOL:[=]TYPE   Register SYMBOL with given TYPE, or define an  
  33.                              alias (if := is used). Valid types are: keyword  
  34.                              (or kw), modifier, qualifier, identifier, type,  
  35.                              wrapper. Any unambiguous abbreviation of the above  
  36.                              is also accepted  
  37.   -S, --use-indentation      * Rely on indentation  
  38.   -U, --undefine=NAME        Cancel any previous definition of NAME  
  39.   
  40.  Output control:  
  41.   
  42.   -b, --brief                * Brief output  
  43.       --emacs                * Additionally format output for use with GNU  
  44.                              Emacs  
  45.   -l, --print-level          * Print nesting level along with the call tree  
  46.       --level-indent=ELEMENT Control graph appearance  
  47.   -n, --number               * Print line numbers  
  48.       --omit-arguments       * Do not print argument lists in function  
  49.                              declarations  
  50.       --omit-symbol-names    * Do not print symbol names in declaration strings  
  51.                               
  52.   -T, --tree                 * Draw ASCII art tree  
  53.   
  54.  Informational options:  
  55.   
  56.       --debug[=NUMBER]       Set debugging level  
  57.   -v, --verbose              * Verbose error diagnostics  
  58.   
  59.   -?, --help                 give this help list  
  60.       --usage                give a short usage message  
  61.   -V, --version              print program version  
  62.   
  63. Mandatory or optional arguments to long options are also mandatory or optional  
  64. for any corresponding short options.  
  65.   
  66. * The effect of each option marked with an asterisk is reversed if the option's  
  67. long name is prefixed with `no-'. For example, --no-cpp cancels --cpp.  
  68.   
  69. Report bugs to <bug-cflow@>.  

        我只列出我觉得有意思的几个参数:

        -T输出函数调用树状图

        -m指定需要分析的函数名

        -n输出函数所在行号

        -r输出调用的反向关系图

        --cpp预处理,这个还是很重要的

文本输出

        最简单的使用方法是以ASCII文本的方式输出结果,比如

  1. cflow -T -m main -n timer.c  
        其结果是一个包含文件名和函数所在代码行号的调用关系图
  1. +-main() <int main (void) at timer.c:13>  
  2.   +-ev_timer_init()  
  3.   +-timeout_cb() <void timeout_cb (EV_P_ ev_timer *w, int revents) at timer.c:7>  
  4.   | +-puts()  
  5.   | \-ev_break()  
  6.   +-ev_timer_start()  
  7.   \-ev_run()  

        然而,对于有一定代码量的项目,我们不会使用ASCII文本的方式去查看函数调用关系,因为调用是相当复杂的,而文本图并不适合人去理解。于是我们希望能cflow能产出一个可供其他软件转换成图片的格式的文件。可惜cflow并不支持,好在网上有开发者做了一个工具,可将其结果转换成dot格式。

转成dot文件

        我们可以使用下面方法获取转换工具
  1. wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/tree2dotx  
        下载完tree2dotx后,可对其做个软链便于使用
  1. cd /usr/bin  
  2. ln -s 【Your Path】/tree2dotx tree2dotx  

        具体的转换方法是

  1. cflow -T -m main -n timer.c > main.txt  
  2. cat main.txt | tree2dotx > main.dot  

dot文件生成图片        

        我们需要借助graphviz(没有安装的可以使用apt-get install graphviz先安装)生成图片,指令是

  1. dot -Tgif main.dot -o main.gif    

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多