2021-04-04 21:04:12 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
2022-03-27 18:32:13 +01:00
|
|
|
#include <cstdint>
|
2021-04-04 21:04:12 +01:00
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <queue>
|
2022-03-27 18:32:13 +01:00
|
|
|
#include <optional>
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-03-31 16:13:44 +01:00
|
|
|
#include "src/DebugServer/ServerInterface.hpp"
|
2022-03-19 15:16:59 +00:00
|
|
|
|
|
|
|
|
#include "GdbDebugServerConfig.hpp"
|
2022-03-27 18:32:13 +01:00
|
|
|
#include "src/EventManager/EventListener.hpp"
|
2022-03-28 01:04:14 +01:00
|
|
|
#include "src/Helpers/EpollInstance.hpp"
|
2022-04-15 22:05:50 +01:00
|
|
|
#include "src/Helpers/EventFdNotifier.hpp"
|
2022-03-27 18:32:13 +01:00
|
|
|
#include "src/TargetController/TargetControllerConsole.hpp"
|
2022-03-19 15:16:59 +00:00
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
#include "Connection.hpp"
|
2022-03-24 19:17:41 +00:00
|
|
|
#include "TargetDescriptor.hpp"
|
|
|
|
|
#include "DebugSession.hpp"
|
2021-04-04 21:04:12 +01:00
|
|
|
#include "Signal.hpp"
|
2021-12-28 00:00:45 +00:00
|
|
|
#include "RegisterDescriptor.hpp"
|
2021-04-04 21:04:12 +01:00
|
|
|
#include "Feature.hpp"
|
2022-03-27 19:43:20 +01:00
|
|
|
#include "CommandPackets/CommandPacket.hpp"
|
2022-03-19 15:17:07 +00:00
|
|
|
|
2022-04-27 21:27:59 +01:00
|
|
|
#include "src/EventManager/Events/TargetControllerStateChanged.hpp"
|
2022-03-27 18:32:13 +01:00
|
|
|
#include "src/EventManager/Events/TargetExecutionStopped.hpp"
|
2022-03-19 15:17:07 +00:00
|
|
|
|
2022-03-31 16:05:39 +01:00
|
|
|
namespace Bloom::DebugServer::Gdb
|
2021-04-04 21:04:12 +01:00
|
|
|
{
|
|
|
|
|
/**
|
2022-04-05 18:49:54 +01:00
|
|
|
* The GdbRspDebugServer is an implementation of the GDB Remote Serial Protocol.
|
2021-04-04 21:04:12 +01:00
|
|
|
*
|
2022-04-05 18:49:54 +01:00
|
|
|
* This server employs TCP/IP sockets to interface with GDB clients. The listening address and port can be
|
|
|
|
|
* configured in the user's project config file.
|
2021-04-04 21:04:12 +01:00
|
|
|
*
|
2022-04-05 18:49:54 +01:00
|
|
|
* See https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html for more info on the GDB Remote Serial
|
|
|
|
|
* Protocol.
|
2021-04-04 21:04:12 +01:00
|
|
|
*/
|
2022-03-27 18:32:13 +01:00
|
|
|
class GdbRspDebugServer: public ServerInterface
|
2021-04-04 21:04:12 +01:00
|
|
|
{
|
2021-10-06 21:12:31 +01:00
|
|
|
public:
|
2021-12-31 19:45:15 +00:00
|
|
|
explicit GdbRspDebugServer(
|
2022-03-27 18:32:13 +01:00
|
|
|
const DebugServerConfig& debugServerConfig,
|
2022-04-15 22:05:50 +01:00
|
|
|
EventListener& eventListener,
|
|
|
|
|
EventFdNotifier& eventNotifier
|
2022-03-27 18:32:13 +01:00
|
|
|
);
|
2021-10-06 21:12:31 +01:00
|
|
|
|
2022-04-05 18:49:54 +01:00
|
|
|
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;
|
|
|
|
|
|
2022-03-27 18:32:13 +01:00
|
|
|
[[nodiscard]] std::string getName() const override {
|
2021-10-06 21:12:31 +01:00
|
|
|
return "GDB Remote Serial Protocol DebugServer";
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-27 18:32:13 +01:00
|
|
|
/**
|
|
|
|
|
* Prepares the GDB server for listing on the selected address and port.
|
|
|
|
|
*/
|
|
|
|
|
void init() override;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Terminates any active debug session and closes the listening socket.
|
|
|
|
|
*/
|
|
|
|
|
void close() override;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Waits for a connection from a GDB client or services an active one.
|
|
|
|
|
*
|
|
|
|
|
* This function will return when any blocking operation is interrupted via this->interruptEventNotifier.
|
|
|
|
|
*/
|
|
|
|
|
void run() override;
|
|
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
protected:
|
2022-04-05 18:49:54 +01:00
|
|
|
/**
|
|
|
|
|
* User project configuration specific to the GDB RSP debug server.
|
|
|
|
|
*/
|
|
|
|
|
GdbDebugServerConfig debugServerConfig;
|
2022-03-27 18:32:13 +01:00
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
/**
|
2022-04-05 18:49:54 +01:00
|
|
|
* The DebugServerComponent's event listener.
|
2021-04-04 21:04:12 +01:00
|
|
|
*/
|
2022-04-05 18:49:54 +01:00
|
|
|
EventListener& eventListener;
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
/**
|
2022-04-15 22:05:50 +01:00
|
|
|
* EventFdNotifier object for interrupting blocking I/O operations.
|
2022-04-05 18:49:54 +01:00
|
|
|
*
|
|
|
|
|
* Extracted from this->eventListener.
|
|
|
|
|
*
|
|
|
|
|
* See documentation in src/DebugServer/README.md for more.
|
2021-04-04 21:04:12 +01:00
|
|
|
*/
|
2022-04-15 22:05:50 +01:00
|
|
|
EventFdNotifier& interruptEventNotifier;
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
/**
|
2022-03-29 14:54:55 +01:00
|
|
|
* 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.
|
2022-04-15 22:05:50 +01:00
|
|
|
* This allows us to interrupt any blocking socket IO calls when EventFdNotifier::notify() is called on
|
2022-03-29 14:54:55 +01:00
|
|
|
* this->interruptEventNotifier.
|
2021-04-04 21:04:12 +01:00
|
|
|
*
|
|
|
|
|
* See GdbRspDebugServer::init()
|
|
|
|
|
* See DebugServer::interruptEventNotifier
|
2022-03-29 14:54:55 +01:00
|
|
|
* See EpollInstance
|
2022-04-15 22:05:50 +01:00
|
|
|
* See EventFdNotifier
|
2021-04-04 21:04:12 +01:00
|
|
|
*/
|
2022-03-28 01:04:14 +01:00
|
|
|
EpollInstance epollInstance = EpollInstance();
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
/**
|
2022-04-05 18:49:54 +01:00
|
|
|
* Passed to command handlers (see CommandPacket::handle()).
|
|
|
|
|
*
|
|
|
|
|
* See documentation in src/DebugServer/Gdb/README.md for more on how GDB commands are processed.
|
|
|
|
|
*/
|
2022-05-01 18:57:45 +01:00
|
|
|
TargetController::TargetControllerConsole targetControllerConsole = TargetController::TargetControllerConsole();
|
2022-04-05 18:49:54 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Listening socket address
|
|
|
|
|
*/
|
|
|
|
|
struct sockaddr_in socketAddress = {};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Listening socket file descriptor
|
2021-04-04 21:04:12 +01:00
|
|
|
*/
|
2022-04-05 18:49:54 +01:00
|
|
|
std::optional<int> serverSocketFileDescriptor;
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-03-27 19:43:20 +01:00
|
|
|
/**
|
|
|
|
|
* When a connection with a GDB client is established, a new instance of the DebugSession class is created and
|
|
|
|
|
* held here. A value of std::nullopt means there is no active debug session present.
|
|
|
|
|
*/
|
2022-03-24 19:17:41 +00:00
|
|
|
std::optional<DebugSession> activeDebugSession;
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
/**
|
2022-03-24 19:17:41 +00:00
|
|
|
* Waits for a GDB client to connect on the listening socket.
|
2021-04-04 21:04:12 +01:00
|
|
|
*
|
2022-03-24 19:17:41 +00:00
|
|
|
* This function may return an std::nullopt, if the waiting was interrupted by some other event.
|
2021-04-04 21:04:12 +01:00
|
|
|
*/
|
2022-03-24 19:17:41 +00:00
|
|
|
std::optional<Connection> waitForConnection();
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-03-27 19:43:20 +01:00
|
|
|
/**
|
|
|
|
|
* Waits for a command packet from the connected GDB client.
|
|
|
|
|
*
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
std::unique_ptr<CommandPackets::CommandPacket> waitForCommandPacket();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Should construct a derived instance of the CommandPackets::CommandPacket class, from a raw packet.
|
|
|
|
|
*
|
|
|
|
|
* Derived implementations of this GDB server class can override this function to include support for more
|
|
|
|
|
* specific GDB commands. For example, the AVR GDB implementation overrides this function to support AVR
|
|
|
|
|
* specific implementations of the read and write memory GDB commands.
|
|
|
|
|
*
|
|
|
|
|
* This function should never return a nullptr. If the command is unknown, it should simply return an
|
|
|
|
|
* instance of the CommandPackets::CommandPacket base class. The handler (CommandPacket::handle()) for the base
|
|
|
|
|
* class will handle unknown packets by responding with an empty response packet (as is expected by the GDB
|
|
|
|
|
* client).
|
|
|
|
|
*
|
|
|
|
|
* @param rawPacket
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2022-10-01 21:01:37 +01:00
|
|
|
virtual std::unique_ptr<CommandPackets::CommandPacket> resolveCommandPacket(const RawPacket& rawPacket);
|
2022-03-27 19:43:20 +01:00
|
|
|
|
2022-05-14 22:38:49 +01:00
|
|
|
/**
|
|
|
|
|
* Should return a set of GDB features supported by the GDB server. Each supported feature may come with an
|
|
|
|
|
* optional value.
|
|
|
|
|
*
|
|
|
|
|
* The set of features returned by this function will be stored against the active debug session object.
|
|
|
|
|
*
|
|
|
|
|
* Derived GDB server implementations may override this function to include any features that are specific to
|
|
|
|
|
* those implementations.
|
|
|
|
|
*
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
virtual std::set<std::pair<Feature, std::optional<std::string>>> getSupportedFeatures();
|
|
|
|
|
|
2022-03-27 19:43:20 +01:00
|
|
|
/**
|
|
|
|
|
* Should return the GDB target descriptor for the connected target.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: This function returns a target descriptor specific to GDB and the target. It's not the same data
|
|
|
|
|
* struct as Targets::TargetDescriptor. But the GDB target descriptor does hold an instance to
|
|
|
|
|
* Targets::TargetDescriptor. See the Gdb::TargetDescriptor::targetDescriptor class member.
|
|
|
|
|
*
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2022-03-24 19:17:41 +00:00
|
|
|
virtual const TargetDescriptor& getGdbTargetDescriptor() = 0;
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2022-03-27 19:43:20 +01:00
|
|
|
/**
|
|
|
|
|
* Responds to any unexpected TargetController state changes.
|
|
|
|
|
*
|
|
|
|
|
* @param event
|
|
|
|
|
*/
|
2022-04-27 21:27:59 +01:00
|
|
|
void onTargetControllerStateChanged(const Events::TargetControllerStateChanged& event);
|
2021-05-30 16:53:49 +01:00
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
/**
|
|
|
|
|
* If the GDB client is currently waiting for the target execution to stop, this event handler will issue
|
|
|
|
|
* a "stop reply" packet to the client once the target execution stops.
|
|
|
|
|
*/
|
2021-06-22 14:44:00 +01:00
|
|
|
void onTargetExecutionStopped(const Events::TargetExecutionStopped&);
|
2021-04-04 21:04:12 +01:00
|
|
|
};
|
|
|
|
|
}
|