繪製函數調用圖(call graph)(2):cflow + graphviz

版權聲明:本文爲博主原創文章,如要轉載請標明出處。 https://blog.csdn.net/benkaoya/article/details/79751000

專欄導讀

本專欄第一篇文章「專欄開篇」列出了專欄的完整目錄,按目錄順序閱讀,有助於你的理解。

前言

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

由於cflow以來gawk,你的環境有可能是mawk,所以還得安裝下gawk:

# sudo apt-get install gawk

使用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

將cflow輸出的文本文件轉化爲dot格式:

# cflow whoami.c | tree2dotx > out.dot

從dot文件轉爲圖片文件

安裝graphviz:

# sudo apt-get install graphviz

將dot格式轉化爲圖片格式:

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

最終生成的圖像如下所示:


這裏寫圖片描述

可以看出,連繫統函數printf都顯示出來了,這往往不是我們所關心的,有沒有什麼辦法可以忽略這些系統函數呢?我還沒找到方法,有知道的誠盼您的留言指教。

其他補充

  • 問:cflow能同時分析一個源文件中多個函數的call graph嗎?
  • 答:cflow默認只分析main函數的call graph,如果main不存在,將分析該文件的所有函數。可以通過 -m 選項分析指定的函數,如果指定的函數不存在,也會分析該文件的所有函數。可以利用這個特點,通過 -m 指定一個空的函數名,讓cflow分析所有函數的call graph,如:
# cflow -m= file1.c
  • 問:cflow可以同時分析多個源文件嗎?
  • 答:可以,使用如下兩種命令都可以:
# cflow -m= file1.c file2.c
# cflow -m= *.c

需要注意的是,如果多個源文件出現同名函數,cflow會警告,並且只分析其中一個main函數。

  • 問:cflow可以分析整個目錄(包括子目錄)的源文件嗎?
  • 答:通過 cflow –help 查看幫助,我沒找到有這方面的選項。

總結

做個簡單的總結:

  1. 使用cflow工具,分析源碼,得到文本格式的函數調用關係;
  2. 使用tree2dotx腳本,將文本格式轉化爲dot格式;
  3. 使用graphviz工具,可視化函數調用,將dot格式轉化爲圖片格式;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章