web-dev-qa-db-ja.com

GDBの前の行に移動する方法は?

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の内容を調べたいと思います。

デバッガーはスローモーションでコードを実行できますが、逆方向には実行できないため、それは不可能だと思います。
その他の洞察..

61
sud03r

はい!新しいバージョン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を使用してください。

97
Michael Snyder

はい、今では実際のハードウェアで(VMだけでなく)可能であり、簡単です。 GDB-7.0は、ネイティブLinux x86マシン上で、reverse-stepやreverse-continueなどのコマンドを使用したリバースデバッグをサポートしています。

ここにチュートリアルがあります: http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial

12
Michael Snyder

mozilla rr

https://github.com/mozilla/rr

GDBの組み込みの記録と再生には厳しい制限があります。 AVX命令のサポートなし: gdbリバースデバッグは「プロセスレコードはアドレスで命令0xf0dをサポートしません」で失敗します

Rrの利点:

  • 現在、はるかに信頼できる
  • また、gdbserverプロトコルを備えたGDBインターフェースを提供しており、優れた代替品となっています。
  • 多くのプログラムのパフォーマンスの小さな低下

次の例では、その機能の一部、特にreverse-nextreverse-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の値をログに記録することができます。

  • 「display」コマンドを使用します(display variable_nameここで、variable_nameはarr、* arr、** arrに置き換えられます)ブレークポイントにヒットすると、variable_nameの内容が画面にダンプされます。 variabe_nameがスコープ内にあるときに表示リストに追加できるため、最初のブレークポイントを待つ必要がある場合があることに注意してください。
  • Variable_nameの値を記録したいコードのさまざまな場所にブレークポイントを作成します。そのようなブレークポイントの1つは、行aです。
  • 各ブレークポイントに対して、コマンド(command breakpoint_number)を使用し、プログラムの実行を停止しないようにブレークポイントに指示します。使用する必要があるコマンドは、continueに続いてendです。以下の例を参照してください。

(gdb)コマンド1

ブレークポイント1にヒットしたときのコマンドを1行に1つずつ入力します。 「終了」とだけ言う行で終了します。

持続する

終わり

  • 行bにブレークポイントを置きます。

これで、他のすべてのロギングブレークポイントにヒットすると、arrの値が画面にダンプされますが、ブレークポイントはユーザーの操作を待たずに自動継続します。行bでブレークポイントに到達すると、gdb自体に記録されるarrの過去の値を確認できます。

状況に応じて、多くの有用な情報をダンプ(および表示)することもできます。たとえば、上記の関数がループ内で10000回呼び出された場合、ループカウンター(iなど)をダンプすることもできます。それはあなたが何を達成しようとしているかに本当に依存します。

5
mohit

http://sourceware.org/gdb/current/onlinedocs/gdb.html#SEC51 に従い、「ターゲット環境でサポートされている場合」はい。

2
ax.

プログラムが短い場合、通常のトリックは、

  1. 前の行に新しいブレークポイントを配置します
    • fire rデバッグを再開する

[〜#〜] gdb [〜#〜]はそのために作られました!

2
nik

Gdbではありませんが、qiraというデバッガーを使用して簡単に履歴に戻ることができます。上矢印と下矢印を使用して前後に移動できます。また、どのレジスタが変更されたかを強調表示します。

enter image description here

1
briankip

Arrのセットアップコードが "line a"のすぐ上にある場合(非常に一般的なシナリオ)、次のようにできます。

tbreak myfilename.c:123(123行目はarrのセットアップコードの開始です)

jump 123

「tbreak」は、ジャンプ後にgdbがプログラムを続行(再開)するのを防ぎます。

次に、セットアップコードをステップ実行するか、「line a」にブレークポイントを設定して続行します。

0
slonik