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 <debug/gdb/stub.h>
|
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, uintptr_t 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, uintptr_t 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.
|
|
|
enum | comPort { COM1 = 0x3f8,
COM2 = 0x2f8,
COM3 = 0x3e8,
COM4 = 0x238
} |
| COM-Port. Mehr ...
|
|
enum | baudRate {
BAUD_300 = 384,
BAUD_600 = 192,
BAUD_1200 = 96,
BAUD_2400 = 48,
BAUD_4800 = 24,
BAUD_9600 = 12,
BAUD_19200 = 6,
BAUD_38400 = 3,
BAUD_57600 = 2,
BAUD_115200 = 1
} |
| Übertragungsgeschwindigkeit. Mehr ...
|
|
enum | dataBits { DATA_5BIT = 0,
DATA_6BIT = 1,
DATA_7BIT = 2,
DATA_8BIT = 3
} |
| Anzahl der Datenbits pro Zeichen.
|
|
enum | stopBits { STOP_1BIT = 0,
STOP_1_5BIT = 4,
STOP_2BIT = 4
} |
| Anzahl der Stopbits pro Zeichen.
|
|
enum | parity {
PARITY_NONE = 0,
PARITY_ODD = 8,
PARITY_EVEN = 24,
PARITY_MARK = 40,
PARITY_SPACE = 56
} |
| Paritätsbit.
|
|
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.
Beispiel:
~> ssh faui04a
faui04a:~> cd mpstubs
faui04a:~/mpstubs> make netboot
faui04a:~/mpstubs> gdb .build/system64
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
[...]
Reading symbols from /proj/i4bs/student/uj66ojab/kernel...done.
(gdb) set arch i386:x86-64
(gdb) set serial baud 9600
(gdb) target remote /dev/ttyBS1
Remote debugging using /dev/ttyBS1
main () at main.cc:87
- 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.
◆ mem_read()
int GDB_Stub::mem_read |
( |
char * |
buf, |
|
|
size_t |
buf_len, |
|
|
uintptr_t |
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, |
|
|
uintptr_t |
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. |
Da wir nur einen internen Zustandsspeicher haben, kann dies im Mehrkern- betrieb schnell böse enden, wenn mehrere Kerne gleichzeitig schreibend darauf zugreifen wollen. Deshalb exklusiver Ausschluss!
Selbstverständlich sollte man bei der Kombination 'aktives Warten' und 'Unterbrechungsbehandlung' sofort üble Bauchschmerzen bekommen. Als Ausrede dient hier, dass es für den Debugger ist, welcher zum einen so einfach wie möglich sein sollte, zum anderen auch nicht im produktiven Betrieb verwendet werden sollte.
Also bitte nur als 'simple Hack' und nicht als 'best practice' im Hinterkopf behalten.
Die Dokumentation für diese Klasse wurde erzeugt aufgrund der Dateien:
- debug/gdb/stub.h
- debug/gdb/handler.cc
- debug/gdb/protocol.cc