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
Ihrer Konfigurationsdatei hinzu und bauen Sie den Kernel neu. (Details zur Konfiguration des FreeBSD-Kernels finden Sie im FreeBSD-Handbuch).
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
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:
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
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
Dies ist nicht das gleiche wie die
next
-Anweisung von gdb
;
es ist wie gdb
s 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 stringbuf
fü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,10
um 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 $eax
und 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.
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>.