tools :cflow

https://blog.csdn.net/benkaoya/article/details/79751000

 

https://blog.csdn.net/wind4study/article/details/53366419

用cflow工具生成代码函数调用关系

1. 安装

  sudo apt-get install cflow

2.使用

  cflow [options...] [file]...

例:

cflow main.c

生成main.c文件例的函数调用关系

cflow -x main.c
生成交叉引用表,查看函数调用的位置和文件
cflow -o call_tree.txt main.c
生成调用关系并输出到call_tree.txt文件
cflow -d 5 -o call_tree.txt main.c
指定输出的最大调用深度位5

其他选项:用 cflow --help查看

通用选项: 
-d, --depth=NUMBER 设置流程图的绘制深度
-f, --format=NAME
使用指定的输出格式名。有效名称是‘gnu’(默认)和‘posix’
-i, --include=CLASSES 包含指定的符号类(见下)。在 CLASSES
之前放上 ^ 或 - 将它们从输出中省去
-o, --output=FILE 设置输出文件名(默认为
-,即标准输出)
-r, --reverse * 打印反向调用树
-x, --xref 仅生成交叉引用列表

--include 参数的符号类

_ 以下划线开始的符号名
s 静态符号
t typedefs(仅针对交叉引用)
x 所有的数据符号(外部的和静态的)

句法分析控制:

-a, --ansi * 仅接受 ANSI C 标准的源码
-D, --define=NAME[=DEFN] 将 NAME 预定义为一个宏
-I, --include-dir=DIR 将 DIR
目录添加至可被头文件搜索到的目录列表
-m, --main=NAME 假定主函数是个叫 NAME 的函数
-p, --pushdown=NUMBER 设置初始标识栈大小为 NUMBER
--preprocess[=COMMAND], --cpp[=COMMAND]
* 执行指定的预处理命令
-s, --symbol=SYMBOL:[=]TYPE Register SYMBOL with given TYPE, or define an
alias (if := is used). Valid types are: keyword
(or kw), modifier, qualifier, identifier, type,
wrapper. Any unambiguous abbreviation of the above
is also accepted
-S, --use-indentation * 依赖缩进风格
-U, --undefine=NAME 取消前面所有的 NAME 预定义

输出控制:

-b, --brief * 简洁输出
--emacs * 为与 GNU Emacs
联合使用而显示额外的格式输出
-l, --print-level * 打印调用关系树的嵌套结构
--level-indent=ELEMENT 控制图显示
-n, --number * 打印行号
--omit-arguments * 不在函数声明部分打印参数列表
--omit-symbol-names * 不在声明字符串中打印符号名
-T, --tree * 绘制 ASCII 形式的树

输出信息选项:

--debug[=NUMBER] 设定调试级别
-v, --verbose * 详细的错误诊断报告

-?, --help 显示此帮助列表
--usage 显示一份简洁的用法信息
-V, --version 打印程序版本

选项完整形式所必须用的或是可选的参数,在使用选项缩写形式时也是必须的或是可选的。

*
每个带有星号标记的选项是相反操作,就像前面带有‘no-’的长选项名一样。例如,--no-cpp
就是取消 --cpp 选项用的。

其他工具:

ctags:
为所有函数创建索引
cxref:
生成交叉引用表

 https://blog.csdn.net/Wind4study/article/details/53366419

 

绘制函数调用图(call graph)(2):cflow + graphviz

2018年03月29日 23:23:39

阅读数:374

专栏导读

本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解。

前言

cflow是一款静态分析C语言代码的工具,通过它可以生成函数调用关系。

如果你英文可以,上面的手册就是很好的使用教程,本文只是简单的介绍下如何使用cflow,旨在让新手快速入门cflow而已。

安装cflow

在linux下安装cflow很简单,如下是我在Ubuntu下的安装命令:

# sudo apt-get install cflow
#
# cflow --version
cflow (GNU cflow) 1.4
Copyright (C) 2005, 2006, 2009, 2010, 2011 2009 Sergey Poznyakoff
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Sergey Poznyakoff.

通过以下命令查看使用说明:

# cflow --help
  • 1

由于cflow以来gawk,你的环境有可能是mawk,所以还得安装下gawk:

# sudo apt-get install gawk
  • 1

使用cflow分析函数调用关系

举个简单的例子,以下是源文件whoami.c内容(源码来自官网手册):

/* whoami.c - a simple implementation of whoami utility */
#include <pwd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

