Verbessern Sie die Codequalität und verhindern Sie unerwartete Ergebnisse, indem Sie lernen, wie Sie mit GNU Debugger unerwünschte Fehler in Ihrem Code aufdecken.
Debugging ist eine unverzichtbare Fähigkeit für Programmierer und Sicherheitsforscher. Wenn Sie über gute Debugging-Kenntnisse verfügen, können Sie eine ausführbare Datei auf einer niedrigeren Ebene verstehen und eventuelle Fehler erkennen.
Der GNU-Debugger oder GDB ist ein zeitloses Debugging-Tool, auf das sich Programmierer seit Jahren verlassen. Hier erfahren Sie, wie Sie GDB unter Linux verwenden.
Beispielprogramme vorbereiten
Um die Funktionen von GDB zu erkunden, benötigen Sie eine ausführbare Datei zum Experimentieren. Zur Demonstration führen Sie GDB einmal mit verfügbarem Quellcode und Debug-Symbolen in einem Schlüsselprüfprogramm aus, einmal ohne Quellcode und auf einem einfachen Multithread-Programm, das Nachrichten auf dem Bildschirm ausgibt, sowohl in C geschrieben als auch mit GCC (GNU C) kompiliert Compiler).
Du kannst
Verwenden Sie einen anderen C-Compiler aber achten Sie darauf, die Binärdatei nicht zu entfernen.Sie werden GDB höchstwahrscheinlich in Ihren eigenen Programmen ausführen. Stellen Sie also sicher, dass Sie sie mit dem kompilieren -G Flag mit gcc, um Debug-Symbole zu aktivieren.
Ohne vorhandene Debug-Symbole und mit einer stark reduzierten Binärdatei müssen Sie die Disassemblierung des Programms debuggen. Dies erfordert gute Kenntnisse der Assemblersprache und wie die Speicherzuweisung unter Linux funktioniert um die Daten im Stapel und in den Registern zu verstehen.
Ausführen eines Programms in GDB
Sie können ein Programm in GDB auf verschiedene Arten ausführen. Entweder eintippen gdb , und sobald es geladen ist, geben Sie Folgendes ein laufen. Oder starten Sie gdb und verwenden Sie dann die Datei Befehl, laden Sie die Binärdatei in gdb und führen Sie sie dann mit aus laufen Befehl.
Wenn Ihr Programm Befehlszeilenargumente benötigt, um ordnungsgemäß zu funktionieren, stellen Sie sicher, dass Sie die Argumente nach dem Programmnamen hinzufügen. Hier ist die Syntax zum Laden des Programms auf GDB und zum Ausführen mit Argumenten:
gdb
run
Oder:
gdb
file
run
Haltepunkte mit GDB setzen
Haltepunkte beim Debuggen sind manuell festgelegte harte Stopps im Code, die den Ausführungsfluss stoppen, wenn das Programm einen Haltepunkt erreicht. Durch das Festlegen von Haltepunkten können Sie den Code schrittweise durchlaufen und prüfen, wie sich jede Ausführungsphase auf Daten und Variablen auswirkt.
Wenn Sie in GDB ein Programm mit Debug-Symbolen debuggen, können Sie entweder einen Haltepunkt anhand des Namens der Funktion oder anhand der Zeilennummer festlegen. Hier ist die Syntax:
break main
break 47
Geben Sie Folgendes ein, um alle Haltepunkte in der aktuellen Debugging-Sitzung anzuzeigen:
info breakpoints
Geben Sie Folgendes ein, um einen bestimmten Haltepunkt oder mehrere Haltepunkte zu löschen:
delete 2
delete 3-5
Mit GDB können Sie auch bedingte Haltepunkte festlegen, was bedeutet, dass das Programm nur dann angehalten wird, wenn während der Ausführung eine bestimmte Bedingung erfüllt ist. Es kann sich um eine Änderung des Werts einer Variablen, einen fehlgeschlagenen Funktionsaufruf oder um alles Mögliche handeln. Hier ist die Syntax zum Festlegen bedingter Haltepunkte:
break if n == 2
Wenn Sie die Ausführung des Programms nach Erreichen eines Haltepunkts fortsetzen möchten, geben Sie Folgendes ein weitermachen Befehl:
continue
Durch den Code gehen
Das schrittweise Durchgehen des Codes ist entscheidend, um zu verstehen, wie das Programm mit den Daten umgeht. Indem Sie verschiedene Funktionen in Ihrem Programm schrittweise durchgehen und den Zustand der Daten untersuchen, können Sie besser verstehen, wie das Programm die von Ihnen im Code geschriebene Logik implementiert.
Es hilft Ihnen auch, die Ursache von Abstürzen zu erkennen und das Programmverhalten mit chirurgischer Präzision zu untersuchen, da Sie jede Codezeile nach Ihren Wünschen durchgehen können. Sie können den Code in GDB hauptsächlich auf drei Arten durchgehen:
- Schritt: Dieser Befehl weist GDB an, in die nächste Zeile der Quelldatei zu wechseln. Auf diese Weise können Sie im Wesentlichen die Länge des Quellcodes Zeile für Zeile durchlaufen.
- nächste: Dieser Befehl führt die nächste Zeile Quellcode innerhalb der aktuellen Funktion aus und stoppt dann. nächste behandelt eine Funktion als einzelne Zeile. Wenn Sie also „next“ vor einem Funktionsaufruf verwenden, wird sie im Gegensatz zu „next“ als einzelne Zeile behandelt und überschritten Schritt Befehl.
- beenden: Der Befehl „finish“ führt alle verbleibenden Zeilen innerhalb der aktuellen Funktion aus und stoppt dann.
Untersuchen von Variablen
Während Sie den Code durchgehen, möchten Sie den Wert von Variablen untersuchen, um zu sehen, wie die Programmlogik sie verändert. Hier ist die Syntax zum Anzeigen des Werts von Variablen in GDB:
print
Wenn Sie die Änderungen im Wert einer Variablen bei jeder Aktualisierung ausdrucken möchten, sollten Sie den Befehl display verwenden. Dies ist besonders nützlich, wenn Sie den Wert einer Variablen in einer Schleife verfolgen und ausgeben möchten:
display
Watchpoints setzen
Watchpoints und bedingte Haltepunkte sind eng miteinander verbunden, da sie beide auf Änderungen in einem Programm reagieren. Watchpoints werden verwendet, um Änderungen an Daten im Code zu verfolgen. Sie möchten beispielsweise, dass das Programm immer dann abbricht, wenn sich der Wert einer Variablen ändert. So geht das mit GDB:
watch
Thread-spezifisches Debuggen mit GDB
Mit GDB können Sie Thread-spezifisches Debugging durchführen, wenn Sie mit Multithread-Programmen arbeiten. Zur Demonstration arbeiten wir mit einem einfachen C-Programm, das vier Threads verwendet, um Nachrichten mit jedem Thread zu drucken.
Um die aktuell erzeugten Threads in Ihrem Programm anzuzeigen, verwenden Sie die die Info Befehl:
info threads
Um mit einem bestimmten Thread zu arbeiten, können Sie ihn anhand seiner Indexnummer aus der Liste auswählen. Zum Beispiel:
thread 2
Nachdem Sie den Thread ausgewählt haben, können Sie dessen Ausführungsablauf mithilfe von durchlaufen Schritt, nächste, Und beenden Befehle wie oben gezeigt.
Remote-Debugging mit GDB
Sie können Programme, die sich auf einem anderen System befinden, auch remote debuggen. Dazu müssen Sie gdbserver auf dem Zielcomputer einrichten. Sie können es einfach mit dem Standardpaketmanager Ihrer Distribution oder installieren andere Paketmanager, die Sie installiert haben auf Ihrem System.
Um beispielsweise gdbserver auf Ihren Ubuntu- oder Debian-basierten Systemen zu installieren, verwenden Sie APT:
sudo apt install gdbserver
Wechseln Sie nach der Installation in den Ordner der Binärdatei und führen Sie diesen Befehl aus, um gdbserver zu starten:
gdbserver :
gdbserver sollte die Ausgabe zurückgeben, dass es aktiv ist und den von Ihnen definierten Port überwacht. Starten Sie nun auf dem Client-Computer GDB und stellen Sie dann mithilfe von eine Verbindung zum Remote-Server her Ziel Befehl:
target remote :
Schreiben von GDB-Skripten zur Automatisierung des Debuggens
Mit GDB können Programmierer GDB-Skripte schreiben, die GDB-Befehle automatisch ausführen. Dies ist enorm hilfreich, wenn Sie versuchen, denselben Teil eines Codes mehrmals zu debuggen. Anstatt jedes Mal, wenn Sie die Binärdatei laden, den Haltepunkt festzulegen, den Code schrittweise durchzugehen und Variablenwerte auszugeben, können Sie den gesamten Prozess mit einem GDB-Skript automatisieren.
Hier ist ein Beispiel:
set logging enabled on
set logging file sample.out
break main
command 1
backtrace
print N
continue
end
quit
Im obigen Skript weisen Sie GDB an, die Protokollierung zu aktivieren und das Protokoll in einer Datei mit dem Namen zu speichern probe.out, und setzen Sie dann einen Haltepunkt am hauptsächlich Funktion.
Führen Sie für Haltepunkt Nummer 1, in diesem Fall den Haltepunkt an der Funktion main, die folgenden Befehle aus: Rückverfolgung, drucken, weitermachen. Grundsätzlich führt GDB zunächst einen Backtrace aus, gibt dann den Wert der Variablen „N“ aus, setzt die Ausführung fort und beendet schließlich den Vorgang.
Um dieses Skript auszuführen, verwenden Sie:
gdb -x