Made a start with documentation for the GDB server implementation

This commit is contained in:
Nav
2022-04-03 02:13:06 +01:00
parent 62375c306c
commit ac534eef95
2 changed files with 131 additions and 3 deletions

View File

@@ -0,0 +1,124 @@
## GDB Remote Serial Protocol (RSP) debug server
The GDB RSP debug server implements GDB's
[Remote Serial Protocol](https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html) over a TCP/IP connection.
With this debug server, users can perform debugging operations on the connected target via GDB. This can be done via
GDB's command line interface, or via an IDE that supports remote GDB capabilities (See
[GDB's machine interface](https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI.html) for more on how GDB is integrated
into IDEs).
The implementation can be found in the `GdbRspDebugServer` class. This class is an abstract class - it does not
implement any target architecture specific functionality.
See ['Target architecture specific functionality'](#target-architecture-specific-functionality) section below for more.
---
### Commands and responses
The objective of the GDB server is to provide GDB with an interface to the connected target, to enable debugging
operations such as memory access and program flow control. The GDB server achieves this by actioning commands sent by
the client (GDB) and returning responses.
Simply put, once GDB has established a connection with the GDB server, it will begin to send commands to the server.
These commands are to be actioned by the GDB server, with the appropriate response being returned, if necessary.
For example, when the GDB user runs the command `b main.cpp:22` in the GDB CLI, instructing GDB to insert a breakpoint
at line 22 in main.cpp, GDB will send a command to the GDB server, requesting that a breakpoint be added at the
appropriate address in program memory. The GDB server will action this command, and then return a response indicating
success or failure.
Commands and responses are delivered in packets. The
[`Bloom::DebugServer::Gdb::CommandPackets::CommandPacket`](./CommandPackets/CommandPacket.hpp) and
[`Bloom::DebugServer::Gdb::ResponsePackets::ResponsePacket`](./ResponsePackets/ResponsePacket.hpp) classes are base
classes for these packets. For most GDB commands supported by this server implementation, there is a specific command
packet that can be found in [/src/DebugServer/Gdb/CommandPackets](./CommandPackets). When the server receives a command
packet from the GDB client, the appropriate (`CommandPacket` derived) object is constructed, which encapsulates all of
the relevant information for the particular command.
Consider the [`Bloom::DebugServer::Gdb::CommandPackets::SetBreakpoint`](./CommandPackets/SetBreakpoint.hpp) command
packet class:
```c++
class SetBreakpoint: public CommandPacket
{
public:
/**
* Breakpoint type (Software or Hardware)
*/
BreakpointType type = BreakpointType::UNKNOWN;
/**
* Address at which the breakpoint should be located.
*/
std::uint32_t address = 0;
explicit SetBreakpoint(const std::vector<unsigned char>& rawPacket): CommandPacket(rawPacket) {
this->init();
};
void handle(DebugSession& debugSession, TargetControllerConsole& targetControllerConsole) override;
private:
void init();
};
```
The `SetBreakpoint` class consists of two public fields; The `address` (at which the breakpoint is to be set). And the
`type` (of breakpoint to set). These two fields are initialised from the raw command packet, during object construction.
#### Command handling
Upon receiving a command packet from the GDB client, the command must be handled and the appropriate response delivered.
Each command packet class implements a `handle()` member function. This function is called upon receipt of the command
and is expected to handle the command and deliver any necessary response to the client.
Handling the `SetBreakpoint` command packet:
```c++
void SetBreakpoint::handle(DebugSession& debugSession, TargetControllerConsole& targetControllerConsole) {
/*
* I know the breakpoint type (this->type) isn't used in here - this is because the current implementation only
* supports software breakpoints, so we don't do anything with this->type, for now.
*/
Logger::debug("Handling SetBreakpoint packet");
try {
targetControllerConsole.setBreakpoint(TargetBreakpoint(this->address));
debugSession.connection.writePacket(OkResponsePacket());
} catch (const Exception& exception) {
Logger::error("Failed to set breakpoint on target - " + exception.getMessage());
debugSession.connection.writePacket(ErrorResponsePacket());
}
}
```
Some GDB commands are handled in the base `CommandPacket` class (see
[`CommandPacket::handle()`](./CommandPackets/CommandPacket.cpp)). Either these commands were too trivial to justify a
new command packet class, or I was too lazy to create one.
---
### Target architecture specific functionality
Within the source code of GDB, there are some hardcoded concepts that are specific to GDB and a particular target
architecture. For example, the AVR implementation of GDB defines a mapping of AVR registers to GDB register numbers.
The GDB register numbers are just identifiers for AVR registers - they allow GDB to refer to a particular AVR register.
| AVR Register Name | GDB Register Number |
|-------------------------------------------|---------------------|
| R0 -> R31 (general purpose CPU registers) | 0 -> 31 |
| Status Register (SREG) | 32 |
| Stack Pointer (SP) | 33 |
| Program Counter (PC) | 34 |
GDB expects the server to be aware of these predefined concepts. This is why the `GdbRspDebugServer` class is an
abstract class - it implements the generic GDB server functionality, but leaves the target architecture specific
functionality to be implemented in derived classes.
#### GDB target descriptor
The [`Bloom::DebugServer::Gdb::TargetDescriptor`](./TargetDescriptor.hpp) abstract class provides access to any
information that is specific to the target architecture and GDB. For example, the register mapping described above, for
AVR targets, is implemented in [`Bloom::DebugServer::Gdb::AvrGdb::TargetDescriptor`](./AvrGdb/TargetDescriptor.hpp).
That class is derived from the abstract `TargetDescriptor` class. It implements the AVR specific concepts that the
server is expected to be aware of.

View File

@@ -32,6 +32,8 @@ running (it hasn't received an event which triggers a shutdown), the `ServerInte
again, and control will be handed back to the server implementation. The AVR GDB server implementation employs this again, and control will be handed back to the server implementation. The AVR GDB server implementation employs this
method to ensure that events are processed ASAP. See the relevant documentation for more. method to ensure that events are processed ASAP. See the relevant documentation for more.
---
Any blocking I/O employed by a server implementation can support event interrupts using an Any blocking I/O employed by a server implementation can support event interrupts using an
[`EventNotifier`](../Helpers/EventNotifier.hpp) and [`EpollInstance`](../Helpers/EpollInstance.hpp). [`EventNotifier`](../Helpers/EventNotifier.hpp) and [`EpollInstance`](../Helpers/EpollInstance.hpp).
@@ -54,13 +56,15 @@ the interruption of blocking I/O operations when an event is triggered. Specific
[`GdbRspDebugServer::waitForConnection()`](./Gdb/GdbRspDebugServer.hpp) or [`GdbRspDebugServer::waitForConnection()`](./Gdb/GdbRspDebugServer.hpp) or
[`Gdb::Connection::read()`](./Gdb/Connection.hpp). [`Gdb::Connection::read()`](./Gdb/Connection.hpp).
---
### Server implementations ### Server implementations
Currently, there is only one server implementation. Others may be added upon request. Currently, there is only one server implementation. Others may be added upon request.
| Server Name | Brief Description | Documentation | | Server Name | Brief Description | Documentation |
|----------------|-------------------|---------------| |----------------|-------------------------------------------------------------------------------|---------------------------------------------------|
| AVR GDB Server | An AVR-specific implementation of the GDB Remote Serial Protocol over TCP/IP. | To follow | | AVR GDB Server | An AVR-specific implementation of the GDB Remote Serial Protocol over TCP/IP. | [/src/DebugServer/Gdb/README.md](./Gdb/README.md) |
#### Adding new server implementations #### Adding new server implementations