int who_am_i(void)
{
    struct passwd *pw;
    char *user = NULL;

    pw = getpwuid (geteuid ());
    if (pw)
        user = pw->pw_name;
    else if ((user = getenv ("USER")) == NULL)
    {
        fprintf (stderr, "I don't know!\n");
        return 1;
    }
    printf ("%s\n", user);
    return 0;
}

int main(int argc, char **argv)
{
    if (argc > 1)
    {
        fprintf (stderr, "usage: whoami\n");
        return 1;
    }
    return who_am_i ();
}

运行cflow将生成以下输出:

# cflow whoami.c 
main() <int main (int argc, char **argv) at whoami.c:24>:
    fprintf()
    who_am_i() <int who_am_i (void) at whoami.c:7>:
        getpwuid()
        geteuid()
        getenv()
        fprintf()
        printf()

cflow默认是分析main函数,可以通过 -m 选项分析其他函数:

# cflow -m who_am_i whoami.c 
who_am_i() <int who_am_i (void) at whoami.c:7>:
    getpwuid()
    geteuid()
    getenv()
    fprintf()
    printf()

cflow只能以ASCII文本的形式输出函数调用关系,不能输出图片格式,对于大型项目的代码来说,庞杂的文本输出简直“惨不忍睹,无法直视”。需要其他工具的辅助,才能将本文格式转化为可读性更强的图片格式,大致步骤如下:

  1. cflow工具:输出文本格式的函数调用关系;
  2. tree2dotx脚本:将文本格式转化为dot格式;
  3. graphviz工具:将dot格式转化为图片格式;

从文本文件转为dot文件

将cflow输出的文本文件转化为dot格式的工具有tree2dotx,是否有其他工具,有待研究。通过以下命令下载tree2dotx脚本:

# wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/tree2dotx -O /usr/bin/tree2dotx
# chmod +x /usr/bin/tree2dotx
  • 1
  • 2

将cflow输出的文本文件转化为dot格式:

# cflow whoami.c | tree2dotx > out.dot
  • 1

从dot文件转为图片文件

安装graphviz:

# sudo apt-get install graphviz
  • 1

将dot格式转化为图片格式:

# dot -Tgif out.dot -o out.gif
  • 1

最终生成的图像如下所示:

 


这里写图片描述

 

可以看出,连系统函数printf都显示出来了,这往往不是我们所关心的,有没有什么办法可以忽略这些系统函数呢?我还没找到方法,有知道的诚盼您的留言指教。

其他补充

  • 问:cflow能同时分析一个源文件中多个函数的call graph吗?
  • 答:cflow默认只分析main函数的call graph,如果main不存在,将分析该文件的所有函数。可以通过 -m 选项分析指定的函数,如果指定的函数不存在,也会分析该文件的所有函数。可以利用这个特点,通过 -m 指定一个空的函数名,让cflow分析所有函数的call graph,如:
# cflow -m= file1.c
  • 1
  • 问:cflow可以同时分析多个源文件吗?
  • 答:可以,使用如下两种命令都可以:
# cflow -m= file1.c file2.c
# cflow -m= *.c

需要注意的是,如果多个源文件出现同名函数,cflow会警告,并且只分析其中一个main函数。

  • 问:cflow可以分析整个目录(包括子目录)的源文件吗?
  • 答:通过 cflow –help 查看帮助,我没找到有这方面的选项。

总结

做个简单的总结:

  1. 使用cflow工具,分析源码,得到文本格式的函数调用关系;
  2. 使用tree2dotx脚本,将文本格式转化为dot格式;
  3. 使用graphviz工具,可视化函数调用,将dot格式转化为图片格式;

 https://blog.csdn.net/benkaoya/article/details/79751000

 

Cflow使用详解

2014年11月08日 17:26:30

阅读数:3511

最近使用cflow,根据Cflow提供的帮助对cflow的用法做了详细的整理。把常用的命令的用法贴出来。完整版请见http://download.csdn.net/detail/hanchaoqi/8136111

12、cflow选项的完整列表

