繪製函數調用圖(call graph)(3):codeviz + graphviz

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

專欄導讀

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

前言

codeviz官網:https://github.com/petersenna/codeviz

codeviz是一款分析C/C++源代碼函數調用關係的工具,通過它可以生成函數調用關係圖(call graph)。其基本原理是給gcc打個補丁,讓gcc在編譯每個源文件時,將其中的函數的調用關係以文本形式保存在 .cdepn 文件中,然後使用 Perl 腳本(genfull和gengraph)把 .cdepn 文件轉成 dot 文件,最後由graphviz 將dot文件轉成圖片文件(如gif、png等)。

給gcc打補丁的過程是:
1. 下載codeviz要求的特定版本的gcc源碼(跟你環境中已安裝的gcc是不同的);
2. 使用codeviz的補丁文件修改gcc源碼(即打補丁);
3. 編譯gcc源碼,得到打完補丁的gcc可執行文件(利用這個gcc可執行文件再來編譯我們項目的源文件,從而得到函數調用關係);

在安裝codeviz的過程中,最難的也就是編譯打完補丁的gcc源碼,會遇到各種編譯出錯,得逐個解決,大部分時間也是耗在這上面。整個安裝過程大致步驟如下:

  1. 安裝graphviz,因爲codeviz依賴graphviz,所以要先安裝graphviz。
  2. 安裝codeviz,這裏麪包括腳本自動下載依賴的gcc源碼,自動打補丁,自動編譯gcc源碼,最後安裝codeviz。

安裝graphviz

codeviz 依賴 graphviz,所以要先安裝 graphviz:

# sudo apt-get install graphviz

安裝codeviz

codeviz源碼包下載地址:
https://web.archive.org/web/20150502053825/http://www.csn.ul.ie/~mel/projects/codeviz/#download

安裝步驟:

# wget https://web.archive.org/web/20150802030038/http://www.csn.ul.ie/~mel/projects/codeviz/codeviz-1.0.12.tar.gz
# tar zxvf codeviz-1.0.12.tar.gz
# cd codeviz-1.0.12/
# ./configure && make && make install

執行make的過程中,codeviz的安裝腳本 compilers/install_gcc-4.6.2.sh 會自動檢測 compilers 目錄下是否有其依賴的 gcc 版本的源碼包(版本codeviz-1.0.12 依賴的是 gcc-4.6.2),如果沒有,則會將 gcc-4.6.2.tar.gz 源碼自動下載到 compilers 目錄中,並將 gcc-4.6.2.tar.gz 解壓到 gcc-graph 目錄,然後打上補丁,最後開始編譯。這個過程,其實是codeviz-1.0.12/compilers/install_gcc-4.6.2.sh腳本自動實現的。

codeviz-1.0.12/
├── bin
├── compilers
│   ├── install_gcc-4.6.2.sh    <-- 執行該腳本將: 
│   ├── gcc-4.6.2.tar.gz                        1. download gcc-4.6.2.tar.gz              
│   ├── gcc-graph                               2. mkdir gcc-graph
│   │   ├── gcc-4.6.2                           3. untar it into gcc-graph
│   ├── gcc-patches                             4. patch it5. compile it

我在編譯的過程中,遇到了以下幾個問題,最後一個問題沒能解決,所以安裝也宣告失敗,不管怎樣,把這次安裝過程做個記錄,留給需要的人蔘考。

問題1:無法自動下載gcc-4.6.2

如果出現無法正常下載gcc的情況,就要檢查下install_gcc-4.6.2.sh腳本了。截取該腳本部分內容:

#!/bin/bash

INSTALL_PATH=$HOME/gcc-graph
if [ "$1" != "" ]; then INSTALL_PATH=$1; fi
if [ "$2" = "compile-only" ]; then export COMPILE_ONLY=yes; fi
echo Installing gcc to $INSTALL_PATH

NCFTP=`which ncftpget`
EXIT=$?
if [ "$EXIT" != "0" ]; then
  NCFTP=ftp
fi

if [ ! -e gcc-4.6.2.tar.gz ]; then
  echo gcc-4.6.2.tar.gz not found, downloading
  $NCFTP ftp://ftp.gnu.org/pub/gnu/gcc/gcc-4.6.2/gcc-4.6.2.tar.gz
  if [ ! -e gcc-4.6.2.tar.gz ]; then
    echo Failed to download gcc, download gcc-4.6.2.tar.gz from www.gnu.org
    exit
  fi
