it-swarm.com.de

Wie gehe ich zur vorherigen Zeile in GDB?

Ist es in gdb möglich, zu einer Zeile vor der aktuell ausgeführten Zeile zu wechseln.


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 )
}

Ich bin derzeit in Zeile b und kann die arr-Werte dort überprüfen, aber ich möchte zurück zu Zeile a und den Inhalt von arr prüfen.

Ich denke, es ist möglicherweise nicht möglich, weil ein Debugger Code in Zeitlupe ausführen kann, aber nicht rückwärts ausführen kann.
.__ Weitere Einblicke ..

58
sud03r

Ja! Mit der neuen Version 7.0 von gdb können Sie genau das tun!

Der Befehl wäre "reverse-step" oder "reverse-next".

Sie können gdb-7.0 von ftp.gnu.org:/pub/gnu/gdb erhalten

Wenn Sie auf den Fehler stoßen: Target child does not support this command., versuchen Sie, target record zu Beginn der Ausführung hinzuzufügen, nachdem Sie run gestartet haben.

Bearbeiten: Da GDB 7.6 target record veraltet ist, verwenden Sie stattdessen target record-full.

94
Michael Snyder

Ja, es ist jetzt möglich und unkompliziert mit echter Hardware (dh nicht nur mit einer VM) . GDB-7.0 unterstützt das umgekehrte Debugging mit Befehlen wie reverse-step und reverse-continue auf nativen Linux-x86-Computern.

Es gibt hier ein Tutorial: http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial

12
Michael Snyder

Kurze Antwort : Nein. 

Für Workaround lesen Sie unten.

In Zeile b ist es nicht möglich, den Wert in Zeile a zu bestimmen. Es ist jedoch möglich, den Wert von arr an a und b und an anderen Orten zu protokollieren, indem nur ein Haltepunkt getroffen wird.

  • Verwenden Sie den Befehl "display" (display Variablenname, wobei Variablenname durch Arr, * Arr, ** Arr, je nachdem, wonach Sie suchen) ersetzt werden soll, damit bei einem beliebigen Haltepunkt der Inhalt des Variablennamens angezeigt wird auf dem Bildschirm ausgegeben werden. Beachten Sie, dass Sie der Anzeigeliste hinzufügen können, wenn sich variabe_name im Gültigkeitsbereich befindet, sodass Sie möglicherweise auf den ersten Haltepunkt warten müssen. 
  • Erstellen Sie Haltepunkte an verschiedenen Stellen des Codes, an denen Sie den Wert von Variablenname protokollieren möchten. Ein solcher Haltepunkt wäre in Zeile a.
  • Verwenden Sie für jeden Haltepunkt den Befehl (Befehl Haltepunktnummer) und weisen Sie den Haltepunkt an, die Ausführung des Programms nicht anzuhalten. Der Befehl, den Sie verwenden müssen, ist continue, gefolgt von end. Siehe Beispiel unten.

(gdb) Befehl 1 

Geben Sie Befehle für den Haltepunkt 1 ein, einen pro Zeile. Beenden Sie mit einer Zeile, die nur "Ende" sagt.

fortsetzen

ende

  • Setzen Sie einen Haltepunkt in Zeile b.

Wenn nun alle anderen Haltepunkte für die Protokollierung erreicht werden, wird der Wert von arr auf dem Bildschirm ausgegeben, der Haltepunkt wartet jedoch nicht auf die Benutzerinteraktion und wird automatisch fortgesetzt. Wenn Sie einen Haltepunkt in Zeile b treffen, können Sie die früheren Werte von arr sehen, die in gdb selbst protokolliert würden. 

Je nach Situation können Sie auch viele nützliche Informationen ausgeben (und anzeigen). Beispielsweise möchten Sie möglicherweise auch einen Schleifenzähler ausgeben (z. B. i), wenn die obige Funktion in einer Schleife 10000-mal aufgerufen wird. Das hängt wirklich davon ab, was Sie erreichen wollen.

4
mohit

mozilla rr

https://github.com/mozilla/rr

Die eingebaute Aufzeichnung und Wiedergabe von GDB unterliegt strengen Einschränkungen, z. Keine Unterstützung für AVX-Anweisungen: gdb reverse debugging schlägt fehl mit "Prozessdatensatz unterstützt keine Anweisung 0xf0d an Adresse"

Vorteile von rr:

  • viel zuverlässiger im Moment
  • bietet auch eine GDB-Schnittstelle mit dem Protokoll gdbserver, was es zu einem hervorragenden Ersatz macht
  • kleiner Leistungsabfall bei vielen Programmen

Das folgende Beispiel zeigt einige seiner Funktionen, insbesondere die Befehle reverse-next, reverse-step und reverse-continue.

Installieren Sie Ubuntu 16.04:

Sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
Sudo cpupower frequency-set -g performance

Aber auch das Kompilieren aus dem Quellcode, um die neuesten Updates zu erhalten, war nicht schwer.

Testprogramm:

#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;
}

kompilieren und ausführen:

gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
rr record ./reverse.out
rr replay

Jetzt bleiben Sie in einer GDB-Sitzung und können das Debuggen ordnungsgemäß rückgängig machen:

(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;

laut http://sourceware.org/gdb/current/onlinedocs/gdb.html#SEC51 und "wenn die Zielumgebung dies unterstützt", ja.

2
ax.

Wenn Ihr Programm kurz ist, lautet der übliche Trick:

  1. Platzieren Sie einen neuen Haltepunkt in der vorherigen Zeile
    • firerum den Debug neu zu starten

GDBwurde dazu gemacht!

2
nik

Nicht gdb, aber Sie können mit einem Debugger namens qira problemlos in die Geschichte zurückkehren. Sie können die Aufwärts- und Abwärtspfeile verwenden, um hin und her zu gehen. Außerdem wird hervorgehoben, welche Register sich geändert haben. 

 enter image description here

1
briankip

Wenn sich Ihr Setup-Code für arr genau über "Zeile a" befindet (ein sehr häufiges Szenario), können Sie dies wie folgt tun:

tbreak myfilename.c:123 (Zeile 123 ist der Start des Setup-Codes für arr), dann

jump 123

Der "tbreak" verhindert, dass gdb das Programm nach dem Sprung fortsetzt (fortsetzt).

dann können Sie den Setup-Code schrittweise durchgehen oder einfach einen Haltepunkt in "Zeile a" setzen und fortfahren

0
slonik

Jeder wünscht sich einen allwissenden Debugger wie diesen: http://www.lambdacs.com/debugger/ , aber er ist (je nach Sprache/Maschine) schwierig zu erstellen und hat viel Buchhaltung.

Im Moment ist es auf echter Hardware und nicht in einer VM nahezu unmöglich, dies zu tun. 

0
Tobias Langner