这一章我们以字符序列出cflow的所有选项,包括简要的说明。所有的长选项和短选项都被列出了,所以你可以将这个表作为快速参考。
大部分的选项都有一个相反意义的负选项对应,负选项的命名是对相应的长选项加前缀no-.这个特性用于取消在配置文件中定义的选项。
-a (--ansi)
假设输入文件使用ANSI C编写。目前这意味着不能解析K&R声明的函数。这在某些情况下可以加快处理进度。
-b (--brief)
简要输出
--cpp[=command]
运行指定的预处理命令
-D name[=defn] (--define=name[=defn])
预定义名字作为宏。
-d number (--depth=number)
设置流图中嵌套的最大层数。
--debug[=number]
设置调试级别。默认值是1,如果你开发或调试cflow时使用这个选项。
--emacs
让访问文件时告诉Emacs使用cflow模式输出。
-f name (--format=name)
使用给定的输出格式名。合法的名字是gnu和posix。
-? (--help)
帮助,对每个选项作简要的说明。
-I dir (--include-dir=dir)
增加搜索头文件时,所需要的头文件所在目录。
-i spec (--include=spec)
控制包含符号的数量。spec是一个字符串,指定了哪一类符号应该包含在输出里。合法字符如下:
- ^ 输出中排除后接字符
+ 输出中包含后接字符(缺省)
_ 以下划线开头的符号
s 静态符号
t 类型定义(只在交叉引用时使用)
x 所有的数据符号,包括外部符号和静态符号
-l
--level-indent=string 指定每个级别缩进时使用的字符串
-m name (--main=name) 设定最开始调用的函数名。
-n (--number) 打印行号
-o file (--output=file) 指定输出文件,默认是’-’,即标准输出
--ommit-arguments 不打印函数声明中的参数列表
--omit-symbol-names 不打印所指定的符号名字,在posix模式下可用。
-r (--reverse) 打印逆向调用图
-x (--xref) 只生成交叉引用列表
-p number (--pushdown=number) 初始化令牌栈的大小。默认值64.令牌栈会自动增长,所以这个选项很少使用。
--preprocess[=command] 使用预处理
-s sym:class
--symbol=sym:class
--symbol=newsym:=oldsym
第一种形式,在语法类class中注册符号sym。合法的额类名是‘keyword’ (or ‘kw’), ‘modifier’, ‘qualifier’, ‘identifier’, ‘type’, ‘wrapper’。任何明确的缩写都是可接受的。
第二种形式(使用’:=’分割),定义newsym作为oldsym的别名。
-S (--use-indentation) 使用文件缩进作为提示。目前这个意思是右大括号 (‘}’) 在第零列强制cflow结束当前的函数定义。使用这个选项解析可能会对某些远产生误解。
-U name (--undefine=name) 取消之前所做的name的定义
-l (--print-level) 打印嵌套层数。层数在输出行的最后打印(如果使用了--number 或 --format=posix,层数会使用大括号括起来)。
-T (--tree) 使用ASCII码打印,调用树。
--usage 提供简短的使用信息。
-v (--verbose) 详细的打印出所有的错误信息。cflow中的错误信息与c编译器的错误信息是不一样的,所以这个选项默认是关闭的。
-V (--version) 打印程序的版本信息

 

5 原理分析

callgraph 实际上只是灵活组装了三个工具,一个是 cflow,一个是 tree2dotx,另外一个是 dot。

5.1 cflow:拿到函数调用关系

  1. $ cflow -b -m start_kernel init/main.c > start_kernel.txt

5.2 tree2dotx: 把函数调用树转换成 dot 格式

  1. $ cat start_kernel.txt | tree2dotx > start_kernel.dot

5.3 用 dot 工具生成可以渲染的图片格式

这里仅以 svg 格式为例:

  1. $ cat start_kernel.dot | dot -Tsvg -o start_kernel.svg

实际上 dot 支持非常多的图片格式,请参考它的手册:man dot

6 趣玩 tree2dotx

关于 tree2dotx,需要多说几句,它最早是笔者 2007 年左右所写,当时就是为了直接用图文展示树状信息。该工具其实支持任意类似如下结构的树状图:

  1. a
  2. b
  3. c
  4. d
  5. x
  6. y
  7. e
  8. f

所以,我们也可以把某个目录结构展示出来,以 Linux 0.11 为例:

  1. $ cd linux-0.11
  2. $ tree -L 2 | tree2dotx | dot -Tsvg -o tree.svg

如果觉得一张图显示的内容太多,则可以指定某个当前正在研读的内核目录,例如 kernel 部分:

  1. $ tree -L 2 kernel | tree2dotx -f Makefile | dot -Tsvg -o tree.svg

看下效果:

Linux 0.11 tree Graph of kernel/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值