fi
......

因爲我的環境沒有安裝ncftpget,但有wget,所以我將:

NCFTP=`which ncftpget`

改爲:

NCFTP=`which wget`

就能順利下載gcc了。

當然,你也可以自己下載 gcc-4.6.2.tar.gz ,再把它拷貝到 codeviz-1.0.12/compilers 目錄中。我還是更傾向於修改 install_gcc-4.6.2.sh 腳本,讓這些過程「自動化」。

問題2:找不到依賴庫gmp、mpfr、mpc

編譯gcc-4.6.2的過程遇到如下錯誤:

configure: error: Building GCC requires GMP 4.2+, MPFR 2.3.1+ and MPC 0.8.0+.

這是因爲缺少相應的依賴庫,要先執行gcc源碼中自帶的依賴庫安裝腳本download_prerequisites,如下所示:

# cd codeviz-1.0.12/compilers/gcc-graph/gcc-4.6.2/
# ./contrib/download_prerequisites

注意:以上 cd 的路徑是有講究的,務必跟以上命令保持一致,這樣gmp、mpfr、mpc才能下載到codeviz-1.0.12/compilers/gcc-graph/gcc-4.6.2/目錄下,才能保證順利編譯。

爲了讓這個過程「自動化」,也可以把以上命令放到 install_gcc-4.6.2.sh 腳本中去執行。當然,如果你的環境沒有報這個錯,就沒必要了。

問題3:linux-unwind.h編譯失敗

編譯gcc-4.6.2的過程遇到如下錯誤:

../../../../gcc-4.6.2/libgcc/../gcc/config/i386/linux-unwind.h:138:17: error: field ‘info’ has incomplete type

解決方法1:

這是因爲我的環境是linux 64-bit內核, struct siginfo不兼容64-bit內核,將以下文件:

codeviz-1.0.12/compilers/gcc-graph/gcc-4.6.2/gcc/config/i386/linux-unwind.h

中的 struct siginfo 替換爲siginfo_t 即可,因爲每次重新執行make,腳本install_gcc-4.6.2.sh都會重新解壓gcc-4.6.2並覆蓋linux-unwind.h,所以這樣的替換要在 install_gcc-4.6.2.sh 腳本中執行,按如下修改install_gcc-4.6.2.sh 腳本內容:

tar -zxf gcc-4.6.2.tar.gz -C gcc-graph || exit

sed -i 's/struct siginfo/siginfo_t/g'  ./gcc-graph/gcc-4.6.2/gcc/config/i386/linux-unwind.h

即在解壓gcc-4.6.2後,使用sed命令將linux-unwind.h文件中的struct siginfo 替換爲siginfo_t,如此,重新執行make指令即可編譯通過。

解決方法2:

在腳本 install_gcc-4.6.2.sh 文件中增加編譯選項:

--disable-multilib

問題4:找不到crt1.o

編譯gcc-4.6.2的過程遇到如下錯誤:

cannot find crt1.o: No such file or directory

先找出crt1.o在哪(你的路徑可能跟我不一樣):

# find /usr/ -name crti.o
/usr/lib/x86_64-linux-gnu/crti.o

解決方法:

# export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu && make

問題5:找不到CXXABI_1.3.8

編譯gcc-4.6.2的過程遇到如下錯誤:

msgfmt: /opt/codeviz-1.0.12/compilers/gcc-graph/objdir/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /usr/lib/x86_64-linux-gnu/libicuuc.so.55)

根據提示,查看其 libstdc++.so.6,確實沒有 CXXABI_1.3.8:

# strings /opt/codeviz-1.0.12/compilers/gcc-graph/objdir/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6 | grep CXXABI
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3
CXXABI_1.3.2
CXXABI_1.3.1
CXXABI_1.3.5
CXXABI_1.3.4
CXXABI_1.3.3

嘗試了網上說的很多方法,該問題依然沒有解決,感覺跟版本依賴性有關,水挺深的,最終放棄,如果有讀者知道怎麼解決,誠盼你的留言告知。

總結

由於codeviz必須依賴特定版本的gcc(給其打補丁,並重新編譯),codeviz 的版本迭代遠遠跟不上gcc,造成安裝過於費勁(甚至以失敗告終,本次體驗就沒能安裝成功),讓人望而卻步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章