GDB Remote Stub KlasseDiese Klasse ermöglicht ein entferntes Debuggen des Betriebssystems mit GDB auf echter Hardware (aber auch im Emulator), in dem sie einen Teil des GDB Remote Serial Protocols (RSP) implementiert, eigene Unterbrechungsbehandlungsroutinen für Traps installiert und über die serielle Schnittstelle kommuniziert.
Mehr ...
#include <stub.h>
|
struct | state |
| Struktur mit dem Systemzustands nach Traps. Mehr ...
|
|
|
enum | Registers |
| zur Verfügung stehende (gesicherte) Register
|
|
typedef unsigned int | address |
| Datentyp für Speicheradresse (mit Zeigerarithmetik)
|
|
typedef unsigned int | reg |
| Datentyp für Register.
|
|
|
void | handle (void) |
| Behandlung eines Traps. Mehr ...
|
|
int | writeString (const char *buf, size_t len) |
| Sende eine Zeichenkette über die serielle Schnittstelle. Mehr ...
|
|
int | readString (char *buf, size_t buf_len, size_t len) |
| Empfange eine Zeichenkette über die serielle Schnittstelle. Mehr ...
|
|
int | send_packet (const char *pkt, size_t pkt_len) |
| Sende ein Datenpaket. Mehr ...
|
|
int | recv_packet (char *pkt_buf, size_t pkt_buf_len, size_t *pkt_len) |
| Empfange ein Datenpaket. Mehr ...
|
|
int | checksum (const char *buf, size_t len) |
| Berechne die Prüfsumme. Mehr ...
|
|
int | recv_ack (void) |
| Empfange ein Bestätigung für ein Paket. Mehr ...
|
|
int | send_ok_packet () |
| Erstelle und sende ein OK Paket. Mehr ...
|
|
int | send_signal_packet (char *buf, size_t buf_len, char signal) |
| Erstelle und sende ein Signalpaket. Mehr ...
|
|
int | send_error_packet (char *buf, size_t buf_len, char error) |
| Erstelle und sende ein Fehlerpaket (E Errorcode) Mehr ...
|
|
int | mem_read (char *buf, size_t buf_len, address addr, size_t len, bool hex) |
| Lese den Speicherinhalt einer Adresse in den Puffer. Mehr ...
|
|
int | mem_write (const char *buf, size_t buf_len, address addr, size_t len, bool hex) |
| Schreibe den Pufferinhalt an eine Adresse. Mehr ...
|
|
void | sys_continue (void) |
| Setze das Programm am aktuellen Instruktionszeiger fort.
|
|
void | sys_step (void) |
| Springe zur nächsten Instruktion.
|
|
bool | install_handler (int vector) |
| Installiere Unterbrechungsbehandlung für Trap-Vektoren. Mehr ...
|
|
|
const bool | debug |
| zusätzliche Debug-Ausgaben auf dem Zielrechner (zum debuggen des Debuggerstubs)
|
|
GDB Remote Stub Klasse
Diese Klasse ermöglicht ein entferntes Debuggen des Betriebssystems mit GDB auf echter Hardware (aber auch im Emulator), in dem sie einen Teil des GDB Remote Serial Protocols (RSP) implementiert, eigene Unterbrechungsbehandlungsroutinen für Traps installiert und über die serielle Schnittstelle kommuniziert.
Für den Einsatz muss GDB mit der selben Binärdatei wie das Betriebssystem auf der Hardware gestartet werden – idealerweise im Quelltextverzeichnis, denn dann kann der Quelltext in die Ausgabe eingebettet werden. Zudem müssen die Einstellungen für die seriellen Übertragung sowohl auf der Hardware als auch im GDB identisch sein.
- Zu beachten
- GDB liegt bereits eine i386-stub.c bei, welche jedoch hässlich, schlecht gewartet und nicht sonderlich gut in unser objektorientiertes Betriebssystem integrierbar ist. Deshalb verwenden wir eine überarbeitete Version von Matt Borgersons gdbstub (veröffentlicht 2016 unter der GPL v2 Lizenz).
◆ GDB_Stub()
Konstruktor.
Konfiguriert die serielle Schnittstelle (als 8N1
) sowie Unterbrechungsbehandlungen
- Parameter
-
wait | Warte nach der Konfiguration auf eine GDB-Verbindung |
debugOutput | Debugge den GDB-Stub durch Bildschirmausgaben der Kommunikation (hilfreich bei Erweiterung des RSP) |
port | COM-Port für die serielle Verbindung |
baudrate | Baud Rate, Standard bei GDB ist 9600 (kann aber zu Engpässen führen) |
◆ checksum()
int GDB_Stub::checksum |
( |
const char * |
buf, |
|
|
size_t |
len |
|
) |
| |
|
protected |
Berechne die Prüfsumme.
- Parameter
-
buf | Zeiger auf den Puffer |
len | Größe des Puffers |
- Rückgabe
- 8-Bit Prüfsumme des Puffers
◆ handle()
void GDB_Stub::handle |
( |
void |
| ) |
|
|
protected |
Behandlung eines Traps.
Diese Funktion wird nach der Speicherung des aktuellen CPU Zustandes von der generischen Debug-Unterbrechungsbehandlungsroutine aufgerufen. Sie ist das Herzstück und übernimmt die Kommunikation mit dem GDB Host.
◆ install_handler()
bool GDB_Stub::install_handler |
( |
int |
vector | ) |
|
|
protected |
Installiere Unterbrechungsbehandlung für Trap-Vektoren.
Der Code für die spezifischen Debugger-Unterbrechungsbehandlungen der Traps ist in Assembler in der debug/gdb/handler.asm
verfasst. Diese ähneln den ebenfalls in Assembler verfassten Einsprungsfunktionen in der boot/startup.asm
für den guardian , sichern jedoch explizit den kompletten Zustand des Systems (inklusive callee save und Segment-Register) und springen eine eigene generische Debug-Unterbrechungsbehandlung an: den GDB_Stub::debug_handler
Da der GDB Stub dynamisch (zur Laufzeit) aktivierbar sein soll, wird vor dem Initialisieren der Klasse die zentrale Unterbrechungsbehandlungsroutine guardian für den Vektor verwendet. Erst durch Aufruf dieser Methode wird die spezifische Debug- Unterbrechungsbehandlung für den Vektor eingestellt.
Hierfür muss die Interrupt Deskriptortabelle (IDT) modifiziert werden: Beim Eintrag an der für den Vektor entsprechenden Stelle (Gate) wird die Adresse der Behandlungsfunktion geändert. Diese zeigt ursprünglich auf irq_entry_VEKTORNUMMER
(definiert in der boot/startup.asm
), wird nun jedoch auf die Adresse des debug/gdb/handler.asm
-Äquivalents dbg_irq_entry_VEKTORNUMMER
geändert.
- Parameter
-
vector | der zu ändernde Trap-Vektor |
- Rückgabewerte
-
true | bei erfolgreicher Änderung der Unterbrechungsbehandlungsroutine |
false | bei Fehler (z.B. ungültige Vektornummer) |
◆ mem_read()
int GDB_Stub::mem_read |
( |
char * |
buf, |
|
|
size_t |
buf_len, |
|
|
address |
addr, |
|
|
size_t |
len, |
|
|
bool |
hex |
|
) |
| |
|
protected |
Lese den Speicherinhalt einer Adresse in den Puffer.
- Parameter
-
buf | Zeiger auf den Puffer |
buf_len | Größe des puffers |
addr | Startadresse des zu lesenden Speichers |
len | Größe des zu lesenden Speichers |
hex | Speichere als Hexadezimal (true ) oder binär (false ) in den Puffer |
- Rückgabe
- Anzahl der gelsenen Bytes oder
-1
falls der Puffer zu klein
◆ mem_write()
int GDB_Stub::mem_write |
( |
const char * |
buf, |
|
|
size_t |
buf_len, |
|
|
address |
addr, |
|
|
size_t |
len, |
|
|
bool |
hex |
|
) |
| |
|
protected |
Schreibe den Pufferinhalt an eine Adresse.
- Parameter
-
buf | Zeiger auf den Puffer |
buf_len | Größe des puffers |
addr | Startadresse des zu schreibenden Speichers |
len | Größe des zu schreibenden Speichers |
hex | Interpretiere den Pufferinhalt als Hexadezimal (true ) oder binär (false ) |
- Rückgabe
- Anzahl der geschrieben Bytes oder
-1
falls der Puffer zu gross
◆ readString()
int GDB_Stub::readString |
( |
char * |
buf, |
|
|
size_t |
buf_len, |
|
|
size_t |
len |
|
) |
| |
|
protected |
Empfange eine Zeichenkette über die serielle Schnittstelle.
- Parameter
-
buf | Zeiger auf den Puffer |
buf_len | Größe des Puffers |
len | Anzahl der zu empfangenden Bytes |
- Rückgabewerte
-
0 | falls erfolgreich, |
-1 | falls kein/nicht alle Bytes empfangen werden konnten |
◆ recv_ack()
int GDB_Stub::recv_ack |
( |
void |
| ) |
|
|
protected |
Empfange ein Bestätigung für ein Paket.
- Rückgabewerte
-
0 | eine [positive] Bestätigung (ACK, + ) wurde empfangen |
1 | eine negative Bestätigung (NACK, - ) wurde empfangen |
-1 | andernfalls |
◆ recv_packet()
int GDB_Stub::recv_packet |
( |
char * |
pkt_buf, |
|
|
size_t |
pkt_buf_len, |
|
|
size_t * |
pkt_len |
|
) |
| |
|
protected |
Empfange ein Datenpaket.
Bedingt eine fehlerfreie Verbindung zur Übertragung von 7-Bit ANSI Zeichen
- Parameter
-
pkt_buf | Zeiger auf den Paketpuffer |
pkt_buf_len | Größe des Paketpuffers |
pkt_len | Größe des zu empfangenden Pakets |
- Rückgabewerte
-
0 | falls Paket erfolgreich empfangen wurde, |
-1 | andernfalls |
◆ send_error_packet()
int GDB_Stub::send_error_packet |
( |
char * |
buf, |
|
|
size_t |
buf_len, |
|
|
char |
error |
|
) |
| |
|
protected |
Erstelle und sende ein Fehlerpaket (E
Errorcode)
- Rückgabe
- Statuscode von send_packet
◆ send_ok_packet()
int GDB_Stub::send_ok_packet |
( |
| ) |
|
|
protected |
Erstelle und sende ein OK
Paket.
- Rückgabe
- Statuscode von send_packet
◆ send_packet()
int GDB_Stub::send_packet |
( |
const char * |
pkt, |
|
|
size_t |
pkt_len |
|
) |
| |
|
protected |
Sende ein Datenpaket.
Datenpakete haben die Form
- Parameter
-
pkt | Zeiger auf den Paketpuffer |
pkt_len | Größe des Paketpuffers |
- Rückgabewerte
-
0 | falls Paket erfolgreich gesendet und bestätigt wurde, |
1 | falls Paket zwar gesendet aber nicht bestätigt wurde, |
-1 | andernfalls |
◆ send_signal_packet()
int GDB_Stub::send_signal_packet |
( |
char * |
buf, |
|
|
size_t |
buf_len, |
|
|
char |
signal |
|
) |
| |
|
protected |
Erstelle und sende ein Signalpaket.
beinhaltet aktuellen Interruptvektor (S
Vektor)
- Rückgabe
- Statuscode von send_packet
◆ writeString()
int GDB_Stub::writeString |
( |
const char * |
buf, |
|
|
size_t |
len |
|
) |
| |
|
protected |
Sende eine Zeichenkette über die serielle Schnittstelle.
- Parameter
-
buf | Zeiger auf den Puffer |
len | Größe des Puffers |
- Rückgabewerte
-
0 | falls erfolgreich, |
-1 | falls kein/nicht alle Bytes gesendet werden konnten |
◆ debug_handler
Erlaube der generischen Unterbrechungsbehandlung Zugriff auf die geschützten Methoden dieser Klasse.
Debug-Unterbrechungsbehandlungsroutine des Systems, analog zu guardian . Aufruf dieser Funktion durch den Assembler Teil der Debug- Unterbrechungsbehandlung (dbg_irq_entry_*
in der debug/gbd/handler.asm
) – diese Routinen müssen zuvor mittels GDB_Stub::install_handler installiert werden. Nach dem vorbereiten der Daten wird GDB_Stub::handle aufgerufen, welches mit dem Host über die serielle Schnittstelle kommuniziert.
- Zu beachten
- Für korrekte Funktionalität im Multiprozessorfall wird eine korrekte Implementierung der Klasse Ticketlock vorausgesetzt!
- Parameter
-
context | beinhaltet einen Pointer auf den eigenen Stack, über den auf den Debug-Unterbrechungskontext zugegriffen werden kann. |
◆ state
Speicher für den aktuelle CPU Zustand.
Wird am Beginn einer Unterbrechungsbehandlung aktualisiert und an deren Ende wieder zurückgeschrieben (mit ggf. modifizierten Werten)
Die Dokumentation für diese Klasse wurde erzeugt aufgrund der Dateien:
- debug/gdb/stub.h
- debug/gdb/handler.cc
- debug/gdb/init.cc
- debug/gdb/protocol.cc