問題タブ [reverse-debugging]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
debugging - コアダンプファイルで「リバースデバッグ」を使用できますか?
GDB 7.0以降、逆デバッグがサポートされています。
コアダンプが生成されたときに、リバースデバッグコマンドを使用できますか?
どうやってやるの?
gdb - VirtualBox VM の gdb レコードから実行ログを抽出する
gdb のレコード機能を使用して、チュートリアルの例で実行された命令のリストを生成しようとしています
gdb レコードを使用して、正常に前後に移動し、「レコード保存」を使用して実行ログをファイルに保存できます。
私がやりたいのは、ドキュメントから「指示履歴を記録する」ことだと思います
記録された実行ログから命令を逆アセンブルします
しかし、これを試みると、エラーが発生します:
ターゲットが「レコードがいっぱい」の場合、それはできません
レコード ターゲットを btrace に設定しようとすると、次のエラーが返されます。
ターゲットは分岐トレースをサポートしていません。
VirtualBox VM で gdb 7.6 を実行しています。ネイティブで実行する必要がありますか、それとも他に不足している魔法がありますか。
lldb - lldb を使用したリバース デバッグ
このチュートリアルを読みましたが、リバース デバッグについては何も見つかりませんでした。lldb にはtarget record
gdb のような機能がありますか? はいの場合、どこでそれについて読むことができますか?
gdb - GDBで命令履歴と関数呼び出し履歴を記録する方法は?
(編集:現在の「トリック」の下の最初の回答によると、Atomプロセッサを使用しているようです。しかし、これが根本的な制限であるか、または他のプロセッサのサポートを追加することがロードマップにあるかどうかについて、gdbの第一人者が答えてくれることを願っています。)
私の環境では逆実行が機能しているようです。
ただし、命令と関数の履歴は利用できません。
利用可能な唯一のターゲット タイプは full であり、他の文書化されたタイプ「btrace」は「ターゲットはブランチ トレースをサポートしていません」で失敗します。
したがって、このターゲットではサポートされていない可能性が非常に高いですが、これは主流の最新のターゲット (gdb 7.6.1-ubuntu、amd64 Linux Mint「Petra」で「Intel(R) Core(TM) i5-3570」を実行) であるためです。 ) 重要なステップまたは構成を見落としていたらいいのにと思いますか?
c++ - 非 GUI メソッドの QtCreator でリバース デバッグを有効にする
Windows(MingW、gcc、g ++、make、gdbを使用)とUbuntuにQtCreatorを2つインストールしています。2 OS では、いくつかの Qt プログラム (Qt Windows を使用) またはコンソール プログラムを実行し、プログラムをデバッグできます。
しかし、リバースデバッグを試みましたが成功しませんでした。デバッガーのオプションで「逆デバッグを許可する」オプションをチェックし、デバッグビューに「逆方向」と呼ばれるボタンがありますが、クリックしても何も起こらず、他のボタンを変更したり、これらのボタンの効果を変換したりしません(前方から後方へ)。
c - GDB リバース デバッグを使用して関数呼び出しによる値の伝播を追跡するにはどうすればよいですか?
GDBリバースデバッグを使用して、プログラム内の関数呼び出しと変数コピーによる値の伝播を追跡する方法を見つけようとしています。私は過去に GDB をよく使用していましたが、リバース デバッグは比較的初めてです。
例を挙げて質問を組み立てるのが最も簡単だと思います。このプログラムを見てください。
プログラムをコンパイルし、リバース デバッグを使用して GDB を起動し、コンパイル済みの実行可能ファイルを実行します。printf
inにブレークポイントを設定しFnA
、プログラムの実行を開始すると、そのブレークポイントに到達します。x
ここからは、「最後に書かれたのはどこですか?」という質問に答えたいと思います。私はすることができたしwatch -l x
、その後reverse-continue
。ただし、スタック上での有効期間が始まったFnA
場所であるため、それはの最初に移動するだけです。x
私が本当に興味を持っているのは、の値がどこから来たかということですi = 5
。その時から、本当にmain
x
i = 5
x
次のように、関数パラメーターと変数のコピーを介して伝播されましたmain:i -> FnC:z -> FnB:y -> FnB:y_copy -> FnA:x
。
明らかに、GDB-fu と人間の直感を組み合わせることでこれを理解できますが、このプロセスを可能な限り自動化しようとしています。最終的には、人間の直感と GDB-fu を使用するのはかなり面倒な、より複雑なソフトウェアでこれを試してみたいと思います。
リバースデバッグを使用して GDB でこれを達成する便利な方法はありますか? GDB は、これらの値の伝播を自動的に把握して追跡することができますか?
PS: 具体的には、実際にrrで GDB を使用しています。rr は、確定的で再現可能な実行コンテキストを可能にする gdb の単なるラッパーです。rr の有無にかかわらず、gdb を使用しているかどうかに関係なく、コアの質問は同じままであると思います/願っています。
c - GOT に加えられた変更は、リバース デバッグ中に元に戻されることが予想されますか?
プログラムのアドレス空間に加えられた変更は、リバース デバッグ中に元に戻されないと予想されますか?
strlen
実行中に GOT 内のポインタが壊れるとセグメンテーション違反になるプログラムをデバッグしています。この質問へのコメントからのアドバイスのおかげで、-z relro
オプションとリンクすることで、このプログラムの GOT を読み取り専用にしました。ただし、問題のポインタが上書きされるのを防ぐことはできません。つまり、start
gdb のプログラムで、最初に出現する にステップしstrlen
、ポインターが有効であることを確認し (例: x/g 0x5555555d10a8 ==> 0x5555555d10a8 <strlen@got.plt>: 0x00007ffff7e8d1e0
)、continue
実行し、ポインターが無効になるのを待ちます (プログラム; 例: x/g 0x5555555d10a8 ==>
0x5555555d10a8 <strlen@got.plt>: 0x0000000000002156
)、プロンプトを表示するsegv
.
ただし、record full
実行全体 (最初の行からプログラムの segfault まで) と、その後awatch
へのポインターを含むアドレスstrlen
duringreverse-continue
の場合、ウォッチポイントはトリガーされません。そして、プログラムが最終的に命令 #0 に戻ったとき、ポインターは、セグメンテーション違反が発生したときに持っていた無効なアドレスを指しているままです。
これは 2 つの疑問につながります。-z relro
まず、リンカー オプションがあるにもかかわらず GOT が変更可能なのはなぜですか? 第 2 に、プログラムの実行中に変更されたメモリ内の場所 (へのポインタstrlen
) は、逆の実行中に元の値に復元されないことが予想されますか?
r - R: 線形コード チェーンの強化されたデバッグ
R のメタプログラミング機能を使用して、適切な量のプログラミングを行うことで、特定のデバッグ機能を作成できるかどうかを調べようとしています。
各行がその入力の全部または一部として前の行からの出力を使用するコード ブロックがあるとします。これは、パイプを使用して構築するコードのようなものです (ただし、ここではパイプは使用されません)。
たとえば、次のような場合です。
f1 <- function(first_arg, second_arg, ...){my_body_code}
、
f1
ブロックを次のように呼び出します。
のfoo_foo
呼び出し環境で定義されたオブジェクトですf1
。
コードの各行に対して、リストにエントリを作成するブロックをラップできる関数が必要です。各エントリには ( line1, line2
) という名前が付けられ、各行エントリには各引数と関数出力のサブエントリがあります。引数エントリは、最初に、実際の引数が一致する形式の名前で構成され、2 番目に、その引数に指定された式または名前 (引数が単なる定数の場合はプレースホルダー) で構成されます。そして 3 番目に、その式の値は、関数への入力時にすぐに強制されたかのようになります。(プロミスが最初に守られた時点での値を取得したいのですが、それははるかに難しい問題のように思えます。2 つの値はほとんどの場合同じです)。
(存在する場合)に割り当てられたすべての引数...
は、dots = list() サブリストに入れられ、エントリに名前がある場合は名前..1, ..2,
が付けられ、位置的に割り当てられている場合は適切にラベル付けされます (など)。各行のサブリストの最後の要素は、出力の名前とその値になります。
これのポイントは、コード ブロックの操作のかなり完全な記録を作成することです。これは、反復に限定されず、各ステップのより詳細な記録を保持する精巧なバージョンに類似していると思います。purrr::safely
実際、関数がエラーで終了した場合、リストエントリと同様にエラーメッセージが必要になります.エラーが生成される前に持っていた可能性のある一致した引数の多く。
これは、このような線形コードのデバッグに非常に役立つように思えます。これにより、RStudio デバッガーだけでは難しいことが可能になります。たとえば、コードを逆方向にトレースできます。out2 の値が正しくないことは、後で出力を確認するまでわからない場合があります。シングルステップでは、大量の追加コードを挿入しない限り、中間値は保持されません。さらに、これにより、Promise が作成される前に発生する一致エラーを追跡するために必要な情報が保持されます。このようなエラーの結果としてシングル ステップで出力が表示されるまでには、一致する情報は蒸発している可能性があります。
私は実際に、パイプされた関数を受け取り、パイプを削除してこの形式にするコードを、テキスト操作だけで作成しました。(確かに、これを考えさせられたのはジョン・マウントの「ビザロ・パイプ」でした)。そして、私、または私たち、またはあなたがこれを行う方法を理解できれば、各関数が次の関数を呼び出し、外部ではなく内部で引数を提供する2番目のバージョンで真剣に実行したいと考えています-トレースバックのようにここで、渡された引数の値と、関数名およびフォーマルを取得します。他の言語にはそのようなデバッグ環境 (GDB など) があり、R 用のデバッグ環境を少なくとも 5 年、おそらく 10 年は望んでいましたが、これはそれに向けた一歩のようです。