Cコードの多くのソースファイルがある大きなワークスペースがあります。 MS VS2005の関数から呼び出された関数はオブジェクトブラウザーを使用して確認できますが、MSVC 6.0でも、これは特定の関数から呼び出された関数のみを非グラフィカルな種類のディスプレイに表示します。また、たとえばmain()
から開始して呼び出される関数、およびそれから呼び出される関数などは、リーフレベル関数のより深い内部には表示されません。
関数callee
とcaller
が矢印などで接続され、main()
から最後のレベルまでの関数呼び出しグラフを絵で表示するツールが必要です。関数、または少なくとも1つのCソースファイル内のすべての関数の呼び出しグラフを絵で表示します。このグラフを印刷できたら素晴らしいと思います。
それを行うための良いツールはありますか(無料のツールである必要はありません)?
エジプト (フリーソフトウェア)
KcacheGrind (GPL)
Graphviz (CPL)
CodeViz (GPL)
動的解析方法
ここでは、いくつかの動的解析方法について説明します。
動的メソッドは、実際にプログラムを実行して呼び出しグラフを決定します。
動的メソッドの反対は静的メソッドです。静的メソッドは、プログラムを実行せずにソースのみから決定しようとします。
動的な方法の利点:
動的メソッドの欠点:
KcacheGrind
https://kcachegrind.github.io/html/Home.html
テストプログラム:
int f2(int i) { return i + 2; }
int f1(int i) { return f2(2) + i + 1; }
int f0(int i) { return f1(1) + f2(2); }
int pointed(int i) { return i; }
int not_called(int i) { return 0; }
int main(int argc, char **argv) {
int (*f)(int);
f0(1);
f1(1);
f = pointed;
if (argc == 1)
f(1);
if (argc == 2)
not_called(1);
return 0;
}
使用法:
Sudo apt-get install -y kcachegrind valgrind
# Compile the program as usual, no special flags.
gcc -ggdb3 -O0 -o main -std=c99 main.c
# Generate a callgrind.out.<PID> file.
valgrind --tool=callgrind ./main
# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234
これで、多くの興味深いパフォーマンスデータが含まれる素晴らしいGUIプログラムの内部に残ります。
右下で、「コールグラフ」タブを選択します。これは、関数をクリックすると、他のウィンドウのパフォーマンスメトリックと相関するインタラクティブな呼び出しグラフを示します。
グラフをエクスポートするには、グラフを右クリックして、「グラフのエクスポート」を選択します。エクスポートされたPNGは次のようになります。
それから次のことがわかります。
_start
は、実際のELFエントリポイントであり、glibc初期化ボイラープレートが含まれていますf0
、f1
およびf2
は互いに期待どおりに呼び出されますpointed
も表示されます。コマンドライン引数を渡した場合は、呼び出されていない可能性があります。not_called
は、追加のコマンドライン引数を渡さなかったため、実行時に呼び出されなかったため表示されません。valgrind
の素晴らしい点は、特別なコンパイルオプションを必要としないことです。
そのため、ソースコードがなくても実行可能ファイルのみを使用できます。
valgrind
は、軽量の「仮想マシン」を介してコードを実行することにより、それを管理しています。
Ubuntu 18.04でテスト済み。
gcc -finstrument-functions
+ etrace
https://github.com/elcritch/etrace
-finstrument-functions
コールバックを追加 、etraceはELFファイルを解析し、すべてのコールバックを実装します。
しかし、残念ながら動作させることができませんでした: 「-finstrument-functions」が機能しないのはなぜですか?
要求された出力は次の形式です。
\-- main
| \-- Crumble_make_Apple_crumble
| | \-- Crumble_buy_stuff
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | \-- Crumble_prepare_apples
| | | \-- Crumble_skin_and_dice
| | \-- Crumble_mix
| | \-- Crumble_finalize
| | | \-- Crumble_put
| | | \-- Crumble_put
| | \-- Crumble_cook
| | | \-- Crumble_put
| | | \-- Crumble_bake
特定のハードウェアトレースサポートに加えて最も効率的な方法と思われますが、コードを再コンパイルする必要があるという欠点があります。
nderstand は、コールグラフの作成に非常に適しています。
DMS Software Reengineering Toolkit には static control/dataflow/points-to/call graph analysis があり、Cコードの巨大なシステム(〜2,500万行)に適用されています。そして、そのようなコールグラフを生成しました、関数ポインタを介して呼び出された関数を含みます。
BashベースのC呼び出しツリージェネレーター here を確認できます。呼び出し元や呼び出し先の情報が必要な1つ以上のC関数を指定できます。または、関数のセットを指定して、それらを接続する関数呼び出しの到達可能性グラフを決定できます。 main()、foo()、およびbar()が接続されるすべての方法を教えてください。グラフ作成エンジンにgraphviz/dotを使用します。
Astrée は、最も堅牢で洗練されたツールです。