callgraph工具, 函數調用關系 | cflow, egypt 和 doxygen 使用


概述

作為一名linux嵌入式開發人員,長時間與linux打交道,多數情況工作在終端 + vim的環境下,已經習慣了文字界面。在閱讀代碼時,經常會在cscope中跳來跳去,但對於大型軟件項目來說,這種情況就有些腦棧不夠。閑來無事,研究下有什么工具可以生成函數調用圖,來提高閱讀代碼的效率。能夠實現代碼調用的工具很多,經過研究cflow, egypt和doxygen豐富程度依次遞增,可以基本滿足不同層次的多數需求。

cflow

‎GNU cflow 分析 C 源文件的集合並打印圖形,繪制程序中的控制流。‎‎GNU cflow能夠為C源生成直接和反轉的流圖。(可選)可以生成交叉引用列表。實現了兩種輸出格式:POSIX 和 GNU(擴展)。‎
‎可以選擇在分析之前對輸入文件進行預處理。

優點:

  1. 輸出樹形文本調用關系:方便快捷,可以直接在終端內使用
  2. 不需要編譯運行,靜態分析
  3. 簡單輕便:使用簡單方便
  4. 函數位置是按照代碼位置輸出,方便查看

缺點:

  1. 不能跨文件分析:不能分析調用的外部函數
  2. 分析不夠准確:如果存在宏嵌套等情況將無法分析走的分支

使用

安裝cflow

sudo apt-get install cflow

以simple-tftp代碼client.c中的main函數為例進行分析

wsk@wsk:~/test/simple-tftp$ cflow -Tn -m main client.c
    1 +-main() <int main (int argc, char *argv[]) at client.c:139>
    2   +-getopt()
    3   +-atoi()
    4   +-fprintf()
    5   +-exit()
    6   +-sprintf()
    7   +-printf()
    8   +-memset()
    9   +-getaddrinfo()
   10   +-gai_strerror()
   11   +-socket()
   12   +-perror()
   13   +-connect()
   14   +-close()
   15   +-inet_ntop()
   16   +-get_in_addr() <void *get_in_addr (struct sockaddr sa) at client.c:130>
   17   +-fcntl()
   18   +-bzero()
   19   +-fopen()
   20   +-strcpy()
   21   +-fill_header()
   22   +-fill_packet()
   23   +-add_checksum()
   24   +-htons()
   25   +-tftp() <int tftp (int sockfd, const void *packet, int expected_seqnum, int timeout, int flag) at client.c:44>
   26   | +-send()
   27   | +-perror()
   28   | +-exit()
   29   | +-printf()
   30   | +-recvfromTimeOut() <int recvfromTimeOut (int socket, long sec, long usec) at client.c:29>
   31   | | +-FD_ZERO()
   32   | | +-FD_SET()
   33   | | \-select()
   34   | +-recv()
   35   | \-read_header()
   36   +-fclose()
   37   +-fread()
   38   \-freeaddrinfo()

還可以查看反向調用

    1 +-FD_SET()
    2   \-recvfromTimeOut() <int recvfromTimeOut (int socket, long sec, long usec) at client.c:29>
    3     \-tftp() <int tftp (int sockfd, const void *packet, int expected_seqnum, int timeout, int flag) at client.c:44>
    4       \-main() <int main (int argc, char *argv[]) at client.c:139>
    5 +-FD_ZERO()
    6   \-recvfromTimeOut() <int recvfromTimeOut (int socket, long sec, long usec) at client.c:29> [see 2]
    7 +-add_checksum()
    8   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
    9 +-atoi()
   10   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   11 +-bzero()
   12   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   13 +-close()
   14   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   15 +-connect()
   16   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   17 +-exit()
   18   +-tftp() <int tftp (int sockfd, const void *packet, int expected_seqnum, int timeout, int flag) at client.c:44> [see 3]
   19   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   20 +-fclose()
   21   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   22 +-fcntl()
   23   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   24 +-fill_header()
   25   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   26 +-fill_packet()
   27   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   28 +-fopen()
   29   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   30 +-fprintf()
   31   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   32 +-fread()
   33   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]
   34 +-freeaddrinfo()
   35   \-main() <int main (int argc, char *argv[]) at client.c:139> [see 4]

egypt

