Wie führe ich finish und dann einen anderen Befehl aus den internen Befehlen aus?

9

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?

    
Randomblue 08.05.2012, 14:56
quelle

5 Antworten

7

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%     
matt 10.05.2012, 07:11
quelle
4
  

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:

  1. Diasemble increment routine mit disas Befehl. Finde den Befehl ret am Ende (es wird nur einen geben).
  2. Legen Sie einen Haltepunkt für diese Anweisung fest, indem Sie break *0xNNNNN syntax verwenden.
  3. 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).

    
Employed Russian 08.05.2012 14:58
quelle
3

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 )

    
Kevin 11.05.2012 07:34
quelle
1

Haben Sie tatsächlich versucht, das zu kompilieren? Ihre Funktion increment() wird als void deklariert, muss jedoch int sein. Nachdem ich das geändert hatte, funktionierte es gut für mich:

%Vor%     
Kevin 08.05.2012 15:50
quelle
0

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.

Python

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:

%Vor%

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%

Guile

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%     
maxschlepzig 05.03.2017 10:10
quelle

Tags und Links