故事缘由源码分析是程序员离不开的话题。无论是研究开源项目,还是平时做各类移植、开发,都避免不了对源码的深入解读。 工欲善其事,必先利其器。今天我们来玩转一个小工具,叫 Callgraph,它可以把 C 语言的函数调用树(或者说流程图)画出来。 传统的命令行工具 Cscope, Ctags 可以结合 vim 等工具提供高效快捷的跳转,但是无法清晰的展示函数内部的逻辑关系。 至于图形化的IDE,如 QtCreator, Source Insight, Eclipse, Android Studio 等,却显得笨重,而且不一定支持导出调用关系图。 在 开源软件在线代码交叉检索 一文中我们也介绍到了诸如 LXR, OpenGrok 之类的工具,它们避免了本地代码库而且提供了方便的 Web 展示,不过也无法提供函数关系的清晰展示。 下面开始 Callgraph 之旅。 安装 CallgraphCallgraph 实际由三个工具组合而成。
以 Ubuntu 为例,分别安装它们: $ sudo apt-get install cflow graphviz 如果确实要用 calltree,请通过如下方式下载。不过 calltree 已经年久失修了,建议不用。 $ wget -c https:///tinylab/linux-0.11/raw/master/tools/calltree 接下来安装 tree2dotx 和 Callgraph,这里都默认安装到 $ wget -c https:///tinylab/linux-0.11/raw/master/tools/tree2dotx$ wget -c https:///tinylab/linux-0.11/raw/master/tools/callgraph$ sudo cp tree2dotx callgraph /usr/local/bin$ sudo chmod +x /usr/local/bin/{tree2dotx,callgraph} 分析 Linux 0.11准备 先下载泰晓科技提供的五分钟 Linux 0.11 实验环境:Linux-0.11-Lab。 $ git clone https:///tinylab/linux-0.11.git && cd linux-0.11 初玩 回到之前在Linux-0.11-Lab 展示的一副图: 它展示了 Linux 0.11 的主函数 main 的调用层次关系,清晰的展示了内核的基本架构。那这样一副图是如何生成的呢?非常简单: $ make cg f=mainFunc: mainMatch: 3File: 1 ./init/main.c: * main() use the stack at all after fork(). Thus, no function 2 ./init/main.c: * won't be any messing with the stack from main(), but we define 3 ./init/main.c:void main(void) /* This really IS void, no error here. */Select: 1 ~ 3 ? 3File: ./init/main.cTarget: ./init/main.c: main -> callgraph/main.__init_main_c.svg 需要注意的是,上面提供了三个选项用于选择需要展示的图片,原因是这个 callgraph 目前的函数识别能力还不够智能,可以看出 3 就是我们需要的函数,所以,上面选择序号 3。 生成的函数调用关系图默认保存为 callgraph/main.__init_main_c.svg。 图片导出后,默认会调用 chromium-browser 展示图片,如果不存在该浏览器,可以指定其他图片浏览工具,例如: $ make cg b=firefox 上面的 $ callgraph -f main -b firefox 玩转它 类似 $ callgraph -f setup_rw_floppyFunc: setup_rw_floppyFile: ./kernel/blk_drv/floppy.cTarget: ./kernel/blk_drv/floppy.c: setup_rw_floppy -> callgraph/setup_rw_floppy.__kernel_blk_drv_floppy_c.svg 因为只匹配到一个
分析新版 Linux初玩 先来一份新版的 Linux,如果手头没有,就到 www. 搞一份吧: $ wget -c https://www./pub/linux/kernel/v3.x/linux-3.10.73.tar.xz$ tar Jxf linux-3.10.73.tar.xz && cd linux-3.10.73 玩起来: $ callgraph -f start_kernel -d init/main.c 酷玩
原理分析
cflow:拿到函数调用关系 $ cflow -b -m start_kernel init/main.c > start_kernel.txt tree2dotx: 把函数调用树转换成 dot 格式 $ cat start_kernel.txt | tree2dotx > start_kernel.dot 用 dot 工具生成可以渲染的图片格式 这里仅以 svg 格式为例: $ cat start_kernel.dot | dot -Tsvg -o start_kernel.svg 实际上 dot 支持非常多的图片格式,请参考它的手册: 趣玩 tree2dotx关于 a b c d x y e f 所以,我们也可以把某个目录结构展示出来,以 Linux 0.11 为例: $ cd linux-0.11$ tree -L 2 | tree2dotx | dot -Tsvg -o tree.svg 如果觉得一张图显示的内容太多,则可以指定某个当前正在研读的内核目录,例如 $ tree -L 2 kernel | tree2dotx -f Makefile | dot -Tsvg -o tree.svg 看下效果: What’s more?上文展示了如何把源码的调用关系用图文的方式渲染出来。好处显而易见:
后续我们将从从运行时角度来动态分析源码的实际执行路径。我们计划分开展示应用部分和内核部分。 0 0 |
|