Dies ist ein reduziertes Beispiel für die Struktur meines Codes:
%Vor%Und hier ist das entsprechende GDB-Skript:
%Vor% Das Problem ist, dass der Befehl finish
verhindert, dass die nachfolgenden Befehle (nämlich print i
und continue
) nicht aufgerufen werden.
Gibt es eine Möglichkeit, GDB anzuweisen, i
direkt nach einem increment
Aufruf zu drucken?
Sie können diesen Fehler offensichtlich umgehen, indem Sie alle Befehle in einen einzigen Python-Aufruf einschließen, z. B.
%Vor%bearbeiten: Eine zweite Arbeit, die nicht erfordert Python scheint einen neuen Befehl gdb zu definieren und das in Befehlen ausführen:
%Vor%Das Problem ist, dass das Beenden die Befehle, die für den ersten Haltepunkt hinter ihm gesetzt sind, nicht mehr abbricht.
Dies ist ein erwartetes Verhalten: Jeder Befehl, der den inferioren Prozess (debugged) wieder aufnimmt (wie finish
), stoppt auch die Ausführung der vordefinierten Befehlssequenz.
Aktualisierung:
Siehe auch diesen GDB-Fehlerbericht .
Gibt es eine Möglichkeit, GDB mitzuteilen, dass ich direkt nach jedem Inkrement-Aufruf drucken soll?
Ja:
increment
routine mit disas
Befehl. Finde den Befehl ret
am Ende (es wird nur einen geben). break *0xNNNNN
syntax verwenden. Fügen Sie einen Befehl an diesen Haltepunkt an:
%Vor% Voila: Sie sollten Werte erhalten, die von increment()
gedruckt werden (kurz bevor sie zurückgegeben werden).
Alternativ zu @Matt antwort, und wenn Sie GDB 7.4 verwenden, können Sie FinishBreakpoints verwenden, mit etwas wie (ungeprüft - ich bin mir nicht sicher, ob Kommentare hier akzeptiert werden):
%Vor%(und einen Link zur Dokumentation )
GDB-Haltepunkt-Befehlslisten sind insofern eingeschränkt, als sie jeden Befehl nach dem ersten Schritt- / Fortsetzen-Befehl ignorieren (Stand: März 2017, GDB 7.12). Dies ist dokumentiert im GDB-Handbuch , wo dies mit der aktuellen Implementierung nicht motiviert war fähig, zwei Befehlslisten gleichzeitig auszuführen (vgl. GDB # 10852 - Befehlsfolgen wurden unerwartet unterbrochen ) .
Diese Einschränkung wird nur mit einem stepping / continue-Befehl erzwungen, der direkt in einer Befehlsliste vorhanden ist. Somit kann man dies umgehen - aber die Beschränkung gilt immer noch und z. Das GDB-Handbuch warnt im Python-API-Abschnitt : "Sie sollte den Ausführungszustand des Untergeordneten nicht ändern (dh Schritt, nächstes usw.).
Wenn es notwendig ist, GDB-Befehle beim Funktionseingang und auszuführen, ist die zuverlässige Lösung, mehrere Haltepunkte zu verwenden und die Befehlslisten aufzuteilen. Das bedeutet, dass für jede Rücksprunganweisung der zu untersuchenden Funktion zusätzliche Haltepunkte gesetzt werden müssen.
Dies kann ähnlich wie folgt gemacht werden:
%Vor% Welches Register den Rückgabewert enthält, hängt von den Aufrufkonventionen ab und ist architekturabhängig. Auf x86-64 ist es in $rax
. Andere Optionen sind $eax
auf x86-32, $o0
auf SPARC, $r0
auf ARM etc.
Die Erstellung der zusätzlichen Haltepunkte kann in GDB mit Hilfe der Skriptunterstützung automatisiert werden.
Aktuelle GDB-Versionen enthalten eine Python-API , die für diese Automatisierung gut geeignet ist. GDB-Pakete, die von Distributionen bereitgestellt werden, aktivieren standardmäßig die Python-Unterstützung.
Als erstes Beispiel setzen Sie automatisch Haltepunkte für jede ret-Anweisung einer gegebenen Funktion:
%Vor%(nimmt an, dass GDB mit Python3-Unterstützung kompiliert wurde, zum Beispiel der Fedora 25)
Um die Erstellung von Breakpoints zu automatisieren, die den Rückgabewert (dh den Wert von register $rax
) ausgeben, und fahren Sie dann mit dem gdb.Breakpoint
class muss unterklassifiziert werden:
Dann kann ein Breakpoint wie folgt erstellt werden:
%Vor%Kombinieren Sie beide Schritte zum Erstellen eines neuen benutzerdefinierten Befehls:
%Vor%Beispiel für die Verwendung dieses neuen Befehls:
%Vor%Falls Sie Python nicht mögen und / oder eine GDB haben, die Python-Unterstützung deaktiviert hat - aber Guile-Unterstützung aktiviert - man kann die Breakpoints auch automatisch über Guile setzen.
Die benutzerdefinierte Befehlsdefinition in Guile:
%Vor%