Gdbで現在実行中の行の前の行に移動することは可能ですか?例えば:
void my_fun( somePtrType** arr,int start,int end)
{
// arr is an array of pointers to somePtrType
//line a
... some assignments
swap(&arr[ind1] , &arr[ind2] ) ;
//line b (current line )
}
現在、行bにあり、arr
値を調べることができますが、行aに戻り、その時点でarr
の内容を調べたいと思います。
デバッガーはスローモーションでコードを実行できますが、逆方向には実行できないため、それは不可能だと思います。
その他の洞察..
はい!新しいバージョン7.0 gdbでは、まさにそれを行うことができます!
コマンドは「reverse-step
」または「reverse-next
」になります。
Ftp.gnu.orgからgdb-7.0を入手できます:/ pub/gnu/gdb
エラーが発生した場合:Target child does not support this command.
その後、run
を開始した後、実行の最初にtarget record
を追加してみてください。
編集:GDB 7.6 target record
は推奨されないため、代わりにtarget record-full
を使用してください。
はい、今では実際のハードウェアで(VMだけでなく)可能であり、簡単です。 GDB-7.0は、ネイティブLinux x86マシン上で、reverse-stepやreverse-continueなどのコマンドを使用したリバースデバッグをサポートしています。
ここにチュートリアルがあります: http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial
mozilla rr
GDBの組み込みの記録と再生には厳しい制限があります。 AVX命令のサポートなし: gdbリバースデバッグは「プロセスレコードはアドレスで命令0xf0dをサポートしません」で失敗します
Rrの利点:
次の例では、その機能の一部、特にreverse-next
、reverse-step
およびreverse-continue
コマンド。
Ubuntu 16.04にインストールします。
Sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
Sudo cpupower frequency-set -g performance
しかし、ソースからコンパイルして最新の更新を取得することも検討してください。それは難しくありませんでした。
reverse.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int f() {
int i;
i = 0;
i = 1;
i = 2;
return i;
}
int main(void) {
int i;
i = 0;
i = 1;
i = 2;
/* Local call. */
f();
printf("i = %d\n", i);
/* Is randomness completely removed?
* Recently fixed: https://github.com/mozilla/rr/issues/2088 */
i = time(NULL);
printf("time(NULL) = %d\n", i);
return EXIT_SUCCESS;
}
コンパイルして実行:
gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
rr record ./reverse.out
rr replay
これでGDBセッション内に残り、デバッグを適切にリバースできます。
(rr) break main
Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
(rr) continue
Continuing.
Breakpoint 1, main () at a.c:16
16 i = 0;
(rr) next
17 i = 1;
(rr) print i
$1 = 0
(rr) next
18 i = 2;
(rr) print i
$2 = 1
(rr) reverse-next
17 i = 1;
(rr) print i
$3 = 0
(rr) next
18 i = 2;
(rr) print i
$4 = 1
(rr) next
21 f();
(rr) step
f () at a.c:7
7 i = 0;
(rr) reverse-step
main () at a.c:21
21 f();
(rr) next
23 printf("i = %d\n", i);
(rr) next
i = 2
27 i = time(NULL);
(rr) reverse-next
23 printf("i = %d\n", i);
(rr) next
i = 2
27 i = time(NULL);
(rr) next
28 printf("time(NULL) = %d\n", i);
(rr) print i
$5 = 1509245372
(rr) reverse-next
27 i = time(NULL);
(rr) next
28 printf("time(NULL) = %d\n", i);
(rr) print i
$6 = 1509245372
(rr) reverse-continue
Continuing.
Breakpoint 1, main () at a.c:16
16 i = 0;
短い答え:いいえ。
回避策については以下をお読みください。
行bでは、行aの値を決定することはできませんが、1つだけのブレークポイントにヒットすることにより、aおよびbおよびその他の場所でarrの値をログに記録することができます。
(gdb)コマンド1
ブレークポイント1にヒットしたときのコマンドを1行に1つずつ入力します。 「終了」とだけ言う行で終了します。
持続する
終わり
これで、他のすべてのロギングブレークポイントにヒットすると、arrの値が画面にダンプされますが、ブレークポイントはユーザーの操作を待たずに自動継続します。行bでブレークポイントに到達すると、gdb自体に記録されるarrの過去の値を確認できます。
状況に応じて、多くの有用な情報をダンプ(および表示)することもできます。たとえば、上記の関数がループ内で10000回呼び出された場合、ループカウンター(iなど)をダンプすることもできます。それはあなたが何を達成しようとしているかに本当に依存します。
http://sourceware.org/gdb/current/onlinedocs/gdb.html#SEC51 に従い、「ターゲット環境でサポートされている場合」はい。
プログラムが短い場合、通常のトリックは、
r
デバッグを再開する[〜#〜] gdb [〜#〜]はそのために作られました!
Arrのセットアップコードが "line a"のすぐ上にある場合(非常に一般的なシナリオ)、次のようにできます。
tbreak myfilename.c:123
(123行目はarrのセットアップコードの開始です)
jump 123
「tbreak」は、ジャンプ後にgdbがプログラムを続行(再開)するのを防ぎます。
次に、セットアップコードをステップ実行するか、「line a」にブレークポイントを設定して続行します。