一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

泰曉科技--源碼分析:靜態(tài)分析 C 程序函數(shù)調(diào)用關(guān)系圖

 guitarhua 2015-11-13

源碼分析:靜態(tài)分析 C 程序函數(shù)調(diào)用關(guān)系圖

Wu Zhangjin 創(chuàng)作于 2015/04/05

By Falcon of TinyLab.org 2015/04/03

1 故事緣由

源碼分析是程序員離不開的話題。無論是研究開源項目,還是平時做各類移植、開發(fā),都避免不了對源碼的深入解讀。

工欲善其事,必先利其器。今天我們來玩轉(zhuǎn)一個小工具,叫 Callgraph,它可以把 C 語言的函數(shù)調(diào)用樹(或者說流程圖)畫出來。

傳統(tǒng)的命令行工具 Cscope, Ctags 可以結(jié)合 vim 等工具提供高效快捷的跳轉(zhuǎn),但是無法清晰的展示函數(shù)內(nèi)部的邏輯關(guān)系。

至于圖形化的IDE,如 QtCreator, Source Insight, Eclipse, Android Studio 等,卻顯得笨重,而且不一定支持導出調(diào)用關(guān)系圖。

開源軟件在線代碼交叉檢索 一文中我們也介紹到了諸如 LXR, OpenGrok 之類的工具,它們避免了本地代碼庫而且提供了方便的 Web 展示,不過也無法提供函數(shù)關(guān)系的清晰展示。

下面開始 Callgraph 之旅。

2 安裝 Callgraph

Callgraph 實際由三個工具組合而成。

  • 一個是用于生成 C 函數(shù)調(diào)用樹的 cflow 或者 calltree,下文主要介紹 cflow。
  • 一個處理 dot 文本圖形語言的工具,由 graphviz 提升。建議初步了解下:DOT 語言。
  • 一個用于把 C 函數(shù)調(diào)用樹轉(zhuǎn)換為 dot 格式的腳本:tree2dotx

以 Ubuntu 為例,分別安裝它們:

  1. $ sudo apt-get install cflow graphviz

如果確實要用 calltree,請通過如下方式下載。不過 calltree 已經(jīng)年久失修了,建議不用。

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

接下來安裝 tree2dotx 和 Callgraph,這里都默認安裝到 /usr/local/bin

  1. $ wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/tree2dotx
  2. $ wget -c https://github.com/tinyclub/linux-0.11-lab/raw/master/tools/callgraph
  3. $ sudo cp tree2dotx callgraph /usr/local/bin
  4. $ sudo chmod +x /usr/local/bin/{tree2dotx,callgraph}

:部分同學反饋,tree2dotx輸出結(jié)果有異常,經(jīng)過分析,發(fā)現(xiàn)用了 mawk,所以請?zhí)峤话惭b下gawk

  1. $ sudo apt-get install gawk

3 分析 Linux 0.11

3.1 準備

先下載泰曉科技提供的五分鐘 Linux 0.11 實驗環(huán)境:Linux-0.11-Lab。

  1. $ git clone https://github.com/tinyclub/linux-0.11-lab.git && cd linux-0.11-lab

3.2 初玩

回到之前在 Linux-0.11-Lab 展示的一副圖:

Linux 0.11 CallGraph of main

它展示了 Linux 0.11 的主函數(shù) main 的調(diào)用層次關(guān)系,清晰的展示了內(nèi)核的基本架構(gòu)。那這樣一副圖是如何生成的呢?非常簡單:

  1. $ make cg f=main
  2. Func: main
  3. Match: 3
  4. File:
  5. 1 ./init/main.c: * main() use the stack at all after fork(). Thus, no function
  6. 2 ./init/main.c: * won't be any messing with the stack from main(), but we define
  7. 3 ./init/main.c:void main(void) /* This really IS void, no error here. */
  8. Select: 1 ~ 3 ? 3
  9. File: ./init/main.c
  10. Target: ./init/main.c: main -> callgraph/main.__init_main_c.svg

需要注意的是,上面提供了三個選項用于選擇需要展示的圖片,原因是這個 callgraph 目前的函數(shù)識別能力還不夠智能,可以看出 3 就是我們需要的函數(shù),所以,上面選擇序號 3。

生成的函數(shù)調(diào)用關(guān)系圖默認保存為 callgraph/main.__init_main_c.svg。

圖片導出后,默認會調(diào)用 chromium-browser 展示圖片,如果不存在該瀏覽器,可以指定其他圖片瀏覽工具,例如:

  1. $ make cg b=firefox

上面的 make cg 實際調(diào)用 callgraph

  1. $ callgraph -f main -b firefox

3.3 玩轉(zhuǎn)它

類似 main 函數(shù),實際也可渲染其他函數(shù),例如:

  1. $ callgraph -f setup_rw_floppy
  2. Func: setup_rw_floppy
  3. File: ./kernel/blk_drv/floppy.c
  4. Target: ./kernel/blk_drv/floppy.c: setup_rw_floppy -> callgraph/setup_rw_floppy.__kernel_blk_drv_floppy_c.svg

因為只匹配到一個 setup_rw_floppy,無需選擇,直接就畫出了函數(shù)調(diào)用關(guān)系圖,而且函數(shù)名自動包含了函數(shù)所在文件的路徑信息。

  • 模糊匹配

    例如,如果只記得函數(shù)名的一部分,比如 setup,則可以:

    1. $ callgraph -f setup
    2. Func: setup
    3. Match: 4
    4. File:
    5. 1 ./kernel/blk_drv/floppy.c:static void setup_DMA(void)
    6. 2 ./kernel/blk_drv/floppy.c:inline void setup_rw_floppy(void)
    7. 3 ./kernel/blk_drv/hd.c:int sys_setup(void * BIOS)
    8. 4 ./include/linux/sys.h:extern int sys_setup();
    9. Select: 1 ~ 4 ?

    因為 setup_rw_floppy 函數(shù)是第 2 個被匹配到的,選擇 2 就可以得到相同的結(jié)果。

  • 指定函數(shù)所在文件(或者文件所在的目錄)

    1. $ callgraph -f setup -d ./kernel/blk_drv/hd.c

    類似的, make cg 可以這么用:

    1. $ make cg f=setup d=./kernel/blk_drv/hd.c

    看看效果:

