2009-10-08 4 views
18

私は内部から巨大なアプリケーションに特定のメッセージが印刷されていることを知っています。アプリケーションはとても大きく、古いので、端末にテキストを印刷する考えられるすべての方法を使用します。 (printf()、fprintf(stdout、...)など)gdbの「端末に何かが印刷されています」にブレークポイントを設定するにはどうしたらいいですか?

write()システムコールにブレークポイントを設定するために書き込みを行いますが、ファイルI/O操作はwrite()も使用します。

基本的には、プログラムが端末に何かを印刷するときにgdbを停止したいが、同時にプログラムが何かをファイルに書き込むときにgdbを停止させたくない。

+1

は私がに置かれているものを監視するにはどうすればよい[も参照してください。標準出力バッファと特定の文字列がパイプに格納されたときに中断?](http://stackoverflow.com/questions/8235436/how-can-i-monitor-whats-being-put-into-the-standard- out-buffer-and-break-when-a) –

+0

端末に表示される「何か」のソースを 'grep'してそこにブレークポイントを置くことはできませんか? – Calmarius

答えて

18

最初のパラメータをチェックする条件付きブレークポイントを使用します。 64ビットのx86システム上での条件は次のようになります。

(GDB)のB書き込み== $のRDI 32ビットシステムで

1場合は、パラメータがスタック上にあるので、それはつまり、より複雑です$ espをint *にキャストし、fdパラメータをインデックスする必要があります。その時点のスタックには、リターンアドレス、長さ、バッファ、最後にfdがあります。

これは、ハードウェアプラットフォームによって大きく異なります。 GDB 7.0

+1

私はこれをちょっと説明して、FD番号が "*(int)($ esp + 4)"、文字列の長さが "(int)*(int)($ esp + 12)"として利用可能であることを発見しました。最後に、文字列データを "*(int)($ esp + 8)"とします。 1 == *(int型)($ ESP + 4) コマンド プリント(int型)*(int型)($ ESP + 12) X/sの場合 ブレーク書き込み: だからSTDOUTのために、あなたのような何かを行うことができますしかし、実際にこのアプリケーションを_huge_アプリケーションで使用しようとしたときに、このメソッドはリダイレクトなどを処理しないため、このメソッドは絶対に安全ではないことが判明しました。これは、アプリケーションがdup2を使用する場合などです。 ()をstdoutに置くと、stdoutにいくつかのものが印刷されないことがあります。 – martin

+0

もう少し洗練された試行があります:

 break write commands silent if !isatty(*(int)($esp + 4)) c end echo \ntty write(), size: x/d (int)($esp + 12) echo tty write(), data: x/s *(int)($esp + 8) end 
martin

11

、あなたは(システムコールの書き込みに条件付きブレークポイントを設定することができます):

(gdb) catch syscall write 
Catchpoint 1 (syscall 'write' [4]) 
(gdb) condition 1 $ebx==1 

$のEBXは、最初のシステムコールのパラメータが含まれている - ここでFD番号

+0

注: 'printf'はバッファリングされているので、連結された2番目の' printf'呼び出しの最初の 'printf'の' write'しか見ることができません。 –

関連する問題