web-dev-qa-db-ja.com

アプリケーションで行われたすべての関数呼び出しのリスト

アプリケーションで呼び出されているすべての関数を一覧表示するにはどうすればよいですか。 GDBを使用してみましたが、そのバックトレースリストはmain関数呼び出しまでしかありませんでした。

より深いリスト、つまりメイン関数によって呼び出されているすべての関数と、これらの呼び出された関数から呼び出されている関数などのリストが必要です。

これをgdbで取得する方法はありますか?または、これを取得する方法についての提案をいただけますか?

22
broun

アプリケーションで呼び出されているすべての関数を一覧表示するにはどうすればよいですか

現実的なサイズのアプリケーションの場合、このリストには何千ものエントリが含まれるため、おそらく役に立たなくなります。

nmコマンドを使用して、アプリケーション内のすべての関数defined(ただし、必ずしも呼び出される必要はありません)を見つけることができます。

nm /path/to/a.out | egrep ' [TW] '

GDBを使用して、各関数にブレークポイントを設定することもできます。

(gdb) set logging on     # collect trace in gdb.txt
(gdb) set confirm off    # you wouldn't want to confirm every one of them
(gdb) rbreak .           # set a breakpoint on each function

続行すると、呼び出された関数ごとにブレークポイントがヒットします。 disableおよびcontinueコマンドを使用して先に進みます。 Pythonスクリプトを使用する場合を除いて、これを自動化する簡単な方法はないと思います。

すでに述べたgprofは、別の良いオプションです。

24

コールグラフが必要です。使用したいツールはgdbではなく、gprofです。 -pgを使用してプログラムをコンパイルし、実行します。実行すると、ファイルgmon.outが生成されます。次に、このファイルをgprofで処理して、出力を楽しんでください。

9
vy32

record function-call-history

https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html

Intel Processor Tracing (Intel PT、をサポートするCPUを使用している数少ない人々(2015)の1人であれば、これはハードウェアアクセラレーションの可能性が高いはずです。 intel_pt in /proc/cpuinfo)。

GDBのドキュメントは、次のような出力を生成できると主張しています。

(gdb) list 1, 10
1   void foo (void)
2   {
3   }
4
5   void bar (void)
6   {
7     ...
8     foo ();
9     ...
10  }
(gdb) record function-call-history /ilc
1  bar     inst 1,4     at foo.c:6,8
2    foo   inst 5,10    at foo.c:2,3
3  bar     inst 11,13   at foo.c:9,10

使用する前に、以下を実行する必要があります。

start
record btrace

これは、非対応のCPUが次のエラーで失敗する場所です。

 Target does not support branch tracing.

CPUサポートについては、以下でさらに説明します。 GDBでレコードの命令履歴および関数呼び出し履歴を実行する方法

関連スレッド:

組み込みの場合、JTAGとARMのサポートハードウェア [〜#〜] dstream [〜#〜] も検討しますが、x86のサポートはあまりよくありません: ハードウェアを使用したx86カーネルのデバッグデバッガ

この質問は、現在2つの回答のどちらであるかを決定するために説明が必要になる場合があります。必要なものによって異なります。

1)各関数が、呼び出し回数に対応する関数のストレートリスト/グラフ形式で何回呼び出されているかを知る必要があります。これは、コードが手続き型ではない場合(つまり、何が何を呼び出しているのかが明確でなく、ブランチアウト構造で他の関数を呼び出す関数)の場合に、あいまいで不確定な結果になる可能性があります。これは、-pgフラグを指定して再コンパイルする必要がある基本的なgprof機能です。

2)関数のリストは、呼び出された順序で必要です。これは、プログラムに依存します。これは、最良/実現可能なオプションです。a)プログラムが実行時エラーで実行および終了せずに終了する場合、この目的でgprofを使用できます。 b)上記のELSEオプションは、ロギングとブレークポイントでdbgを使用するときに、これを読んだときに学んだ残りのオプションです。

3)順序だけでなく、たとえば、各呼び出しの関数引数も知る必要があります。私の現在の仕事は粒子輸送の物理学のシミュレーションなので、異常な結果がどこから来ているのかを追跡するのに絶対に役立ちます...つまり、渡された引数が意味をなさなくなったとき。これを行う方法の1つは、次を使用することを除いて、ロシアの雇用者が行ったことのバリエーションになると思います。

(gdb)情報引数

このコマンドの結果をすべてのブレークポイント(関数呼び出しごとに設定)でログに記録すると、現在の関数の引数がわかります。

3
opetrenko