18

スタック内の深さに応じてインデントされた関数が呼び出されたときに、gdb が対象の関数を出力するようにするにはどうすればよいですか?

私は(でっち上げ)のようなことを言えるようになりたい:

(gdb) trace Foo* Bar* printf

そして、呼び出されたときに Foo または Bar で始まるすべての関数を gdb に出力させます。gnu cflow のようなものですが、デバッグ シンボルを使用し、実際に呼び出される関数のみを表示することを除いて、可能なすべての呼び出しフローではありません。

役に立たないツールには、関数が最も頻繁に呼び出された結果を並べ替える cachegrind、callgrind、および oprofile が含まれます。呼び出す順序を保持する必要があります。

多くの Foo および Bar 関数があるため、ワイルドカード (または同等のもの) は不可欠です。私は絶対にすべての機能を記録することに落ち着きますが. または、特定のライブラリにすべての関数を記録するように gdb に指示することもできます。

一部の GDB ウィザードには、この一般的なジョブのスクリプトが必要です!

4

5 に答える 5

8

あなたの場合define、gdb のコマンドを使用します。これにより、最大 10 個の引数を取ることができる関数を定義できます。

定義した関数の引数として "trace" に関数の名前を渡すことも、関数自体にそれらすべてを記録することもできます。私は次のようなことをします

define functiontrace
if $arg0
    break $arg0
    commands
        where
        continue
        end
    end

if $arg1
...

gdb のユーザー定義関数への引数は、$arg0 ~ $arg9 として参照されます。または、$arg0-9 を使用する代わりに、トレースしたいすべての関数を関数に記録することもできます。

注: これはスタック トレースの深さに関してインデントしませんが、関数が呼び出されるたびにスタック トレースを出力します。このアプローチは、必要な関数、システム、ライブラリ、ローカルなどをログに記録するため、strace などよりも便利だと思います。

于 2009-09-30T20:22:04.463 に答える
4

rbreakブレークポイントを設定するための正規表現を受け入れる cmdがあります。以下を使用できます。

(gdb) rbreak Foo.*
(gdb) rbreak Bar.*
(gdb) break printf

ブレークポイントの詳細については、こちらを参照してください。

次に、commands呼び出されたすべての関数を出力するために使用します。たとえば、α = 最後のブレークポイントの番号(失敗したかどうかを確認できi brます)とし、次のようにします。

(gdb) commands 1-α
Type commands for breakpoint(s) 1-α, one per line.
End with a line saying just "end".
>silent
>bt 1
>c
>end
(gdb) 

いくつかの詳細:silent不要な情報メッセージを抑制bt 1し、バックトレースの最後のフレーム(つまり、現在の関数)を出力し、実行を継続cするためのショートカットであり、コマンド リストの単なる区切り文字です。continueend

注意: ライブラリ関数をトレースする場合は、lib がロードされるまで待つ必要がある場合があります。たとえば、main任意の関数にブレークを設定し、その時点までアプリを実行してから、必要なブレークポイントを設定します。

于 2013-01-30T05:04:27.933 に答える
2

仕事に適したツールを使用してください ;)

次のN実行行をGDBで自動的に印刷する方法は?

于 2009-07-14T02:59:38.617 に答える
1

ここで同様の投稿に対するlitbの優れた回答を見ましたか?

彼は readelf を使用して興味深いシンボルを取得し、gdb コマンドを使用してトレースを取得し、awk を使用してそれらすべてを接着します。

基本的に変更する必要があるのは、彼の gdb コマンド スクリプトを変更して、バックトレースから 1 深度を削除してスタックを表示し、特定の関数をフィルター処理し、awk/python/(...) スクリプトで出力を再フォーマットして、それを木。(私は今それをするのが面倒だと認めています...)

于 2008-11-23T01:29:20.607 に答える
0

gdbバッチ モードで (オプションを使用して)呼び出し、-x必要な場所で中断し、バックトレース ( ) を要求してから、またはbtを使用して結果をフィルター処理することができます。grepegrep

インデントはより困難ですが、bt出力が順序付けられているため、トレースの上部とmain下部に現在の関数が表示されます。

したがって、次のコマンドでファイルを作成します。

br <function name where to break>
run
bt
kill
quit

次に実行しますgdb <program> -x<command file>

-で始まる文字列をフィルター処理すると#<digit>、スタック トレースが取得されます。

于 2008-11-23T07:53:11.503 に答える