他の人が書いたコードでバグを修正しようとしていますが、何が起きているのか把握するためにgdbで実行しようとしています。しかし、私が打つ行の1つはlongjmp()の呼び出しで、その行の "next"を押すとgdbは実行されている次のソース行を壊すのではなく、通常の実行を続けます。 longjmp()行で「ステップ」を実行すると、同様の続きが発生します。 longjmp()の後に実行されている次のソース行でブレークするgdbコマンドはありますか?gdbでlongjmpを実行する方法
答えて
ゼロ以外の戻りコードに続く行にブレークポイントを設定する必要があります(setjmp
)。例えば
:
#include <stdio.h>
#include <setjmp.h>
jmp_buf jb;
void f1()
{
printf("jumping\n");
longjmp(jb, 1);
printf("what???\n");
}
int main()
{
if (!setjmp(jb)) {
printf("calling f1\n");
f1();
} else {
printf("jumped!!\n"); // line 19
}
return 0;
}
longjmp
を呼び出した後、実行すべき次のラインは、ライン19(コメントを参照します)。したがってこの場合は、gdbプロンプトでbreak 19
を実行し、longjmp
の呼び出し後にその行で停止します。
gdbの出力:
(gdb) break 19
Breakpoint 2 at 0x40056d: file /tmp/x1.c, line 19.
(gdb) start
Temporary breakpoint 3 at 0x400549: file /tmp/x1.c, line 15.
Starting program: /tmp/x1
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000
Temporary breakpoint 3, main() at /tmp/x1.c:15
15 if (!setjmp(jb)) {
(gdb) step
16 printf("calling f1\n");
(gdb)
calling f1
17 f1();
(gdb)
f1() at /tmp/x1.c:8
8 printf("jumping\n");
(gdb)
jumping
9 longjmp(jb, 1);
(gdb)
Breakpoint 2, main() at /tmp/x1.c:19
19 printf("jumped!!\n");
(gdb)
jumped!!
21 return 0;
(gdb)
22 }
(gdb)
0x0000003fa441d9f4 in __libc_start_main() from /lib64/libc.so.6
(gdb)
これは基本的に働いた。 setjmpが最後に呼び出されたものが何であるか把握するのに少し時間がかかりましたが、十分なsetjmpsが0以外の値に戻った後にブレークポイントを設定した後、プログラムがどこに行かれたかが分かりました。 –
は、私が)のlongjmp(後に実行されている次のソース行でブレークするために使用できる任意のGDBコマンドはありますか?
私が知る限りではありません。 jmp_buf
の起源をトレースして、コールスタックをバックアップして、それが満たされたsetjmp()
を見つけ出す必要があります。ソース内のsetjmp()
コールが少ない場合、それぞれの後にブレークポイントを設定することを検討することができます。それ以外の場合は、プログラムをステップ実行し、各setjmp()
がパスした後にブレークポイントを設定します。
対応するlongjmp()
に達すると、コールスタック内の関数の1つに該当するsetjmp()
が見つかるはずです。そうでない場合はjmp_buf
が無効です。
bt
コマンドを使用してコールスタックを取得し、frame
コマンドを使用してスタック上のフレームに切り替えて検査することができます。
gdbの動作はシステムによって異なることに注意してください。
Linuxの、next
あなたが期待するよう約働くlongjmp
上またはthrow
:非ローカルジャンプのターゲットがでたり、現在のフレームの上にある場合、実行が停止します。
これは、longjmp
とthrow
の実装でデバッグフックを使用して実装されています。 throw
の場合、これはヘルパー機能(旧アプローチ)といわゆるSystemTapプローブ(別名「sdtプローブ」)の両方で行われます。 longjmp
の場合、これはglibcのsdtプローブでのみ行われます。
これを機能させるには、プローブサポートを問題のライブラリにコンパイルする必要があります。 readelf -n
で確認できます。少なくともFedoraはこれを適切に行います。
gdbの他のプラットフォームではlongjmp
のサポートを実装することは理論上可能です。しかし、それは自明ではないかもしれません。
他のコメントに記載されているように、jmp_buf
のデコードを試みることができます。ただし、セキュリティ上の理由から、Linuxなどの一部のシステムでは、jmp_buf
のターゲットPCがエンコードされています。だからあなたはそれを解読する方法を理解しなければならないでしょう。
これにアプローチするもう1つの方法は、longjmp
を介して単純に1ステップ実行することです。ブレークポイントをbreak longjmp
のように設定します。アセンブリを表示するにはdisassemble
を使用してください。実行をターゲットに転送する命令をステップ実行するまで、si
を実行します。
- 1. gdbコマンドラインで 'run to cursor'を実行する方法
- 2. gdbブレークポイントのコマンド内でmoreコマンドを実行して実行する方法
- 3. gdbを使用して#defineステートメントを実行する方法
- 4. gdbシングルオールスレッドモードでシングルスレッドを実行する
- 5. 子実行ファイルでgdbを実行しています
- 6. C++:linuxシェルスクリプトでgdbを実行
- 7. ブレークポイントが接続された後にndk-gdbを実行する方法
- 8. gdbでテストをデバッグする方法
- 9. setjmp longjmp with Stack
- 10. GDB:特定のブレークポイントまで実行
- 11. 例外が発生するまでGDBでアプリケーションを実行
- 12. gdbプリントでgrepする方法
- 13. gdb内で実行ループを中断する
- 14. 関数gdbを終了するまで単一のステップ実行
- 15. スクリプトの結果をGDBで実行するには?
- 16. GDBでプログラムを何度も再実行するには?
- 17. gdb/gdbserverでライブラリ呼び出しを実行する
- 18. gdbのブレークポイントの行を変更する方法は?
- 19. os ubuntuでgdbを実行すると、valiablesの値をテキストファイルにエクスポートする方法
- 20. チームシティでe2eテストを実行する方法、バックグラウンドでサーバーを実行してe2eを実行する方法
- 21. GDBで埋め込みプロセスを実行できますか?
- 22. GDB:バックトレースコマンドの形式:枠線、私はローカルでバックトレースコマンドでGDBを実行すると、別のシェル/ SSH
- 23. GDB TUIでソースファイルを開く方法
- 24. コードを実行中にXcodeデバッグ(GDB)がランダムにハングアップする
- 25. MacでSQLを実行する方法
- 26. CMDでPowerShellを実行する方法
- 27. バッチでストアドプロシージャを実行する方法
- 28. デフォルトパラメータでシェルスクリプトを実行する方法
- 29. Gitでマルチタスクを実行する方法
- 30. MVCでコンソールアプリケーションを実行する方法
あなたは 'break main'を実行してから' run'を実行し、 'step'をプログラムに入れておくことができます。それから、longjmp()の後の行を含むすべての行に入力を促します。 (それがあなたの質問に答えたなら私は答えに入れます) –
"next"の代わりにその行の "step"を押すとどうなりますか?あなたができることの1つは、 'setjmp()'からのゼロ以外の戻り値を扱うコードにブレークポイントを追加することです。 –
@MDXFは、 'next'コマンドの代わりに' step'コマンドを使うのがポイントですか? OPは彼が彼のために働かないと言います。私はあなたが特に 'main'で壊れていることを示唆しているのを見ていますが、' longjmp() 'の前に別の場所で壊れてしまうのはなぜなのでしょうか。 –