Egypt 是一個用於創建 C 程序調用圖的簡單工具。 Egypt既不分析源代碼也不布置圖表。 相反,它將源代碼分析留給 GCC,將圖形布局留給 Graphviz,這兩者在各自的工作中都比Egypt本身所希望的要好。 Egypt只是一個非常小的 Perl 腳本,它將這些現有工具粘合在一起。

優點:

  1. 軟件小巧,易於使用
  2. 使用簡單

缺點:

  1. 依賴編譯生成的dump文件
  2. 不支持函數指針分析
  3. 生成結果依賴傳入的dump文件

使用

使用路徑:gcc生成dump文件 --> Egypt解析dump文件后生成dot --> Graphviz將dot生成圖表
安裝Graphviz

sudo apt-get install graphviz

安裝Egypt

解壓Egypt軟件包后進入到目錄中
perl Makefile.PL
make
sudo make install

然后以simple-tftp軟件包為例:

  1. 增加或修改編譯參數-fdump-rtl-expand
wsk@wsk:~/test/simple-tftp$ git diff Makefile
diff --git a/Makefile b/Makefile
index 25e88db..2d1e7c9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CC = gcc
+CC = gcc -fdump-rtl-expand

 all: client server
  1. 編譯生成dump文件*.expand
wsk@wsk:~/test/simple-tftp$ ls
callgraph.svg  checksum.c.229r.expand  checksum.o  client.c              header.c              header.h  Makefile   server    server.c.229r.expand
checksum.c     checksum.h              client      client.c.229r.expand  header.c.229r.expand  header.o  Readme.md  server.c
  1. 生成svg圖片
    這里面分成3中情況進行生成:
    case 1:全部的expand生成在一起
    case 2:僅包含client的(simple-tftp軟件包會編譯出兩個程序client和server)
    case 3:僅包含server的(simple-tftp軟件包會編譯出兩個程序client和server)
    對應的命令
case 1:
egypt *.expand | dot -Grankdir=LR -Tsvg -o callgraph.svg
case 2:
egypt client.c.229r.expand checksum.c.229r.expand header.c.229r.expand | dot -Grankdir=LR -Tsvg -o client.svg
case 3:
egypt server.c.229r.expand checksum.c.229r.expand header.c.229r.expand | dot -Grankdir=LR -Tsvg -o server.svg

生成的svg圖表對比
【case 1】全部的dump

【case 2】client dump

【case 3】server dump

通過對比和分析,可以有初步的結果:

  • 系統函數顯示不出來(分析client svg)
  • 傳入不同的dump文件,顯示的結果會有不同

doxygen

doxygen可以生成項目文檔不僅包含調用關系,詳見下面gjf,可以看到生成的內容非常的豐富。

優點:

  1. 功能強大,不僅可以生成代碼調用關系
  2. 輸出文件內容豐富:html,chm和pdf文件
  3. 配置容易,使用簡單

還是以simple-tftp工程為例
安裝doxygen

sudo apt-get install doxygen
sudo apt-get install graphviz

生成Doxyfile

進入到項目目錄
doxygen -g

配置Doxyfile:(下面的修改也可以自己封裝成腳本來實現)。下面的配置僅包含常用參數,有需要可以細看Doxyfile中的備注

需要設置YES的變量
HAVE_DOT
EXTRACT_ALL
EXTRACT_PRIVATE
EXTRACT_STATIC
CALL_GRAPH
OPTIMIZE_OUTPUT_FOR_C
RECURSIVE

下面參數按需配置:
INPUT:源碼位置 | 按需修改
  1. 為空時表示源碼在當前位置
  2. 支持多路徑,路徑間用空格隔開
GENERATE_HTML:是否生成html。生成html后可以通過web進行訪問 | 建議開啟
GENERATE_HTMLHELP:是否生成壓縮HTML格式文檔(.chm) | 按需開啟
EXTRACT_LOCAL_CLASSES:是否解析源文件(cpp文件)中定義的類 | 按需開啟
SOURCE_BROWSER:如果設定為YES,則Doxygen會產生出源文件的列表,以供查閱。 | 按需開啟

執行命令創建:

doxygen Doxyfile
執行完成后,會生成html目錄

創建http server:

進入到html目錄
python3 -m http.server 8000

8000:是端口,可以按需修改

瀏覽內容:

瀏覽器中訪問http://$hostip:8000

附件

《Doxygen v1.63 中文手冊.pdf》鏈接: https://pan.baidu.com/s/1ptS6B4ovA911TzSDb3YtlQ?pwd=nwu4 提取碼: nwu4

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM