Friedrich-Alexander-Universität Erlangen-Nürnberg  /   Technische Fakultät  /   Department Informatik

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>

Klassendiagramm für GDB_Stub:
Zusammengehörigkeiten von GDB_Stub:

Klassen

struct  state
 Struktur mit dem Systemzustands nach Traps. Mehr ...
 

Öffentliche Methoden

 GDB_Stub (bool wait=false, bool debugOutput=false, Serial::comPort port=COM1, Serial::baudRate baudrate=BAUD_9600)
 Konstruktor. Mehr ...
 
- Öffentliche Methoden geerbt von Serial
 Serial (Serial::comPort port=COM1, Serial::baudRate baudrate=BAUD_115200, Serial::dataBits databits=DATA_8BIT, Serial::stopBits stopbits=STOP_1BIT, Serial::parity parity=PARITY_NONE)
 Konstruktor. Mehr ...
 
int read (bool blocking=true)
 Lese ein Byte von serieller Schnittstelle. Mehr ...
 
int write (char out, bool blocking=true)
 Schreibe ein Byte auf die serieller Schnittstelle. Mehr ...
 
bool receiveInterrupt (bool enable)
 Unterbrechung bei Datenempfang. Mehr ...
 

Geschützte Typen

enum  Registers {
  REG_EAX = 0, REG_ECX = 1, REG_EDX = 2, REG_EBX = 3,
  REG_ESP = 4, REG_EBP = 5, REG_ESI = 6, REG_EDI = 7,
  REG_PC = 8, REG_PS = 9, REG_CS = 10, REG_SS = 11,
  REG_DS = 12, REG_ES = 13, REG_FS = 14, REG_GS = 15,
  NUM_REGISTERS = 16
}
 zur Verfügung stehende (gesicherte) Register
 
typedef unsigned int address
 Datentyp für Speicheradresse (mit Zeigerarithmetik)
 
typedef unsigned int reg
 Datentyp für Register.
 

Geschützte Methoden

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 ...
 

Geschützte Attribute

struct state state
 Speicher für den aktuelle CPU Zustand. Mehr ...
 

Freundbeziehungen

void debug_handler (struct debug_context *context)
 Erlaube der generischen Unterbrechungsbehandlung Zugriff auf die geschützten Methoden dieser Klasse. Mehr ...
 

Weitere Geerbte Elemente

- Öffentliche Typen geerbt von Serial
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.
 

Ausführliche Beschreibung

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/system
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
[...]
Reading symbols from /proj/i4bs/student/uj66ojab/kernel...done.
(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).

Beschreibung der Konstruktoren und Destruktoren

◆ GDB_Stub()

GDB_Stub::GDB_Stub ( bool  wait = false,
bool  debugOutput = false,
Serial::comPort  port = COM1,
Serial::baudRate  baudrate = BAUD_9600 
)

Konstruktor.

Konfiguriert die serielle Schnittstelle (als 8N1 ) sowie Unterbrechungsbehandlungen

Parameter
waitWarte nach der Konfiguration auf eine GDB-Verbindung
debugOutputDebugge den GDB-Stub durch Bildschirmausgaben der Kommunikation (hilfreich bei Erweiterung des RSP)
portCOM-Port für die serielle Verbindung
baudrateBaud Rate, Standard bei GDB ist 9600 (kann aber zu Engpässen führen)

Dokumentation der Elementfunktionen

◆ checksum()

int GDB_Stub::checksum ( const char *  buf,
size_t  len 
)
protected

Berechne die Prüfsumme.

Parameter
bufZeiger auf den Puffer
lenGröß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
vectorder zu ändernde Trap-Vektor
Rückgabewerte
truebei erfolgreicher Änderung der Unterbrechungsbehandlungsroutine
falsebei 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
bufZeiger auf den Puffer
buf_lenGröße des puffers
addrStartadresse des zu lesenden Speichers
lenGröße des zu lesenden Speichers
hexSpeichere 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
bufZeiger auf den Puffer
buf_lenGröße des puffers
addrStartadresse des zu schreibenden Speichers
lenGröße des zu schreibenden Speichers
hexInterpretiere 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
bufZeiger auf den Puffer
buf_lenGröße des Puffers
lenAnzahl der zu empfangenden Bytes
Rückgabewerte
0falls erfolgreich,
-1falls 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
0eine [positive] Bestätigung (ACK, + ) wurde empfangen
1eine negative Bestätigung (NACK, - ) wurde empfangen
-1andernfalls

◆ 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_bufZeiger auf den Paketpuffer
pkt_buf_lenGröße des Paketpuffers
pkt_lenGröße des zu empfangenden Pakets
Rückgabewerte
0falls Paket erfolgreich empfangen wurde,
-1andernfalls

◆ 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

$<Daten>#<Prüfsumme>
Parameter
pktZeiger auf den Paketpuffer
pkt_lenGröße des Paketpuffers
Rückgabewerte
0falls Paket erfolgreich gesendet und bestätigt wurde,
1falls Paket zwar gesendet aber nicht bestätigt wurde,
-1andernfalls

◆ 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
bufZeiger auf den Puffer
lenGröße des Puffers
Rückgabewerte
0falls erfolgreich,
-1falls kein/nicht alle Bytes gesendet werden konnten

Freundbeziehungen und Funktionsdokumentation

◆ debug_handler

void debug_handler ( struct debug_context context)
friend

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.

Parameter
contextbeinhaltet einen Pointer auf den eigenen Stack, über den auf den Debug-Unterbrechungskontext zugegriffen werden kann.

Dokumentation der Datenelemente

◆ state

struct state GDB_Stub::state
protected

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