GDB hat eine neue Version herausgebracht, die Reverse Debug unterstützt (siehe http://www.gnu.org/software/gdb/news/reversible.html ). Ich habe mich gefragt, wie das funktioniert.
Damit das Reverse-Debug funktioniert, müssen Sie für jeden Schritt den gesamten Maschinenstatus einschließlich des Speichers speichern. Dies würde die Leistung unglaublich langsam machen, ganz zu schweigen von der Verwendung von viel Speicher. Wie werden diese Probleme gelöst?
reverse-debugging
Nathan Fellman
quelle
quelle
Antworten:
Ich bin ein GDB-Betreuer und einer der Autoren des neuen Reverse-Debugging. Ich würde gerne darüber sprechen, wie es funktioniert. Wie mehrere Personen spekuliert haben, müssen Sie genügend Maschinenzustand speichern, um ihn später wiederherstellen zu können. Es gibt eine Reihe von Schemata, von denen eines darin besteht, einfach die Register oder Speicherstellen zu speichern, die von jedem Maschinenbefehl geändert werden. Um diesen Befehl rückgängig zu machen, setzen Sie einfach die Daten in diesen Registern oder Speicherstellen zurück.
Ja, es ist teuer, aber moderne CPUs sind so schnell, dass Sie es nicht wirklich bemerken, wenn Sie ohnehin interaktiv sind (Stepping oder Breakpoints).
quelle
next
undstep
Eingeben von Befehlen oder das Rückgängigmachen einer beliebigen Anzahl von Anweisungen? Wenn ich beispielsweise einen Haltepunkt für eine Anweisung festlege und sie bis dahin laufen lasse, kann ich dann zur vorherigen Anweisung zurückkehren, obwohl ich sie übersprungen habe?Beachten Sie, dass Sie die Verwendung von Simulatoren, virtuellen Maschinen und Hardware-Rekordern zur Implementierung der umgekehrten Ausführung nicht vergessen dürfen.
Eine andere Lösung zur Implementierung besteht darin, die Ausführung auf physischer Hardware zu verfolgen, wie dies GreenHills und Lauterbach in ihren hardwarebasierten Debuggern tun. Basierend auf dieser festen Spur der Aktion jeder Anweisung können Sie dann zu einem beliebigen Punkt in der Spur wechseln, indem Sie die Auswirkungen jeder Anweisung nacheinander entfernen. Beachten Sie, dass dies voraussetzt, dass Sie alle Dinge verfolgen können, die sich auf den im Debugger sichtbaren Status auswirken.
Eine andere Möglichkeit ist die Verwendung einer Checkpoint + Neuausführungsmethode, die von VmWare Workstation 6.5 und Virtutech Simics 3.0 (und höher) verwendet wird und anscheinend mit Visual Studio 2010 geliefert wird. Hier verwenden Sie eine virtuelle Maschine oder einen Simulator um eine Indirektionsebene für die Ausführung eines Systems zu erhalten. Sie speichern regelmäßig den gesamten Status auf der Festplatte oder im Speicher und verlassen sich dann darauf, dass der Simulator genau denselben Programmpfad deterministisch erneut ausführen kann.
Vereinfacht funktioniert es so: Angenommen, Sie befinden sich zum Zeitpunkt T in der Ausführung eines Systems. Um zur Zeit T-1 zu gelangen, nehmen Sie einen Kontrollpunkt vom Punkt t <T auf und führen dann (Tt-1) Zyklen aus, um einen Zyklus vor Ihrer Position zu beenden. Dies kann sehr gut funktionieren und gilt auch für Workloads, die Festplatten-E / A ausführen, aus Code auf Kernelebene bestehen und Gerätetreiberarbeiten ausführen. Der Schlüssel ist ein Simulator, der das gesamte Zielsystem mit all seinen Prozessoren, Geräten, Speichern und E / A enthält. Weitere Informationen finden Sie in der GDB-Mailingliste und in der folgenden Diskussion auf der GDB-Mailingliste. Ich selbst benutze diesen Ansatz ziemlich regelmäßig, um kniffligen Code zu debuggen, insbesondere in Gerätetreibern und frühen Betriebssystemstarts.
Eine weitere Informationsquelle ist a Virtutech-Whitepaper zum Thema Checkpointing (das ich in vollständiger Offenlegung verfasst habe).
quelle
Während einer EclipseCon-Sitzung haben wir auch gefragt, wie dies mit dem Chronon Debugger für Java gemacht wird. Dass man nicht erlauben Sie tatsächlich einen Schritt zurück, kann aber eine aufgezeichnete Programmausführung so wiedergeben , dass es fühlt sich an wie Reverse Debugging. (Der Hauptunterschied besteht darin, dass Sie das laufende Programm im Chronon-Debugger nicht ändern können, während Sie dies in den meisten anderen Java-Debuggern tun können.)
Wenn ich es richtig verstanden habe, manipuliert es den Bytecode des laufenden Programms so, dass jede Änderung eines internen Status des Programms aufgezeichnet wird. Externe Zustände müssen nicht zusätzlich aufgezeichnet werden. Wenn sie Ihr Programm in irgendeiner Weise beeinflussen, müssen Sie eine interne Variable haben, die diesem externen Status entspricht (und daher ist diese interne Variable ausreichend).
Während der Wiedergabezeit können sie dann grundsätzlich jeden Status des laufenden Programms aus den aufgezeichneten Statusänderungen neu erstellen.
Interessanterweise sind die Zustandsänderungen viel kleiner als man auf den ersten Blick erwarten würde. Wenn Sie also eine bedingte "if" -Anweisung haben, würden Sie denken, dass Sie mindestens ein Bit benötigen, um aufzuzeichnen, ob das Programm die then- oder die else-Anweisung verwendet hat. In vielen Fällen können Sie sogar dies vermeiden, beispielsweise in dem Fall, dass diese verschiedenen Zweige einen Rückgabewert enthalten. Dann reicht es aus, nur den Rückgabewert aufzuzeichnen (der ohnehin benötigt würde) und die Entscheidung über den ausgeführten Zweig aus dem Rückgabewert selbst neu zu berechnen .
quelle
Obwohl diese Frage alt ist, sind die meisten Antworten auch und als Reverse-Debuggingbleibt ein interessantes Thema, ich poste eine Antwort für 2015. Kapitel 1 und 2 meiner MSc-Arbeit, Kombination von Reverse-Debugging und Live-Programmierung in Richtung visuelles Denken in der Computerprogrammierung , behandeln einige der historischen Ansätze für das Reverse-Debugging (insbesondere im Hinblick auf den Snapshot- (oder Checkpoint-) und Wiederholungsansatz) und erklärt den Unterschied zum allwissenden Debuggen:
quelle
Mozilla
rr
ist eine robustere Alternative zum Reverse-Debugging von GDBhttps://github.com/mozilla/rr
Die in GDB integrierte Aufzeichnung und Wiedergabe weist schwerwiegende Einschränkungen auf, z. B. keine Unterstützung für AVX-Anweisungen: Das Reverse-Debugging von GDB schlägt fehl mit "Prozessdatensatz unterstützt Anweisung 0xf0d an Adresse nicht".
Oberseite von rr:
rr erreicht dies, indem das Programm zunächst so ausgeführt wird, dass aufgezeichnet wird, was bei jedem einzelnen nicht deterministischen Ereignis passiert ist, z. B. bei einem Thread-Wechsel.
Während des zweiten Wiederholungslaufs wird diese überraschend kleine Trace-Datei verwendet, um genau zu rekonstruieren, was beim ursprünglichen nicht deterministischen Lauf passiert ist, jedoch auf deterministische Weise, entweder vorwärts oder rückwärts.
rr wurde ursprünglich von Mozilla entwickelt, um ihnen zu helfen, Timing-Fehler zu reproduzieren, die bei ihren nächtlichen Tests am nächsten Tag auftraten. Der Aspekt des umgekehrten Debuggens ist jedoch auch von grundlegender Bedeutung, wenn Sie einen Fehler haben, der nur Stunden innerhalb der Ausführung auftritt, da Sie häufig einen Schritt zurücktreten möchten, um zu untersuchen, welcher vorherige Status zu dem späteren Fehler geführt hat.
Das folgende Beispiel zeigt einige seiner Funktionen, vor allem die
reverse-next
,reverse-step
undreverse-continue
Befehle.Unter Ubuntu 18.04 installieren:
Testprogramm:
kompilieren und ausführen:
Jetzt befinden Sie sich in einer GDB-Sitzung und können das Debuggen ordnungsgemäß rückgängig machen:
Wenn Sie komplexe Software debuggen, werden Sie wahrscheinlich bis zu einem Absturzpunkt laufen und dann in einen tiefen Rahmen fallen. Vergessen Sie in diesem Fall nicht, dass Sie
reverse-next
bei höheren Frames zuerst Folgendes tun müssen:Bis zu diesem Rahmen
up
reicht es nicht aus , nur das Übliche zu tun .Die schwerwiegendsten Einschränkungen von rr sind meiner Meinung nach:
UndoDB ist eine kommerzielle Alternative zu rr: https://undo.io Beide basieren auf Trace / Replay, aber ich bin mir nicht sicher, wie sie sich in Bezug auf Funktionen und Leistung vergleichen lassen.
quelle
Nathan Fellman schrieb:
Sie können eine beliebige Anzahl von Anweisungen rückgängig machen. Sie sind beispielsweise nicht darauf beschränkt, nur an den Punkten anzuhalten, an denen Sie angehalten haben, als Sie vorwärts gingen. Sie können einen neuen Haltepunkt festlegen und rückwärts dorthin laufen.
Ja. Solange Sie den Aufnahmemodus aktiviert haben, bevor Sie zum Haltepunkt gelaufen sind.
quelle
So funktioniert ein anderer Reverse-Debugger namens ODB. Extrakt:
Ich vermute, dass die GDB auf die gleiche Art und Weise funktioniert.
quelle
Reverse Debugging bedeutet, dass Sie das Programm rückwärts ausführen können. Dies ist sehr nützlich, um die Ursache eines Problems zu ermitteln.
Sie müssen nicht für jeden Schritt den vollständigen Maschinenstatus speichern, sondern nur die Änderungen. Es ist wahrscheinlich immer noch ziemlich teuer.
quelle