c语言调用graphviz_c语言分析函数调用关系图(call graph)的几种方法

本文介绍了四种分析C语言函数调用关系的方法,包括Doxygen、CodeViz、cflow与dot(Graphviz)、以及egypt工具。其中,CodeViz和egypt是编译器级别的分析工具,cflow与dot则用于源码解析。文章详细阐述了这些工具的使用步骤和注意事项,如cflow的文件分析限制和callgraph脚本的局限性,以及egypt如何通过编译器dump生成调用图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基于 Doxygen或 lxr 的API形式的文档系统。

二、基于CodeViz, CodeViz是《Understanding The Linux Virtual Memory Manager》的作者 Mel Gorman 写的一款分析C/C++源代码中函数调用关系的open source工具(类似的open source软件有 egypt、ncc)。属于编译器级别的分析工具。

三、基于cflow、dot(即graphviz)等系列软件。属于源码直接解析类的分析工具。

四、基于egypt, 比较推荐这个,因为它支持 arm。它不用大动干戈地给编译器打补丁,而是让编译器自己dump出调用关系,然后分析分析,交给Graphviz去绘图。属于编译器级别的分析工具。

一、略。

二、基于CodeViz,主要是Graphviz + CodeViz,一个分析,一个画图。

三、基于cflow、dot(graphviz)。用于源码分析比较合适,无法从编译器视角去分析。参看:

www.tinylab.org/callgraph-draw-the-calltree-of-c-functions/?utm_source=tuicool&utm_medium=referral

值得说明的是,cflow无法直接对目录进行recursive分析,它只支持文件分析,即必须手动把要分析的文件指定给它,如: cflow -b  -m fib ./h/fib.c ./cc/fi.c ./ccc/fi.c

而且,如果 ./h/fib.c  ./cc/fi.c  ./ccc/fi.c 中有重名的函数,则这些同名函数的调用关系会合并,即若./cc/fi.c 中有个函数a只调用了函数b,而./ccc/fi.c中也有个函数a只调用了函数c,则最后打印出来的结果是函数a同时调用了b和c,即合并了。

对于cflow系列工具的使用,因为它输出的不是图形化的调用关系,因此这里推荐使用www.tinylab.org的组合工具:calltree。 它整合了cflow及graphviz并附带了一个将C 函数调用树转换为 dot 格式的脚本:tree2dotx:以 Ubuntu 为例,分别安装它们:

$ sudo apt-get install cflow graphviz

$ wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/tree2dotx

$ wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/callgraph

$ sudo cp tree2dotx callgraph /usr/local/bin

$ sudo chmod +x /usr/local/bin/{tree2dotx,callgraph}

$ sudo apt-get install gawk

我已经把tree2dotx 及 callgraph

### 使用 `perf` 和其他工具构建与分析 C 语言中的函数调用树 #### 利用 perf 进行动态分析 对于 Linux 系统上的应用程序而言,`perf` 是一套强大的性能分析工具集合。当涉及到追踪并绘制出程序内部的函数调用层次结构时,该工具无需修改原有的编译设置即可工作[^1]。 要利用 `perf` 来记录一次运行期间发生的函数调用事件,可以采用如下命令: ```bash sudo perf record -g ./your_program ``` 完成数据收集之后,通过下面这条指令查看详细的报告: ```bash perf report --call-graph dwarf ``` 这会展示一个交互式的界面,在其中可以看到各个函数之间的调用链路以及它们消耗的时间比例等信息。 #### 静态分析方法 除了上述提到的基于实际执行过程的方法外,还有静态的方式能够帮助理解源码级别的控制流图。例如借助 GCC 编译器自带的功能或者第三方插件来生成图形化的表示形式。 GCC 可以配合 `-fdump-tree-all` 参数输出中间表示(IR),从中提取有关函数间相互依赖的信息;而像 Doxygen 或 Graphviz 这样的文档生成软件则更进一步提供了可视化的支持,允许开发者直观地看到整个项目的架构布局。 另外值得注意的是 Clang/LLVM 提供了一个叫做 `clang-query` 的实用程序,它能方便地查询特定模式下的 AST(Abstract Syntax Tree)节点,从而实现自定义规则下查找所有可能存在的间接或直接调用路径。 #### 手动编写辅助脚本 如果希望获得更加定制化的结果,则可以通过解析编译后的二进制文件(如 ELF 文件)或是预处理过的汇编列表(.s files)来自行开发相应的逻辑。Python 结合 capstone disassembly framework 就是一个不错的选择,因为 Python 易于学习且拥有丰富的库资源可以帮助快速搭建原型系统。 ```python from capstone import * def analyze_function_calls(binary_code): md = Cs(CS_ARCH_X86, CS_MODE_64) call_instructions = [] for i in md.disasm(binary_code, 0x1000): if 'call' in i.mnemonic.lower(): call_instructions.append(i) return call_instructions ``` 此段代码展示了如何使用 Capstone 库识别机器码里的 CALL 指令序列,进而推断潜在的目标地址作为下一步深入研究的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值