コードの絵による関数呼び出しグラフを取得するツール[終了]


106

Cコードの多くのソースファイルを含む大きなワークスペースがあります。オブジェクトブラウザーを使用してMS VS2005の関数から呼び出された関数を確認できますが、MSVC 6.0でも、特定の関数から呼び出された関数を非グラフィカルな種類のディスプレイでのみ表示します。さらに、say main()から呼び出された関数、次にそこから呼び出された関数など、リーフレベル関数のより深い内部は表示されません。

関数呼び出しグラフを絵で関数calleeで示しcaller、矢印などで接続して、main()関数の最後のレベルから開始するか、少なくとも1つのCソースファイル内のすべての関数の呼び出しグラフを絵で示すツールが必要です。このグラフを印刷していただければ幸いです。

それを行うための良いツールはありますか(無料のツールである必要はありません)?


回答:


53

2
CodeVizについてのQusetion、コードを渡すと、コードが生成されるかどうか、またはコードビスでグラフを作成する必要がありますか?
Mohammad Reza Rezwani 14

5
私はエジプトを試しました。それは恐ろしいグラフィックです。他の人についてはわかりません。
ar2015

29

動的分析法

ここでは、いくつかの動的解析方法について説明します。

動的メソッドは実際にプログラムを実行して、呼び出しグラフを決定します。

動的メソッドの反対は静的メソッドであり、プログラムを実行せずにソースのみから判断しようとします。

動的メソッドの利点:

  • 関数ポインタと仮想C ++呼び出しをキャッチします。これらは、重要なソフトウェアに多数存在します。

動的メソッドの欠点:

  • あなたはプログラムを実行する必要があります、それは遅いかもしれません、またはあなたが持っていないセットアップ、例えばクロスコンパイルを必要とします
  • 実際に呼び出された関数のみが表示されます。たとえば、一部の関数は、コマンドライン引数に応じて呼び出されたりされなかったりします。

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初期化ボイラープレートが含まれています
  • f0f1およびf2互いに予想どおりに呼び出されます
  • pointed関数ポインターで呼び出した場合でも、が表示されます。コマンドライン引数を渡した場合は、呼び出されなかった可能性があります。
  • not_called 追加のコマンドライン引数を渡さなかったため、実行時に呼び出されなかったため、表示されていません。

クールなこと valgrindは、特別なコンパイルオプションを必要としないことです。

したがって、ソースコードがなくても実行可能ファイルのみを使用できます。

valgrind軽量の「仮想マシン」を介してコードを実行することで、なんとかそれを実現します。これにより、ネイティブの実行と比較して実行が非常に遅くなります。

グラフからわかるように、各関数呼び出しに関するタイミング情報も取得され、これはプログラムのプロファイルに使用できます。これは、呼び出しグラフを表示するだけでなく、このセットアップの元の使用例である可能性があります。 Linuxで実行されているC ++コード?

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

特定のハードウェアトレースサポート以外に最も効率的な方法のようですが、コードを再コンパイルする必要があるという欠点があります。


2
動的呼び出しグラフはプログラムの1回の実行のみをカバーすることに注意してください。
smwikipedia 2018

1
@smwikipediaはい、わかりやすくするために答えをアップグレードしました
Ciro Santilli郝海东冠状病六四事件法轮功



9

当社のDMSソフトウェアリエンジニアリングツールキットには、Cコードの巨大なシステム(〜2500万行)に適用され、関数ポインターを介して呼び出される関数を含む、このような呼び出しグラフを生成する静的制御/データフロー/ points-to / callグラフ分析があります


1
ああ、いいですね、2016年、そして今度は投票者が現れました。彼の反対票は、このツールでは実行できないという正確な評価に基づいていたと思います。まあ、そうではないかもしれません。それは確かにOPが要求したことをします。
Ira Baxter

1
反対票を投じて反対します。それが仕事を
成し遂げる


5

私のbashベースのCコールツリージェネレーターはこちらで確認できます。呼び出し元や呼び出し先の情報が必要な1つ以上のC関数を指定できます。または、関数のセットを指定して、それらを接続する関数呼び出しの到達可能性グラフを決定できます...つまり、すべての方法を教えてくださいmain( )、foo()、およびbar()が接続されています。グラフエンジンにはgraphviz / dotを使用します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.