Tidied GDB RSP debug server

This commit is contained in:
Nav
2022-04-05 18:49:54 +01:00
parent e3beea6b40
commit b8e34b87d3
2 changed files with 67 additions and 43 deletions

View File

@@ -1,7 +1,6 @@
#include "GdbRspDebugServer.hpp" #include "GdbRspDebugServer.hpp"
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/epoll.h>
#include "src/Logger/Logger.hpp" #include "src/Logger/Logger.hpp"
@@ -48,17 +47,17 @@ namespace Bloom::DebugServer::Gdb
void GdbRspDebugServer::init() { void GdbRspDebugServer::init() {
this->socketAddress.sin_family = AF_INET; this->socketAddress.sin_family = AF_INET;
this->socketAddress.sin_port = htons(this->debugServerConfig->listeningPortNumber); this->socketAddress.sin_port = htons(this->debugServerConfig.listeningPortNumber);
if (::inet_pton( if (::inet_pton(
AF_INET, AF_INET,
this->debugServerConfig->listeningAddress.c_str(), this->debugServerConfig.listeningAddress.c_str(),
&(this->socketAddress.sin_addr) &(this->socketAddress.sin_addr)
) == 0 ) == 0
) { ) {
// Invalid IP address // Invalid IP address
throw InvalidConfig( throw InvalidConfig(
"Invalid IP address provided in config file: (\"" + this->debugServerConfig->listeningAddress "Invalid IP address provided in config file: (\"" + this->debugServerConfig.listeningAddress
+ "\")" + "\")"
); );
} }
@@ -69,12 +68,14 @@ namespace Bloom::DebugServer::Gdb
throw Exception("Failed to create socket file descriptor."); throw Exception("Failed to create socket file descriptor.");
} }
const auto enableReuseAddressSocketOption = 1;
if (::setsockopt( if (::setsockopt(
socketFileDescriptor, socketFileDescriptor,
SOL_SOCKET, SOL_SOCKET,
SO_REUSEADDR, SO_REUSEADDR,
&(this->enableReuseAddressSocketOption), &(enableReuseAddressSocketOption),
sizeof(this->enableReuseAddressSocketOption) sizeof(enableReuseAddressSocketOption)
) < 0 ) < 0
) { ) {
Logger::error("Failed to set socket SO_REUSEADDR option."); Logger::error("Failed to set socket SO_REUSEADDR option.");
@@ -87,13 +88,13 @@ namespace Bloom::DebugServer::Gdb
) < 0 ) < 0
) { ) {
throw Exception("Failed to bind address. The selected port number (" throw Exception("Failed to bind address. The selected port number ("
+ std::to_string(this->debugServerConfig->listeningPortNumber) + ") may be in use."); + std::to_string(this->debugServerConfig.listeningPortNumber) + ") may be in use.");
} }
this->serverSocketFileDescriptor = socketFileDescriptor; this->serverSocketFileDescriptor = socketFileDescriptor;
this->epollInstance.addEntry( this->epollInstance.addEntry(
this->serverSocketFileDescriptor, this->serverSocketFileDescriptor.value(),
static_cast<std::uint16_t>(EpollEvent::READ_READY) static_cast<std::uint16_t>(EpollEvent::READ_READY)
); );
@@ -102,8 +103,8 @@ namespace Bloom::DebugServer::Gdb
static_cast<std::uint16_t>(EpollEvent::READ_READY) static_cast<std::uint16_t>(EpollEvent::READ_READY)
); );
Logger::info("GDB RSP address: " + this->debugServerConfig->listeningAddress); Logger::info("GDB RSP address: " + this->debugServerConfig.listeningAddress);
Logger::info("GDB RSP port: " + std::to_string(this->debugServerConfig->listeningPortNumber)); Logger::info("GDB RSP port: " + std::to_string(this->debugServerConfig.listeningPortNumber));
this->eventListener.registerCallbackForEventType<Events::TargetControllerStateReported>( this->eventListener.registerCallbackForEventType<Events::TargetControllerStateReported>(
std::bind(&GdbRspDebugServer::onTargetControllerStateReported, this, std::placeholders::_1) std::bind(&GdbRspDebugServer::onTargetControllerStateReported, this, std::placeholders::_1)
@@ -117,8 +118,8 @@ namespace Bloom::DebugServer::Gdb
void GdbRspDebugServer::close() { void GdbRspDebugServer::close() {
this->terminateActiveDebugSession(); this->terminateActiveDebugSession();
if (this->serverSocketFileDescriptor > 0) { if (this->serverSocketFileDescriptor.has_value()) {
::close(this->serverSocketFileDescriptor); ::close(this->serverSocketFileDescriptor.value());
} }
} }
@@ -191,7 +192,7 @@ namespace Bloom::DebugServer::Gdb
} }
std::optional<Connection> GdbRspDebugServer::waitForConnection() { std::optional<Connection> GdbRspDebugServer::waitForConnection() {
if (::listen(this->serverSocketFileDescriptor, 3) != 0) { if (::listen(this->serverSocketFileDescriptor.value(), 3) != 0) {
throw Exception("Failed to listen on server socket"); throw Exception("Failed to listen on server socket");
} }
@@ -205,7 +206,10 @@ namespace Bloom::DebugServer::Gdb
return std::nullopt; return std::nullopt;
} }
return std::make_optional<Connection>(this->serverSocketFileDescriptor, *(this->interruptEventNotifier)); return std::make_optional<Connection>(
this->serverSocketFileDescriptor.value(),
*(this->interruptEventNotifier)
);
} }
std::unique_ptr<CommandPacket> GdbRspDebugServer::waitForCommandPacket() { std::unique_ptr<CommandPacket> GdbRspDebugServer::waitForCommandPacket() {
@@ -266,12 +270,14 @@ namespace Bloom::DebugServer::Gdb
} }
void GdbRspDebugServer::terminateActiveDebugSession() { void GdbRspDebugServer::terminateActiveDebugSession() {
if (this->activeDebugSession.has_value()) { if (!this->activeDebugSession.has_value()) {
this->activeDebugSession->terminate(); return;
this->activeDebugSession = std::nullopt;
EventManager::triggerEvent(std::make_shared<Events::DebugSessionFinished>());
} }
this->activeDebugSession->terminate();
this->activeDebugSession = std::nullopt;
EventManager::triggerEvent(std::make_shared<Events::DebugSessionFinished>());
} }
void GdbRspDebugServer::onTargetControllerStateReported(const Events::TargetControllerStateReported& event) { void GdbRspDebugServer::onTargetControllerStateReported(const Events::TargetControllerStateReported& event) {

View File

@@ -25,20 +25,16 @@
#include "src/EventManager/Events/TargetControllerStateReported.hpp" #include "src/EventManager/Events/TargetControllerStateReported.hpp"
#include "src/EventManager/Events/TargetExecutionStopped.hpp" #include "src/EventManager/Events/TargetExecutionStopped.hpp"
#include "src/Helpers/BiMap.hpp"
namespace Bloom::DebugServer::Gdb namespace Bloom::DebugServer::Gdb
{ {
/** /**
* The GdbRspDebugServer is an implementation of a GDB server using the GDB Remote Serial Protocol. * The GdbRspDebugServer is an implementation of the GDB Remote Serial Protocol.
* *
* This DebugServer employs TCP/IP sockets to interface with GDB clients. The listening address can be configured * This server employs TCP/IP sockets to interface with GDB clients. The listening address and port can be
* in the user's project config file. * configured in the user's project config file.
* *
* See https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html for more info on the GDB Remote * See https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html for more info on the GDB Remote Serial
* Serial Protocol. * Protocol.
*
* @TODO: This could do with some cleaning.
*/ */
class GdbRspDebugServer: public ServerInterface class GdbRspDebugServer: public ServerInterface
{ {
@@ -48,6 +44,15 @@ namespace Bloom::DebugServer::Gdb
EventListener& eventListener EventListener& eventListener
); );
GdbRspDebugServer() = delete;
virtual ~GdbRspDebugServer() = default;
GdbRspDebugServer(const GdbRspDebugServer& other) = delete;
GdbRspDebugServer(GdbRspDebugServer&& other) = delete;
GdbRspDebugServer& operator = (const GdbRspDebugServer& other) = delete;
GdbRspDebugServer& operator = (GdbRspDebugServer&& other) = delete;
[[nodiscard]] std::string getName() const override { [[nodiscard]] std::string getName() const override {
return "GDB Remote Serial Protocol DebugServer"; return "GDB Remote Serial Protocol DebugServer";
}; };
@@ -70,24 +75,25 @@ namespace Bloom::DebugServer::Gdb
void run() override; void run() override;
protected: protected:
std::optional<GdbDebugServerConfig> debugServerConfig; /**
* User project configuration specific to the GDB RSP debug server.
*/
GdbDebugServerConfig debugServerConfig;
/**
* The DebugServerComponent's event listener.
*/
EventListener& eventListener; EventListener& eventListener;
/**
* EventNotifier object for interrupting blocking I/O operations.
*
* Extracted from this->eventListener.
*
* See documentation in src/DebugServer/README.md for more.
*/
EventNotifier* interruptEventNotifier = nullptr; EventNotifier* interruptEventNotifier = nullptr;
TargetControllerConsole targetControllerConsole = TargetControllerConsole(this->eventListener);
/**
* Listening socket address
*/
struct sockaddr_in socketAddress = {};
/**
* Listening socket file descriptor
*/
int serverSocketFileDescriptor = -1;
/** /**
* When waiting for a connection, we don't listen on the this->serverSocketFileDescriptor directly. Instead, * When waiting for a connection, we don't listen on the this->serverSocketFileDescriptor directly. Instead,
* we use an EpollInstance to monitor both this->serverSocketFileDescriptor and this->interruptEventNotifier. * we use an EpollInstance to monitor both this->serverSocketFileDescriptor and this->interruptEventNotifier.
@@ -102,9 +108,21 @@ namespace Bloom::DebugServer::Gdb
EpollInstance epollInstance = EpollInstance(); EpollInstance epollInstance = EpollInstance();
/** /**
* SO_REUSEADDR option value for listening socket. * Passed to command handlers (see CommandPacket::handle()).
*
* See documentation in src/DebugServer/Gdb/README.md for more on how GDB commands are processed.
*/ */
int enableReuseAddressSocketOption = 1; TargetControllerConsole targetControllerConsole = TargetControllerConsole(this->eventListener);
/**
* Listening socket address
*/
struct sockaddr_in socketAddress = {};
/**
* Listening socket file descriptor
*/
std::optional<int> serverSocketFileDescriptor;
/** /**
* When a connection with a GDB client is established, a new instance of the DebugSession class is created and * When a connection with a GDB client is established, a new instance of the DebugSession class is created and