Während kgdb als Offline-Debugger eine Benutzerschnittstelle auf höchster Ebene bietet, gibt es einige Dinge, die es nicht kann. Die wichtigsten sind das Setzen von Breakpoints und das Abarbeiten des Kernel-Codes in Einzelschritten (Single-Stepping).
Falls Sie eine systemnahe Fehlersuche an Ihrem Kernel vorhaben, steht Ihnen ein Online-Debugger mit dem Namen DDB zur Verfügung. Er erlaubt Ihnen das Setzen von Breakpoints, die Abarbeitung von Kernel-Funktionen in Einzelschritten, das Untersuchen und Verändern von Kernel-Variablen usw. Jedoch hat er keinen Zugriff auf Kernel-Quelldateien, sondern kann nur, im Gegensatz zu gdb, welches auf die ganzen Informationen zur Fehlersuche zurückgreifen kann, auf globale und statische Symbole zugreifen.
Um DDB in Ihren Kernel einzubinden, fügen Sie die Optionen
options KDB
options DDBIhrer Konfigurationsdatei hinzu und bauen Sie den Kernel neu. (Details zur Konfiguration des FreeBSD-Kernels finden Sie im FreeBSD-Handbuch).
Anmerkung: Falls Sie eine ältere Version des Boot-Blocks haben, könnte es sein, dass Ihre Symbole zur Fehlersuche noch nicht einmal geladen werden. Aktualisieren Sie den Boot-Block; aktuelle Versionen laden die DDB-Symbole automatisch.
Sobald Ihr Kernel mit DDB startet, gibt es mehrere Wege, um in DDB zu gelangen. Der
erste und früheste Weg ist, das Boot-Flag -d
gleich an der
Boot-Eingabeaufforderung einzugeben. Der Kernel startet dann in den Debug-Modus und
betritt DDB noch vor jedweder Gerätesuche. Somit können Sie Funktionen zur
Gerätesuche/-bereitstellung auf Fehler untersuchen. FreeBSD-CURRENT-Benutzer müssen die
sechste Option im Boot-Menü auswählen, um an eine Eingabeaufforderung zu gelangen.
Das zweite Szenario ist der Gang in den Debugger, sobald das System schon gestartet ist. Es gibt zwei einfache Wege dies zu erreichen. Falls Sie von der Eingabeaufforderung aus in den Debugger gelangen möchten, geben Sie einfach folgenden Befehl ab:
# sysctl debug.kdb.enter=1
Anmerkung: Um eine schnelle Panic zu erzwingen, geben Sie das folgende Kommando ein:
# sysctl debug.kdb.panic=1
Anderenfalls können Sie ein Tastenkürzel auf der Tastatur benutzen, wenn Sie an der Systemkonsole sind. Die Voreinstellung für die break-to-debugger-Sequenz ist Ctrl+Alt+ESC. In syscons kann diese Sequenz auf eine andere Tastenkombination gelegt werden (remap) und manche der verfügbaren Tastaturlayouts tun dies, stellen Sie also sicher, dass Sie die richtige Sequenz kennen, die benutzt werden soll. Für serielle Konsolen ist eine Option vorhanden, die die Benutzung einer Unterbrechung der seriellen Verbindung (BREAK) auf der Kommandozeile erlaubt, um in DDB zu gelangen (options BREAK_TO_DEBUGGER in der Kernel-Konfigurationsdatei). Dies ist jedoch nicht der Standard, da viele serielle Adapter in Verwendung sind, die grundlos eine BREAK-Bedingung erzeugen, zum Beispiel bei Ziehen des Kabels.
Die dritte Möglichkeit ist, dass jede Panic-Bedingung in DDB springt, falls der Kernel hierfür konfiguriert ist. Aus diesem Grund ist es nicht sinnvoll einen Kernel mit DDB für ein unbeaufsichtigtes System zu konfigurieren.
Um die unbeaufsichtigte Funktionsweise zu erreichen fügen Sie:
options KDB_UNATTENDED
der Kernel-Konfigurationsdatei hinzu und bauen/installieren Sie den Kernel neu.
Die DDB-Befehle ähneln grob einigen gdb-Befehlen. Das Erste, das Sie vermutlich tun müssen, ist einen Breakpoint zu setzen:
break function-name address
Zahlen werden standardmäßig hexadezimal angegeben, aber um sie von Symbolnamen zu unterscheiden, muss Zahlen, die mit den Buchstaben a-f beginnen, 0x vorangehen (dies ist für andere Zahlen beliebig). Einfache Ausdrücke sind erlaubt, zum Beispiel: function-name + 0x103.
Um den Debugger zu verlassen und mit der Abarbeitung fortzufahren, geben Sie ein:
continue
Um eine Stack-Ablaufverfolgung zu erhalten, benutzen Sie:
trace
Anmerkung: Beachten Sie, dass wenn Sie DDB mittels einer Schnelltaste betreten, der Kernel zurzeit einen Interrupt bereitstellt, sodass die Stack-Ablaufverfolgung Ihnen nicht viel nützen könnte.
Falls Sie einen Breakpoint entfernen möchten, benutzen Sie
del del address-expression
Die erste Form wird direkt, nachdem ein Breakpoint anschlug, angenommen und entfernt den aktuellen Breakpoint. Die zweite kann jeden Breakpoint löschen, aber Sie müssen die genaue Adresse angeben; diese kann bezogen werden durch:
show b
oder:
show break
Um den Kernel in Einzelschritten auszuführen, probieren Sie:
s
Dies springt in Funktionen, aber Sie können DDB veranlassen, diese schrittweise zu verfolgen, bis die passende Rückkehranweisung (Return-Statement) erreicht ist. Nutzen Sie hierzu:
n
Anmerkung: Dies ist nicht das gleiche wie die next-Anweisung von gdb; es ist wie gdbs finish. Mehrmaliges Drücken von n führt zu einer Fortsetzung.
Um Daten aus dem Speicher zu untersuchen, benutzen Sie (zum Beispiel):
x/wx 0xf0133fe0,40 x/hd db_symtab_space x/bc termbuf,10 x/s stringbuffür Word/Halfword/Byte-Zugriff und Hexadezimal/Dezimal/Character/String-Ausgabe. Die Zahl nach dem Komma ist der Objektzähler. Um die nächsten 0x10 Objekte anzuzeigen benutzen Sie einfach:
x ,10
Gleichermaßen benutzen Sie
x/ia foofunc,10um die ersten 0x10 Anweisungen aus
foofunc
zu zerlegen
(disassemble) und Sie zusammen mit ihrem Adressabstand (Offset) vom Anfang von foofunc
auszugeben.Um Speicher zu verändern benutzen Sie den Schreibbefehl:
w/b termbuf 0xa 0xb 0 w/w 0xf0010030 0 0
Die Befehlsoption (b/h/w) legt die Größe der Daten fest, die geschrieben werden sollen, der erste Ausdruck danach ist die Adresse, wohin geschrieben werden soll, und der Rest wird als Daten verarbeitet, die in aufeinander folgende Speicherstellen geschrieben werden.
Falls Sie die aktuellen Register wissen möchten, benutzen Sie:
show reg
Alternativ können Sie den Inhalt eines einzelnen Registers ausgeben mit z.B.
p $eaxund ihn bearbeiten mit:
set $eax new-value
Sollten Sie irgendeine Kernel-Funktion aus DDB heraus aufrufen wollen, geben Sie einfach ein:
call func(arg1, arg2, ...)
Der Rückgabewert wird ausgegeben.
Für eine Zusammenfassung aller laufenden Prozesse im Stil von ps(1) benutzen Sie:
ps
Nun haben Sie herausgefunden, warum Ihr Kernel fehlschlägt, und möchten neu starten. Denken Sie daran, dass, abhängig von der Schwere vorhergehender Störungen, nicht alle Teile des Kernels wie gewohnt funktionieren könnten. Führen Sie eine der folgenden Aktionen durch, um Ihr System herunterzufahren und neu zu starten:
panic
Dies wird Ihren Kernel dazu veranlassen abzustürzen, einen Speicherauszug abzulegen und neu zu starten, sodass Sie den Kernspeicherauszug später auf höherer Ebene mit gdb auswerten können. Diesem Befehl muss normalerweise eine weitere continue-Anweisung folgen.
call boot(0)
Dürfte ein guter Weg sein, um das laufende System sauber herunterzufahren, alle
Festplatten mittels sync()
zu schreiben und schließlich, in
manchen Fällen, neu zu starten. Solange die Festplatten- und Dateisystemschnittstellen
des Kernels nicht beschädigt sind, könnte dies ein guter Weg für ein beinahe sauberes
Abschalten sein.
call cpu_reset()
Dies ist der letzte Ausweg aus der Katastrophe und kommt beinahe dem Drücken des Ausschaltknopfes gleich.
Falls Sie eine kurze Zusammenfassung aller Befehle benötigen, geben Sie einfach ein:
help
Es ist strengstens empfohlen, eine ausgedruckte Version der ddb(4)-Manualpage während der Fehlersuche neben sich liegen zu haben. Denken Sie daran, dass es schwer ist, die Online-Hilfe zu lesen, während der Ausführung des Kernels in Einzelschritten.
Zurück | Zum Anfang | Weiter |
Fehlersuche in einem Speicherauszug nach einem Absturz mit DDD | Nach oben | Online-Kernel-Fehlersuche mit GDB auf einem entfernten System |
Wenn Sie Fragen zu FreeBSD haben, schicken Sie eine E-Mail an
<de-bsd-questions@de.FreeBSD.org>.
Wenn Sie Fragen zu dieser Dokumentation haben, schicken Sie eine E-Mail an <de-bsd-translators@de.FreeBSD.org>.