オープンソースコードツールを見てください-Graphviz + CodeVizを使用してC / C ++関数呼び出しグラフ(呼び出しグラフ)を生成します



Look Open Source Code Tool Use Graphviz Codeviz Generate C C Function Call Graph



1. Graphviz + CodeVizの簡単な紹介

CodeVizは、「Understanding The Linux Virtual Memory Manager」の著者であるメル・ゴーマンによって書かれたオープンソースツールであり、C / C ++ソースコードの関数呼び出し関係を分析します(同様のオープンソースソフトウェアには エジプトGraphviz グラフィックを描く( Graphviz バックエンドに属し、CodeVizはフロントエンドに属します)。

CodeVizは元々、Linux仮想メモリのソースコードを分析するために作者によって書かれた小さなツールでした。今では基本的にC ++言語をサポートしています。最新バージョン1.0.9は、Windows + Cygwinで正常にコンパイルおよび使用できます。



基本的な紹介はこちらです。その原則に興味がある場合は、次の記事を参照してください。 関数呼び出しグラフを分析するいくつかの方法




次に、Graphviz + CodeVizをコンパイルしてインストールします

1.GraphVizをインストールします

コールグラフの生成はGraphVizに依存するため、最初にGraphVizをインストールします。ソースパッケージをダウンロードしてコンパイルおよびインストールできます(ダウンロードホームページ: http://www.graphviz.org/Download.php )。
Ubuntuシステムの場合は、apt:sudo apt-get installgraphvizで直接インストールできます。

2.CodeVizをインストールします

CodeVizeソースパッケージをダウンロードします。 解凍したディレクトリを入力します:cd codeviz-1.0.12 /

CodeVizはGCCコンパイラのパッチバージョンを使用し、異なるCodeVizバージョンは異なるGCCバージョンを使用します。 CodeVizソースパッケージをダウンロードし、Makefileファイルをチェックして、使用するGCCバージョンを決定できます。

このために、codeviz-1.0.12はGCC-4.6.2を使用します。実際、CodeVizをインストールするとき、インストールスクリプトmakeは現在のGCCバージョンをチェックします。一致しない場合は、対応するGCCを自動的にダウンロードしてパッチを適用しますが、GCCが大きいため、ネットワーク速度が悪く、仮想マシン内にある場合は、ダウンロードしやすいか、システムエラーが発生します。 、したがって、ここでも段階的にインストールし、最初にgccをインストールしてから、戻ってCodeVizをインストールします。


(1)GCCをインストールします

gcc-4.6.2.tar.gzをcdcodeviz-1.0.12ディレクトリのコンパイラにダウンロードします。
ダウンロードアドレス:ftp://ftp.gnu.org/pub/gnu/gcc/gcc-4.6.2/gcc-4.6.2.tar.gz

CodeVizのインストールスクリプトコンパイラ/install_gcc-4.6.2.shは、コンパイラディレクトリにgccソースパッケージがあるかどうかを自動的に検出します。ない場合は、自動的にダウンロードしてパッチを適用します。すでにここにダウンロードしています。ディレクトリに移動するだけで、残りは解凍とインストールです。 install_gcc-3.4.6.shはgccを解凍してパッチを適用し、指定されたディレクトリにインストールします。指定されたディレクトリがない場合、デフォルトでは$ HOME / gcc-graphを使用し、通常は/ usr /にインストールするように指定されます。
local / gcc-graph(現時点ではroot権限が必要です)。

インストール:./ install_gcc-4.6.2.sh

注:インストール中にエラーが発生する場合があります。特定のエラーと解決策については、以下を参照してください。


(2)CodeVizをインストールします
./configure && make install-codeviz

注1:makeの役割はgccがあるかどうかを検出し、ない場合はソースパッケージをダウンロードすることであるため、makeは必要ありません。ここにcodevizをインストールするだけです。詳細については、Makefileを確認してください。

注:ここでmake installの役割は、最初にgccをインストールしてからcodevizをインストールすることであり、gccは以前にインストールされているため、ここでは通常のmake installが行われないのはなぜですか。したがって、ここではcodevizをインストールするだけです。スクリプトの場合、スクリプトはgenfullとgengraphを/ usr / local / binディレクトリにコピーします。

これで、CodeVizのインストールは完了です。


3.基本的な実用的な方法

GraphVizは、さまざまなスタイルのコールグラフの生成をサポートしていますが、追加のサポートツールやライブラリプログラムをインストールする必要がある場合もあります。興味のある友人は、 公式サイト 関連情報を検索します。この記事ではCodeVizの使用に焦点を当てていますが、特定の画像スタイルコントロールについては詳しく説明しません。

CodeVizは2つのスクリプトを使用してコールグラフを生成します。1つはgenfullで、スクリプトはプロジェクトの完全なコールグラフを生成できるため、コールグラフは非常に大きく複雑になる可能性があります。デフォルトでは、cdepnファイルを使用してコールグラフを作成します。 gengraph、スクリプト特定の関数セットに対して小さなコールグラフを生成でき、対応するポストスクリプトファイルも生成できます。これらの2つのスクリプトは、インストール時に/ usr / local / binディレクトリにコピーされるため、パスを指定せずに直接使用できます。基本的な手順は次のとおりです。

以下例として、単純なtest.cファイルをコンパイルします。

1.新しくインストールされたgcc-4.6.2を使用して、現在のディレクトリ内のすべての.cファイルをコンパイルします。gcc/ g ++は、コンパイルされたC / C ++ファイルごとに.cdepnファイルを生成します。コンパイルするだけで(パラメーター-c)、リンクする必要はありません。

つまり:$〜/ gcc-graph / bin / gcc test.c


2. genfulを呼び出すと、現在のディレクトリにfull.graphファイルが生成されます。このスクリプトは、プロジェクトの完全なコールグラフ情報ファイルを生成し、ソースコード内およびそれらの間のすべての関数の場所を記録することができます。したがって、コールグラフ情報ファイルは非常に大きく複雑になる可能性があります。デフォルトでは、cdepnファイルを使用してコールグラフ情報ファイルを作成します。

つまり:$ genfull


3. gengraphを使用して、特定の関数セットの小さなコールグラフを生成し、関数呼び出しの関係を示します。

つまり:$ gengraph


4つの簡単な例のデモンストレーション

自分で簡単なプログラムを書いて、その効果を見てください~~~

// test.c #include void test1() void test2() void test3() int main() { test1() test2() return 0 } void test1() { } void test2() { test2() } void test3() { }

以下に示すように、上記の3つの手順を順番に実行します。



main.psを開き、一目で次のような効果を確認します。



5、高度な使用

もちろん、誰もがCodeVizを使用するのは、遊ぶためではなく、実際のプロジェクトのためです。 4つの学校を単純に使用するだけでは不十分です。もう少し深く見ていきましょう。

1.上記の実行フローを分析してみましょう

まず、新しくインストールしたgccを使用して.cファイルをコンパイルします(PS:ここでは、gccをインストールした場所を指定する必要があります。そうしないと、インストールしたgccの代わりにシステムgccが使用されます)。次に、genfullによってfull.graphファイルが作成されます。 genfull--helpまたはgenfull--manを使用して、使用方法を確認できます。最も簡単な方法は、プロジェクトの最上位ディレクトリにパラメータなしで実行することです。プロジェクトの完全な通話情報は非常に大きいため、通常はプロジェクトのfull.graphを生成し、genfullを使用して必要な通話情報を取得するだけです。完全な情報が必要な場合は、full.graphがドットで処理されてから表示され、ポストスクリプトファイルが生成されます。 (ドットはGraphVizのツールであり、特定の使用法は詳細に研究されていません。興味のある読者はそれを自分で参照できます~~~)。 test.cが配置されているディレクトリに対してgenfullを実行し、full.graphファイルが生成されることを確認します。猫を使って見ることができます。次に、gengraphを使用して関数呼び出しグラフを生成します。 gengraph--helpまたはgengraph--manを使用して、その使用方法を確認できます。私にとっては、次のオプションに焦点を当てるだけで十分です。

-f:最上位関数、つまりmainなどの入力関数を指定します(もちろん、mainに限定されません)。

-o:出力ポストファイルファイル名を指定します。指定しない場合は、上記のメインなどの関数名です。

--output-type:png、gif、html、psなどの出力タイプを指定します。デフォルトは上記のmain.psのようにpsです。

-d:呼び出しレイヤーの最大数を指定します

-s:呼び出しを展開せずに、指定された関数のみを表示します

-i:指定された関数を無視します

-t:Linux固有のカーネル関数セットを無視します

-k:sub.graphとして、-sによって無視された内部詳細によって形成された中間ファイルを保持します

2. gengraphを使用する場合のオプションパラメータ値は、 ''で囲む必要があります。例:

gengraph --output-type'png '-f main

3.名前の競合

複雑なプロジェクトでは、full.graphは完全ではありません。たとえば、カーネルモジュールには同じ名前の関数がたくさんあります。現時点では、genfullはそれらを区別できません。それを解決するには2つの方法があります。最初の方法は複雑すぎてエラーが発生しやすくなります。推奨されません。 -sオプションの-sは、検出するサブディレクトリを指定します。たとえば、alloc_pages関数はカーネルのmmディレクトリとdrivers / char / drmディレクトリで定義されている場合、genfullは次の方法で呼び出すことができます。

genfull -s'mm include / linux drivers / block arch / i386 '

実際の使用では、-sは非常に便利です。このオプションを覚えておいてください。

4.デーモン/クライアントモードを使用します

full.graphが大きい場合、入力ファイルの読み取りに多くの時間が費やされます。たとえば、カーネルのfull.graphは非常に大きく、以前に生成されたものは約15Mです。これは、カーネルのすべての関数呼び出し分析情報ではありません。時間を節約するために、gengraphはデーモンモードで実行されていると言えます。この薬は-pオプションを使用します。

gengraph -p -g linux-2.6.25 / full.graph

コマンドが戻ると、gengraphはデーモンモードで実行され、codeviz.pipeファイルが/ tmpディレクトリに生成されます。関数呼び出しグラフを生成するには、-qオプションを使用できます。

gengraph -q -t -d 2 -f alloc_pages

gengraphの操作を終了するには、次のコマンドを使用します。

エコーQUIT> /tmpcodeviz.pipe


6.高度なデモ

「組み込みリアルタイムオペレーティングシステムuC / OS-II(第2版)」の最初のサンプルプログラムの分析を例にとると、どのプログラムを使用するかは問題ではありません。ここでは、主に使用方法と使用後の効果について説明します。


最初にメイン()を分析します。

1. gengraph --output-type gif -f main
main()のコールグラフを分析すると、得られたグラフは次のようになり、本質がわかりません。

2. gengraph --output-type gif -f main -s OSInit
OSInit()(parameters -s)の内部実装の詳細は気にしないでください。ノードとして表示されます。結果の画像は次のようになり、少し乱雑になりますが、はるかに優れています。

3. gengraph --output-type gif -f main -s OSInit -i 'OSCPUSaveSROSCPURestoreSR'
基本的に、すべての関数にはクリティカルセクションに出入りするためのコードがあり、それを無視します(パラメーター -i)。得られた画像は次のとおりで、基本的に明確です。

4. gengraph --output-type gif -f main -s 'OSInitOSSemCreate' -i 'OSCPUSaveSROSCPURestoreSR' -k
OSSemCreate()の内部の詳細は気にしないようですが、中間ファイルのsub.graph(パラメーターは保持されます -k)、結果の画像は次のようになります。

5. dot -Tgif -o main.gif sub.graph
sub.graphを変更して、グラフが関数呼び出しシーケンスに準拠するようにします。最終的な図は次のとおりです。これにより、コードを確認する必要がなくなります:)

次に、OSTimeDly()の呼び出し関係を分析します。

gengraph --output-type gif -r -f OSTimeDly

OSTimeDly()を呼び出す関数を確認します。パラメーター-r、Task()、およびTaskStart()は、すべてユーザーが作成した関数です。

最後に、どの関数がTask()によって直接呼び出されるかを見てみましょう。

gengraph --output-type gif -d 1-fタスク

タスクからの最初の呼び出しを見てください(パラメーター-d 1):



7、インストールプロセスのエラーと解決策

1. ./install_gcc-4.6.2.shを実行すると、次のエラーが表示されます。

gcc configure:エラー:GCCのビルドには、GMP 4.2以降、MPFR 2.3.1以降、およびMPC0.8.0以降が必要です。

エラーからわかります:GCCコンパイルにはGMP、MPFR、MPCの3つのライブラリが必要です(一部のシステムはこのプロンプトなしでインストールされ、私のものはインストールされません)、2つのインストール方法があります(2番目が推奨されます):

(1)バイナリソースのインストール(強くお勧めしません)

私が使用しているバージョンは、gmp-4.3.2、mpfr-2.4.2、mpc-0.8.1です。 ftp://gcc.gnu.org/pub/gcc/infrastructure/ '提案された順序に従って、GMP、MPFR、およびMPC(mpfrはgmpに依存し、mpcはgmpおよびmpfrに依存します)をダウンロードしてインストールします。すべてのインストールディレクトリはここで指定されます。指定しない場合、それらは/ usr / includeにインストールされ、/ usr / libおよび/ usr / shareは管理に不便です。たとえば、アンインストールする場合は、次のものを1つずつ見つける必要があります。

gmpをインストールします:./ configure --prefix = / usr / local / gmp-4.3.2 make install

mpfrをインストールします。./configure--prefix=/ usr / local / mpfr-2.4.2 --with-gmp = / usr / local / gmp-4.3.2 / make install

mpcをインストールします:./ configure --prefix = / usr / local / mpc-0.8.1 --with-gmp = / usr / local / gmp-4.3.2 / --with-mpfr = / usr / local / mpfr- 2.4.2 / make install

PS:インストールプロセス中に新しいエラーメッセージが表示される場合があります。2、3、および4を参照してください。

構成環境変数:ここでインストール場所を指定しました。指定しない場合、これらのライブラリのデフォルトの場所は/ usr / local / includeおよび/ usr / local / libです。GCCが指定されているかどうかに関係なく、見つからない場合があります。これら3つのライブラリについて、ライブラリの場所は環境変数LD_LIBRARY_PATHにあり、コマンドを使用して環境変数の内容を表示できます。
$ echo $ LD_LIBRARY_PATH
この環境変数を設定するコマンドは次のとおりです。

インストールを指定します:export LD_LIBRARY_PATH = $ LD_LIBRARY_PATH:/usr/local/gmp-4.3.2/lib:/usr/local/mpfr-2.4.2/lib:/usr/local/mpc-0.8.1/lib

デフォルトのインストール:$ export LD_LIBRARY_PATH = '$ LD_LIBRARY_PATH:/ usr / local / lib

PS:このインストール方法はお勧めできません。一般的に、正常にインストールできますが、インストールプロセス中の新しい問題を除外するものではありません。詳細については、質問5を参照してください。


(2)gccにはスクリプトのインストールが付属しています(強くお勧めします)

方法(1)のインストール方法は非常に面倒で、インストールプロセス中にさまざまな予期しない新しいエラーが発生する可能性があるため、gccソースパッケージには、gccソースディレクトリのcontrib / download_prerequisitesにあるgcc依存ライブラリインストールスクリプトdownload_prerequisitesが付属しています。したがって、ディレクトリを入力し、スクリプトを直接実行してインストールします。./download_prerequisites

PS:スクリプトの内容は次のとおりです。

#! /bin/sh # Download some prerequisites needed by gcc. # Run this from the top level of the gcc source tree and the gcc # build will do the right thing. # # (C) 2010 Free Software Foundation # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see http://www.gnu.org/licenses/. MPFR=mpfr-2.4.2 GMP=gmp-4.3.2 MPC=mpc-0.8.1 wget ftp://gcc.gnu.org/pub/gcc/infrastructure/$MPFR.tar.bz2 || exit 1 tar xjf $MPFR.tar.bz2 || exit 1 ln -sf $MPFR mpfr || exit 1 wget ftp://gcc.gnu.org/pub/gcc/infrastructure/$GMP.tar.bz2 || exit 1 tar xjf $GMP.tar.bz2 || exit 1 ln -sf $GMP gmp || exit 1 wget ftp://gcc.gnu.org/pub/gcc/infrastructure/$MPC.tar.gz || exit 1 tar xzf $MPC.tar.gz || exit 1 ln -sf $MPC mpc || exit 1 rm $MPFR.tar.bz2 $GMP.tar.bz2 $MPC.tar.gz || exit 1

目に見えるのはwgetを介してダウンロードしてインストールすることです。したがって、wgetがインストールされていない場合は、最初にインストールする必要があります。

誰もがこのスクリプトを詳しく調べたところ、非常に単純であることがわかりました。これは、インターネットから3つの依存ライブラリを自動的にダウンロードして解凍し、これら3つのライブラリを指す3つの名前が変更されたソフトリンクを作成することです。ここでは、ソフトリンクを確立するプロセスでエラーが発生する可能性があります。質問6を参照してください。スクリプトを自分で変更し、名前を直接変更してから、gccディレクトリに移動することもできます。

ヒント:ここから、gccが依存するライブラリは、解凍されてgccの現在のディレクトリに配置されている限り実際に存在することがわかります。実際、方法(1)の多くのステップを保存でき、直接ダウンロードされた3つの圧縮パッケージは解凍されます。名前を変更して以下のgccに移動した後は、環境変数を設定する必要はありません。


2.gmpのコンパイル中にエラーが発生しました。

$ PATHまたは/ usr / 5binに使用可能なm4がありません(理由についてはconfig.logを参照してください)。
これは、M4ファイルが欠落していることを示しています。 http://ftp.gnu.org/gnu/m4/からダウンロードして、コンパイルしてインストールできます。私はUbuntuシステムなので、直接アクセスします。

sudo apt-get installm4がインストールされます。


3. mpfrのインストール中にエラーが発生しました:

configure:エラー:gmp.hが見つからないか、使用できません。

これは、mpfrをインストールするときに最初にgmpをインストールしないことが原因で、mpfrはgmpに依存します。


4.mpcのインストール中にエラーが発生しました。

configure:エラー:libgmpが見つからないか、別のABIを使用しています。および構成:エラー:libmpfrが見つからないか、別のABIを使用しています。 '。

また、mpcが依存するライブラリgmpおよびmpfrがインストールされていないためです。


5. ./install_gcc-4.6.2.shの実行中にエラーが発生しました。つまり、gccプロセス中に発生した問題です。

(1)libmpfr.so.1:共有オブジェクトファイルを開くことができません:そのようなファイルまたはディレクトリはありません

分析:スクリプトはgccをインストールすることですが、問題1があり、方法(1)を使用して問題を解決する場合、もちろん、運が悪ければ、後の段階でそのような問題が発生する可能性があります。この問題は通常発生しません。 、とにかく、私は逃げます、そのような問題が発生しました。

解決策:この記事http://blog.csdn.net/leo115/article/details/7671819を参照して解決できます。


(2)../../ gcc-4.6.2 / gcc / realmpfr.h:27:17:致命的なエラー:mpc.h:そのようなファイルまたはディレクトリはありません
分析:gccは、依存しているライブラリmpcを検出しませんでした。多くの理由があります。最も可能性の高い理由は、環境変数を設定していないか、mpcが配置されている場所が間違っていることです。

解決策:環境変数を設定します。質問1を参照してください。


(3)/usr/include/stdc-predef.h:30:26:致命的なエラー:bits / predefs.h:そのようなファイルまたはディレクトリはありません

分析:コマンド 'を使用しますビット/predefs.hを見つけます'ヘッダーファイルのパスを見つけて、そこにあることを見つけます'/ usr / include / x86_64-linux-gnu'
解決策:環境変数を設定します。
#export C_INCLUDE_PATH = / usr / include / i386-linux-gnu && export CPLUS_INCLUDE_PATH = $ C_INCLUDE_PATH


(4) / usr / bin / ld:crti.oが見つかりません:そのようなファイルまたはディレクトリはありません

分析:また、「locate crti.o」を使用して、このファイルを「/ usr / lib /」で検索します。i386-linux-gnu / crti.o '

解決策:LIBRARY_PATH(LDFLAGS)環境変数を次のように設定します。
#export LIBRARY_PATH = / usr / lib / i386-linux-gnu


(5)unwind-dw2.c:1031:エラー:フィールド `info 'のタイプが不完全です

分析:インターネット上に対応する解決策がないため、このエラーは長い間発生しています。これはgccのバグであるということだけです。

解決策:ソースファイルを深く調べて、次のようなエラーを見つけます。

static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) { struct dwarf_fde *fde struct dwarf_cie *cie const unsigned char *aug, *insn, *end memset (fs, 0, sizeof (*fs)) context->args_size = 0 context->lsda = 0 fde = _Unwind_Find_FDE (context-> ra-1, & context-> bases) // NULL is returned here if (fde == NULL) { /* Couldn't find frame unwind info for this function. Try a target-specific fallback mechanism. This will necessarily not profide a personality routine or LSDA. */ #ifdef MD_FALLBACK_FRAME_STATE_FOR MD_FALLBACK_FRAME_STATE_FOR (context, fs, success) // where something went wrong return _URC_END_OF_STACK success: return _URC_NO_REASON #else return _URC_END_OF_STACK // return on error #endif } ..... }

fdeがNULLを返し、フレーム巻き戻し情報が見つからないため、エラーが発生した場所がマークされます。最も重要なのは、次の方法です。

MD_FALLBACK_FRAME_STATE_FOR (context, fs, success)

エラーがありました、なぜ私はNULLを返しました、私は確かにそれを研究することはできません、この関数呼び出しが失敗したことを知っているだけで失敗したので、私の解決策は非常に怠惰です、次の2行をコメントアウトしてください、直接成功、ハハ、スプレーしないでください、そうして解決したので、ずっと成功しました~~~

// MD_FALLBACK_FRAME_STATE_FOR (context, fs, success) // where something went wrong // return _URC_END_OF_STACK

6.6。ln-sソフトリンクによって生成されたToomanylevelsofsymboliclinksエラーを解決します

私はインターネットから理由を見つけました。ソフト接続の確立時に相対パスが使用されていることが判明したため、このエラーが発生しました。解決策は、絶対パスを使用してソフトリンクを確立することです。したがって、問題は解決されます。


8.まとめ

この記事では、インターネット上の多くの資料を参照して、CodeVizのインストールと使用について詳しく説明しました。 CodeVizはGraphVizに依存しているため、非常に豊富な関数呼び出しグラフを生成できます。特定のオプションの使用と画像形式の選択は、読者が個人的なニーズや好みに応じて使用できます。ソースコードを分析するときは、これらのグラフィックを手元に印刷してメモしてください。これは非常に便利で有益です。


9.参考資料:

1. http://blog.csdn.net/delphiwcdj/article/details/9936717

2. http://www.cppblog.com/hacrwang/archive/2007/06/30/27296.html

3. http://www.cnblogs.com/xuxm2007/archive/2010/10/14/1851086.html