Linux 0.11 CallGraph of setup_rw_floppy

4 分析新版 Linux

4.1 初玩

先來一份新版的 Linux,如果手頭沒有,就到 www. 搞一份吧:

  1. $ wget -c https://www./pub/linux/kernel/v3.x/linux-3.10.73.tar.xz
  2. $ tar Jxf linux-3.10.73.tar.xz && cd linux-3.10.73

玩起來:

  1. $ callgraph -f start_kernel -d init/main.c

4.2 酷玩

  • 砍掉不感興趣的函數(shù)分支

    上面生成的圖,有沒有覺得 printk 之類的調(diào)用太多,覺得很繁瑣。沒關(guān)系,用 -F 砍掉。

    1. $ callgraph -f start_kernel -d init/main.c -F printk

    如果要砍掉很多函數(shù),則可以指定一個函數(shù)列表:

    1. $ callgraph -f start_kernel -d init/main.c -F "printk boot_cpu_init rest_init"
  • 指定函數(shù)調(diào)用深度:

    -D 命令可以指定:

    1. $ callgraph -f start_kernel -d init/main.c -F "printk boot_cpu_init rest_init" -D 2
  • 指定函數(shù)搜索路徑

    我們來看看 update_process_times 的定義,用 -d 指定搜索路徑:

    1. $ callgraph -f update_process_times -d kernel/

    它會自動搜索 kernel/ 目錄并生成一副圖,效果如下:

    Linux CallGraph of update_process_times

    考慮到 callgraph 本身的檢索效率比較低(采用grep),如果不能明確函數(shù)所在的目錄,則可以先用 cscope 之類的建立索引,先通過這些索引快速找到函數(shù)所在的文件,然后用 -d 指定文件。

    例如,假設我們通過 cs find g update_process_times 找到該函數(shù)在 kernel/timer.c 中定義,則可以:

    1. $ callgraph -f update_process_times -d kernel/timer.c

5 原理分析

callgraph 實際上只是靈活組裝了三個工具,一個是 cflow,一個是 tree2dotx,另外一個是 dot。

5.1 cflow:拿到函數(shù)調(diào)用關(guān)系

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

5.2 tree2dotx: 把函數(shù)調(diào)用樹轉(zhuǎn)換成 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

關(guān)于 tree2dotx,需要多說幾句,它最早是筆者 2007 年左右所寫,當時就是為了直接用圖文展示樹狀信息。該工具其實支持任意類似如下結(jié)構(gòu)的樹狀圖:

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

所以,我們也可以把某個目錄結(jié)構(gòu)展示出來,以 Linux 0.11 為例:

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

如果覺得一張圖顯示的內(nèi)容太多,則可以指定某個當前正在研讀的內(nèi)核目錄,例如 kernel 部分:

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

看下效果:

Linux 0.11 tree Graph of kernel/

7 What’s more?

上文展示了如何把源碼的調(diào)用關(guān)系用圖文的方式渲染出來。好處顯而易見:

  • 不僅可以清晰的理解源碼結(jié)構(gòu),從而避免直接陷入細節(jié),進而提高源碼分析的效率。
  • 也可以基于這個結(jié)果構(gòu)建流程圖,然后用 inkscape 之類的工具做自己的調(diào)整和擴充,方便做后續(xù)展示。
  • 還可以把這些圖文用到文檔甚至書籍中,以增加可讀性。

Callgraph 的圖文展示基于 cflow 或者 calltree,它們都只是靜態(tài)源碼分析的范疇。

后續(xù)我們將從從運行時角度來動態(tài)分析源碼的實際執(zhí)行路徑。我們計劃分開展示應用部分和內(nèi)核部分。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    久久精品中文扫妇内射| 欧美性高清一区二区三区视频| 开心久久综合激情五月天| 亚洲国产性感美女视频| 成年女人午夜在线视频| 人妻亚洲一区二区三区| 中文字幕日产乱码一区二区| 欧美精品在线观看国产| 亚洲综合色在线视频香蕉视频| 翘臀少妇成人一区二区| 色播五月激情五月婷婷| 亚洲最新的黄色录像在线| 日本不卡在线一区二区三区| 久热久热精品视频在线观看| 欧美成人高清在线播放| 日本深夜福利在线播放| 91人妻人澡人人爽人人精品| 欧洲日本亚洲一区二区| 欧美同性视频免费观看| 精品欧美在线观看国产| 久久精品国产99国产免费| 伊人久久青草地综合婷婷| 大香蕉网国产在线观看av| 日韩欧美二区中文字幕| 欧美黑人在线精品极品| 亚洲欧洲一区二区中文字幕| 国产女高清在线看免费观看| 欧美精品久久99九九| 免费在线播放不卡视频| 日韩欧美国产精品中文字幕| 欧美一区二区三区五月婷婷| 日本熟女中文字幕一区| 久久国产成人精品国产成人亚洲| 久久精品亚洲精品一区| 亚洲av熟女国产一区二区三区站| 亚洲国产成人久久一区二区三区| 久久午夜福利精品日韩| 91欧美亚洲精品在线观看| 91亚洲国产成人久久精品麻豆| 亚洲欧美日韩在线中文字幕| 丝袜破了有美女肉体免费观看 |