diff --git a/src/DebugServer/CMakeLists.txt b/src/DebugServer/CMakeLists.txt index b3b0c747..6b4e10bd 100755 --- a/src/DebugServer/CMakeLists.txt +++ b/src/DebugServer/CMakeLists.txt @@ -4,7 +4,6 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/DebugServerComponent.cpp # GDB RSP Server - ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/GdbRspDebugServer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/GdbDebugServerConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/Connection.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/DebugSession.cpp @@ -29,8 +28,7 @@ target_sources( # AVR GDB RSP Server ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/AvrGdbRsp.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/TargetDescriptor.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/DebugSession.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/AvrGdbTargetDescriptor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/CommandPackets/ReadRegisters.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/CommandPackets/ReadRegister.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/CommandPackets/WriteRegister.cpp diff --git a/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp b/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp index cbacf144..c63c5efc 100644 --- a/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp +++ b/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp @@ -23,6 +23,7 @@ namespace DebugServer::Gdb::AvrGdb { using namespace Exceptions; + using namespace ::Exceptions; using Targets::TargetRegisterDescriptor; using Targets::TargetRegisterType; @@ -33,33 +34,16 @@ namespace DebugServer::Gdb::AvrGdb EventListener& eventListener, EventFdNotifier& eventNotifier ) - : GdbRspDebugServer(debugServerConfig, targetDescriptor, eventListener, eventNotifier) - , gdbTargetDescriptor(targetDescriptor) + : GdbRspDebugServer( + debugServerConfig, + targetDescriptor, + AvrGdbTargetDescriptor{targetDescriptor}, + eventListener, + eventNotifier + ) {} - DebugSession* AvrGdbRsp::startDebugSession(Connection&& connection) { - this->activeDebugSession.emplace( - std::move(connection), - this->getSupportedFeatures(), - this->debugServerConfig - ); - - return &*(this->activeDebugSession); - } - - void AvrGdbRsp::endDebugSession() { - this->activeDebugSession.reset(); - } - - const Gdb::TargetDescriptor& AvrGdbRsp::getGdbTargetDescriptor() { - return this->gdbTargetDescriptor; - } - - DebugSession* AvrGdbRsp::getActiveDebugSession() { - return this->activeDebugSession.has_value() ? &*(this->activeDebugSession) : nullptr; - } - - std::unique_ptr AvrGdbRsp::resolveCommandPacket(const RawPacket& rawPacket) { + std::unique_ptr AvrGdbRsp::rawPacketToCommandPacket(const RawPacket& rawPacket) { using Gdb::CommandPackets::Monitor; using CommandPackets::ReadRegister; @@ -86,7 +70,7 @@ namespace DebugServer::Gdb::AvrGdb } if (rawPacket[1] == 'g') { - return std::make_unique(rawPacket, this->gdbTargetDescriptor); + return std::make_unique(rawPacket); } if (rawPacket[1] == 'P') { @@ -105,11 +89,11 @@ namespace DebugServer::Gdb::AvrGdb const auto rawPacketString = std::string{rawPacket.begin() + 1, rawPacket.end()}; if (rawPacketString.find("qXfer:memory-map:read::") == 0) { - return std::make_unique(rawPacket, this->gdbTargetDescriptor); + return std::make_unique(rawPacket); } if (rawPacketString.find("vFlashErase") == 0) { - return std::make_unique(rawPacket, this->gdbTargetDescriptor); + return std::make_unique(rawPacket); } if (rawPacketString.find("vFlashWrite") == 0) { @@ -117,7 +101,7 @@ namespace DebugServer::Gdb::AvrGdb } if (rawPacketString.find("vFlashDone") == 0) { - return std::make_unique(rawPacket, this->gdbTargetDescriptor); + return std::make_unique(rawPacket); } if (rawPacketString.find("vCont?") == 0) { @@ -134,7 +118,7 @@ namespace DebugServer::Gdb::AvrGdb if (this->debugServerConfig.rangeStepping) { if (rawPacketString.find("vCont;r") == 0) { - return std::make_unique(rawPacket, this->gdbTargetDescriptor); + return std::make_unique(rawPacket); } } @@ -143,15 +127,12 @@ namespace DebugServer::Gdb::AvrGdb auto monitorCommand = std::make_unique(rawPacket); if (monitorCommand->command.find("eeprom fill") == 0) { - return std::make_unique( - std::move(*(monitorCommand.release())), - this->gdbTargetDescriptor - ); + return std::make_unique(std::move(*(monitorCommand.release()))); } } } - return GdbRspDebugServer::resolveCommandPacket(rawPacket); + return nullptr; } std::set>> AvrGdbRsp::getSupportedFeatures() { @@ -174,7 +155,7 @@ namespace DebugServer::Gdb::AvrGdb Logger::debug("Target stopped at byte address: 0x" + StringService::toHex(programAddress)); - auto& activeRangeSteppingSession = this->activeDebugSession->activeRangeSteppingSession; + auto& activeRangeSteppingSession = this->debugSession->activeRangeSteppingSession; if ( activeRangeSteppingSession.has_value() @@ -186,7 +167,7 @@ namespace DebugServer::Gdb::AvrGdb * * We need to figure out why, and determine whether the stop should be reported to GDB. */ - if (this->activeDebugSession->externalBreakpointsByAddress.contains(programAddress)) { + if (this->debugSession->externalBreakpointsByAddress.contains(programAddress)) { /* * The target stopped due to an external breakpoint, set by GDB. * @@ -194,7 +175,7 @@ namespace DebugServer::Gdb::AvrGdb */ Logger::debug("Reached external breakpoint within stepping range"); - this->activeDebugSession->terminateRangeSteppingSession(this->targetControllerService); + this->debugSession->terminateRangeSteppingSession(this->targetControllerService); return GdbRspDebugServer::handleTargetStoppedGdbResponse(programAddress); } @@ -236,7 +217,7 @@ namespace DebugServer::Gdb::AvrGdb * We have to end the range stepping session and report the stop to GDB. */ Logger::debug("Target stopped within stepping range, but for an unknown reason"); - this->activeDebugSession->terminateRangeSteppingSession(this->targetControllerService); + this->debugSession->terminateRangeSteppingSession(this->targetControllerService); } // Report the stop to GDB diff --git a/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.hpp b/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.hpp index 3401c1aa..2d76708b 100644 --- a/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.hpp +++ b/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.hpp @@ -2,14 +2,14 @@ #include -#include "TargetDescriptor.hpp" -#include "DebugSession.hpp" +#include "AvrGdbTargetDescriptor.hpp" +#include "CommandPackets/CommandPacket.hpp" #include "src/DebugServer/Gdb/GdbRspDebugServer.hpp" namespace DebugServer::Gdb::AvrGdb { - class AvrGdbRsp: public GdbRspDebugServer + class AvrGdbRsp: public GdbRspDebugServer { public: AvrGdbRsp( @@ -24,37 +24,8 @@ namespace DebugServer::Gdb::AvrGdb } protected: - DebugSession* startDebugSession(Connection&& connection) override; - - void endDebugSession() override; - - const Gdb::TargetDescriptor& getGdbTargetDescriptor() override; - - DebugSession* getActiveDebugSession() override; - - std::unique_ptr resolveCommandPacket( - const RawPacket& rawPacket - ) override; - - /** - * Should return a set of GDB features supported by the AVR 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. - * - * @return - */ - std::set>> getSupportedFeatures(); - + std::unique_ptr rawPacketToCommandPacket(const RawPacket& rawPacket) override; + std::set>> getSupportedFeatures() override; void handleTargetStoppedGdbResponse(Targets::TargetMemoryAddress programAddress) override; - - private: - TargetDescriptor gdbTargetDescriptor; - - /** - * 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. - */ - std::optional activeDebugSession; }; } diff --git a/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.cpp b/src/DebugServer/Gdb/AvrGdb/AvrGdbTargetDescriptor.cpp similarity index 71% rename from src/DebugServer/Gdb/AvrGdb/TargetDescriptor.cpp rename to src/DebugServer/Gdb/AvrGdb/AvrGdbTargetDescriptor.cpp index 4c3b80e4..5d935872 100644 --- a/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.cpp +++ b/src/DebugServer/Gdb/AvrGdb/AvrGdbTargetDescriptor.cpp @@ -1,4 +1,4 @@ -#include "TargetDescriptor.hpp" +#include "AvrGdbTargetDescriptor.hpp" #include "src/Exceptions/Exception.hpp" @@ -9,7 +9,7 @@ namespace DebugServer::Gdb::AvrGdb using Exceptions::Exception; - TargetDescriptor::TargetDescriptor(const Targets::TargetDescriptor& targetDescriptor) + AvrGdbTargetDescriptor::AvrGdbTargetDescriptor(const Targets::TargetDescriptor& targetDescriptor) : programAddressSpaceDescriptor(targetDescriptor.getAddressSpaceDescriptor("prog")) , eepromAddressSpaceDescriptor(targetDescriptor.getFirstAddressSpaceDescriptorContainingMemorySegment("internal_eeprom")) , sramAddressSpaceDescriptor(targetDescriptor.getAddressSpaceDescriptor("data")) @@ -45,11 +45,11 @@ namespace DebugServer::Gdb::AvrGdb } this->gdbRegisterDescriptorsById.emplace( - TargetDescriptor::STATUS_GDB_REGISTER_ID, - RegisterDescriptor{TargetDescriptor::STATUS_GDB_REGISTER_ID, 1} + AvrGdbTargetDescriptor::STATUS_GDB_REGISTER_ID, + RegisterDescriptor{AvrGdbTargetDescriptor::STATUS_GDB_REGISTER_ID, 1} ); this->targetRegisterDescriptorsByGdbId.emplace( - TargetDescriptor::STATUS_GDB_REGISTER_ID, + AvrGdbTargetDescriptor::STATUS_GDB_REGISTER_ID, &(targetDescriptor.getPeripheralDescriptor("cpu").getRegisterGroupDescriptor("cpu") .getRegisterDescriptor("sreg")) ); @@ -60,45 +60,45 @@ namespace DebugServer::Gdb::AvrGdb * CommandPackets::WriteRegister, etc for more. */ this->gdbRegisterDescriptorsById.emplace( - TargetDescriptor::STACK_POINTER_GDB_REGISTER_ID, - RegisterDescriptor{TargetDescriptor::STACK_POINTER_GDB_REGISTER_ID, 2} + AvrGdbTargetDescriptor::STACK_POINTER_GDB_REGISTER_ID, + RegisterDescriptor{AvrGdbTargetDescriptor::STACK_POINTER_GDB_REGISTER_ID, 2} ); this->gdbRegisterDescriptorsById.emplace( - TargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID, - RegisterDescriptor{TargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID, 4} + AvrGdbTargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID, + RegisterDescriptor{AvrGdbTargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID, 4} ); } - const Targets::TargetAddressSpaceDescriptor& TargetDescriptor::addressSpaceDescriptorFromGdbAddress( + const Targets::TargetAddressSpaceDescriptor& AvrGdbTargetDescriptor::addressSpaceDescriptorFromGdbAddress( GdbMemoryAddress address ) const { - if ((address & TargetDescriptor::EEPROM_ADDRESS_MASK) == TargetDescriptor::EEPROM_ADDRESS_MASK) { + if ((address & AvrGdbTargetDescriptor::EEPROM_ADDRESS_MASK) == AvrGdbTargetDescriptor::EEPROM_ADDRESS_MASK) { return this->eepromAddressSpaceDescriptor; } - if ((address & TargetDescriptor::SRAM_ADDRESS_MASK) == TargetDescriptor::SRAM_ADDRESS_MASK) { + if ((address & AvrGdbTargetDescriptor::SRAM_ADDRESS_MASK) == AvrGdbTargetDescriptor::SRAM_ADDRESS_MASK) { return this->sramAddressSpaceDescriptor; } return this->programAddressSpaceDescriptor; } - Targets::TargetMemoryAddress TargetDescriptor::translateGdbAddress(GdbMemoryAddress address) const { - if ((address & TargetDescriptor::EEPROM_ADDRESS_MASK) == TargetDescriptor::EEPROM_ADDRESS_MASK) { + Targets::TargetMemoryAddress AvrGdbTargetDescriptor::translateGdbAddress(GdbMemoryAddress address) const { + if ((address & AvrGdbTargetDescriptor::EEPROM_ADDRESS_MASK) == AvrGdbTargetDescriptor::EEPROM_ADDRESS_MASK) { // GDB sends EEPROM addresses in relative form - convert them to absolute form. return this->eepromMemorySegmentDescriptor.addressRange.startAddress - + (address & ~(TargetDescriptor::EEPROM_ADDRESS_MASK)); + + (address & ~(AvrGdbTargetDescriptor::EEPROM_ADDRESS_MASK)); } - if ((address & TargetDescriptor::SRAM_ADDRESS_MASK) == TargetDescriptor::SRAM_ADDRESS_MASK) { - return address & ~(TargetDescriptor::SRAM_ADDRESS_MASK); + if ((address & AvrGdbTargetDescriptor::SRAM_ADDRESS_MASK) == AvrGdbTargetDescriptor::SRAM_ADDRESS_MASK) { + return address & ~(AvrGdbTargetDescriptor::SRAM_ADDRESS_MASK); } return address; } - GdbMemoryAddress TargetDescriptor::translateTargetMemoryAddress( + GdbMemoryAddress AvrGdbTargetDescriptor::translateTargetMemoryAddress( Targets::TargetMemoryAddress address, const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor, const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor @@ -110,10 +110,10 @@ namespace DebugServer::Gdb::AvrGdb if (memorySegmentDescriptor.type == Targets::TargetMemorySegmentType::EEPROM) { // GDB expects EEPROM addresses in relative form return (address - memorySegmentDescriptor.addressRange.startAddress) - | TargetDescriptor::EEPROM_ADDRESS_MASK; + | AvrGdbTargetDescriptor::EEPROM_ADDRESS_MASK; } // We assume everything else is SRAM - return address | TargetDescriptor::SRAM_ADDRESS_MASK; + return address | AvrGdbTargetDescriptor::SRAM_ADDRESS_MASK; } } diff --git a/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp b/src/DebugServer/Gdb/AvrGdb/AvrGdbTargetDescriptor.hpp similarity index 92% rename from src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp rename to src/DebugServer/Gdb/AvrGdb/AvrGdbTargetDescriptor.hpp index b6af786b..c3c9a865 100644 --- a/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp +++ b/src/DebugServer/Gdb/AvrGdb/AvrGdbTargetDescriptor.hpp @@ -10,7 +10,7 @@ namespace DebugServer::Gdb::AvrGdb { - class TargetDescriptor: public DebugServer::Gdb::TargetDescriptor + class AvrGdbTargetDescriptor: public DebugServer::Gdb::TargetDescriptor { public: static constexpr auto SRAM_ADDRESS_MASK = 0x00800000U; @@ -33,7 +33,7 @@ namespace DebugServer::Gdb::AvrGdb const Targets::TargetPeripheralDescriptor& cpuGpPeripheralDescriptor; const Targets::TargetRegisterGroupDescriptor& cpuGpRegisterGroupDescriptor; - explicit TargetDescriptor(const Targets::TargetDescriptor& targetDescriptor); + explicit AvrGdbTargetDescriptor(const Targets::TargetDescriptor& targetDescriptor); const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptorFromGdbAddress( GdbMemoryAddress address diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/CommandPacket.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/CommandPacket.hpp new file mode 100644 index 00000000..189dc733 --- /dev/null +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/CommandPacket.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "src/DebugServer/Gdb/DebugSession.hpp" +#include "src/DebugServer/Gdb/AvrGdb/AvrGdbTargetDescriptor.hpp" +#include "src/Targets/TargetDescriptor.hpp" +#include "src/Services/TargetControllerService.hpp" + +namespace DebugServer::Gdb::AvrGdb::CommandPackets +{ + class CommandPacket: public Gdb::CommandPackets::CommandPacket + { + public: + explicit CommandPacket(const RawPacket& rawPacket) + : Gdb::CommandPackets::CommandPacket(rawPacket) + {} + + explicit CommandPacket(const Gdb::CommandPackets::CommandPacket& commandPacket) + : Gdb::CommandPackets::CommandPacket(commandPacket) + {} + + virtual ~CommandPacket() = default; + + /** + * Should handle the command for the current active debug session. + * + * @param debugSession + * The current active debug session. + * + * @param TargetControllerService + */ + virtual void handle( + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, + const Targets::TargetDescriptor& targetDescriptor, + Services::TargetControllerService& targetControllerService + ) = 0; + }; +} diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp index 6e53daf3..b6b2c6c2 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp @@ -23,33 +23,31 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using ::Exceptions::Exception; using Exceptions::InvalidCommandOption; - EepromFill::EepromFill(Monitor&& monitorPacket, const TargetDescriptor& gdbTargetDescriptor) - : Monitor(std::move(monitorPacket)) - , eepromAddressSpaceDescriptor(gdbTargetDescriptor.eepromAddressSpaceDescriptor) - , eepromMemorySegmentDescriptor(gdbTargetDescriptor.eepromMemorySegmentDescriptor) + EepromFill::EepromFill(Gdb::CommandPackets::Monitor&& monitorPacket) + : CommandPacket(monitorPacket) + , rawFillValue(monitorPacket.commandArguments.size() >= 3 ? monitorPacket.commandArguments[2] : std::string{}) {} void EepromFill::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { Logger::info("Handling EepromFill packet"); try { - if (this->commandArguments.size() < 3 || this->commandArguments[2].empty()) { + if (this->rawFillValue.empty()) { throw InvalidCommandOption{"Fill value required"}; } - const auto eepromSize = this->eepromMemorySegmentDescriptor.size(); - const auto& rawFillValue = this->commandArguments[2]; + const auto eepromSize = gdbTargetDescriptor.eepromMemorySegmentDescriptor.size(); const auto fillValue = Services::StringService::dataFromHex( - rawFillValue.size() >= 3 && rawFillValue[0] == '0' - && (rawFillValue[1] == 'X' || rawFillValue[1] == 'x') - ? rawFillValue.substr(2) - : rawFillValue + this->rawFillValue.size() >= 3 && this->rawFillValue[0] == '0' + && (this->rawFillValue[1] == 'X' || this->rawFillValue[1] == 'x') + ? this->rawFillValue.substr(2) + : this->rawFillValue ); const auto fillValueSize = fillValue.size(); @@ -87,9 +85,9 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets Logger::debug("Filling EEPROM with values: " + hexValues); targetControllerService.writeMemory( - this->eepromAddressSpaceDescriptor, - this->eepromMemorySegmentDescriptor, - this->eepromMemorySegmentDescriptor.addressRange.startAddress, + gdbTargetDescriptor.eepromAddressSpaceDescriptor, + gdbTargetDescriptor.eepromMemorySegmentDescriptor, + gdbTargetDescriptor.eepromMemorySegmentDescriptor.addressRange.startAddress, std::move(data) ); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp index 727733c8..8aed0253 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp @@ -1,14 +1,12 @@ #pragma once #include +#include + +#include "CommandPacket.hpp" #include "src/DebugServer/Gdb/CommandPackets/Monitor.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" - -#include "src/Targets/TargetAddressSpaceDescriptor.hpp" -#include "src/Targets/TargetMemorySegmentDescriptor.hpp" - namespace DebugServer::Gdb::AvrGdb::CommandPackets { /** @@ -16,17 +14,16 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * * This command fills the target's EEPROM with the given value. */ - class EepromFill: public Gdb::CommandPackets::Monitor + class EepromFill: public CommandPackets::CommandPacket { public: - const Targets::TargetAddressSpaceDescriptor& eepromAddressSpaceDescriptor; - const Targets::TargetMemorySegmentDescriptor& eepromMemorySegmentDescriptor; + std::string rawFillValue; - explicit EepromFill(Monitor&& monitorPacket, const TargetDescriptor& gdbTargetDescriptor); + explicit EepromFill(Gdb::CommandPackets::Monitor&& monitorPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp index 8f409901..bc78d8f1 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp @@ -15,15 +15,13 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using namespace Exceptions; - FlashDone::FlashDone(const RawPacket& rawPacket, const TargetDescriptor& targetDescriptor) + FlashDone::FlashDone(const RawPacket& rawPacket) : CommandPacket(rawPacket) - , programMemoryAddressSpaceDescriptor(targetDescriptor.programAddressSpaceDescriptor) - , programMemorySegmentDescriptor(targetDescriptor.programMemorySegmentDescriptor) {} void FlashDone::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -42,8 +40,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets targetControllerService.enableProgrammingMode(); targetControllerService.writeMemory( - this->programMemoryAddressSpaceDescriptor, - this->programMemorySegmentDescriptor, + gdbTargetDescriptor.programAddressSpaceDescriptor, + gdbTargetDescriptor.programMemorySegmentDescriptor, debugSession.programmingSession->startAddress, std::move(debugSession.programmingSession->buffer) ); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp index ee5827f0..222c5b03 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp @@ -3,28 +3,21 @@ #include #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" - -#include "src/Targets/TargetAddressSpaceDescriptor.hpp" -#include "src/Targets/TargetMemorySegmentDescriptor.hpp" +#include "CommandPacket.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { /** * The FlashDone class implements the structure for the "vFlashDone" packet. */ - class FlashDone: public Gdb::CommandPackets::CommandPacket + class FlashDone: public CommandPackets::CommandPacket { public: - const Targets::TargetAddressSpaceDescriptor& programMemoryAddressSpaceDescriptor; - const Targets::TargetMemorySegmentDescriptor& programMemorySegmentDescriptor; - - explicit FlashDone(const RawPacket& rawPacket, const TargetDescriptor& targetDescriptor); + explicit FlashDone(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp index 6b326fda..1d071a48 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp @@ -16,10 +16,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using namespace Exceptions; - FlashErase::FlashErase(const RawPacket& rawPacket, const TargetDescriptor& targetDescriptor) + FlashErase::FlashErase(const RawPacket& rawPacket) : CommandPacket(rawPacket) - , programMemoryAddressSpaceDescriptor(targetDescriptor.programAddressSpaceDescriptor) - , programMemorySegmentDescriptor(targetDescriptor.programMemorySegmentDescriptor) { using Services::StringService; @@ -45,8 +43,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets } void FlashErase::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -59,8 +57,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets // We don't erase a specific address range - we just erase the entire program memory. targetControllerService.eraseMemory( - this->programMemoryAddressSpaceDescriptor, - this->programMemorySegmentDescriptor + gdbTargetDescriptor.programAddressSpaceDescriptor, + gdbTargetDescriptor.programMemorySegmentDescriptor ); debugSession.connection.writePacket(OkResponsePacket{}); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp index 07b6c60f..27b7108b 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp @@ -3,11 +3,7 @@ #include #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" - -#include "src/Targets/TargetAddressSpaceDescriptor.hpp" -#include "src/Targets/TargetMemorySegmentDescriptor.hpp" +#include "CommandPacket.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { @@ -15,19 +11,17 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The FlashErase class implements the structure for the "vFlashErase" packet. Upon receiving this packet, the * server is expected to erase a particular region of the target's flash memory. */ - class FlashErase: public Gdb::CommandPackets::CommandPacket + class FlashErase: public CommandPackets::CommandPacket { public: std::uint32_t startAddress = 0; std::uint32_t bytes = 0; - const Targets::TargetAddressSpaceDescriptor& programMemoryAddressSpaceDescriptor; - const Targets::TargetMemorySegmentDescriptor& programMemorySegmentDescriptor; - explicit FlashErase(const RawPacket& rawPacket, const TargetDescriptor& targetDescriptor); + explicit FlashErase(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp index 4b1a6314..3f2a1d88 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp @@ -40,8 +40,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets } void FlashWrite::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp index 3cc25e4b..9ae1db78 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp @@ -3,8 +3,7 @@ #include #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" -#include "src/DebugServer/Gdb/TargetDescriptor.hpp" +#include "CommandPacket.hpp" #include "src/Targets/TargetMemory.hpp" @@ -14,17 +13,17 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The FlashWrite class implements the structure for the "vFlashWrite" packet. Upon receiving this packet, the * server is expected to write to a particular region of the target's flash memory. */ - class FlashWrite: public Gdb::CommandPackets::CommandPacket + class FlashWrite: public CommandPackets::CommandPacket { public: - std::uint32_t startAddress = 0; + Targets::TargetMemoryAddress startAddress; Targets::TargetMemoryBuffer buffer; explicit FlashWrite(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp index 2f735bc8..ee0e2b2f 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp @@ -19,13 +19,13 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using Exceptions::Exception; - ReadMemory::ReadMemory(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor) + ReadMemory::ReadMemory(const RawPacket& rawPacket, const AvrGdbTargetDescriptor& gdbTargetDescriptor) : ReadMemory(rawPacket, gdbTargetDescriptor, ReadMemory::extractPacketData(rawPacket)) {} void ReadMemory::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -147,7 +147,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets ReadMemory::ReadMemory( const RawPacket& rawPacket, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, ReadMemory::PacketData&& packetData ) : CommandPacket(rawPacket) diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp index cb963b34..2291c49f 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp @@ -3,11 +3,10 @@ #include #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" #include "src/Targets/TargetAddressSpaceDescriptor.hpp" #include "src/Targets/TargetMemory.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { @@ -15,7 +14,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The ReadMemory class implements a structure for "m" packets. Upon receiving these packets, the server is * expected to read memory from the target and send it the client. */ - class ReadMemory: public Gdb::CommandPackets::CommandPacket + class ReadMemory: public CommandPackets::CommandPacket { public: const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor; @@ -23,11 +22,11 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets Targets::TargetMemoryAddress startAddress; Targets::TargetMemorySize bytes; - ReadMemory(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor); + ReadMemory(const RawPacket& rawPacket, const AvrGdbTargetDescriptor& gdbTargetDescriptor); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; @@ -42,7 +41,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets static PacketData extractPacketData(const RawPacket& rawPacket); ReadMemory( const RawPacket& rawPacket, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, PacketData&& packetData ); }; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp index db76d7b9..bb213b16 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp @@ -13,11 +13,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using Exceptions::Exception; - ReadMemoryMap::ReadMemoryMap(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor) + ReadMemoryMap::ReadMemoryMap(const RawPacket& rawPacket) : CommandPacket(rawPacket) - , eepromAddressSpaceDescriptor(gdbTargetDescriptor.eepromAddressSpaceDescriptor) - , programMemorySegmentDescriptor(gdbTargetDescriptor.programMemorySegmentDescriptor) - , eepromMemorySegmentDescriptor(gdbTargetDescriptor.eepromMemorySegmentDescriptor) { using Services::StringService; @@ -41,8 +38,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets } void ReadMemoryMap::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -53,18 +50,18 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * data via memory read/write packets. */ const auto ramSectionEndAddress = gdbTargetDescriptor.translateTargetMemoryAddress( - this->eepromMemorySegmentDescriptor.addressRange.endAddress, - this->eepromAddressSpaceDescriptor, - this->eepromMemorySegmentDescriptor + gdbTargetDescriptor.eepromMemorySegmentDescriptor.addressRange.endAddress, + gdbTargetDescriptor.eepromAddressSpaceDescriptor, + gdbTargetDescriptor.eepromMemorySegmentDescriptor ); - const auto ramSectionStartAddress = TargetDescriptor::SRAM_ADDRESS_MASK; + const auto ramSectionStartAddress = AvrGdbTargetDescriptor::SRAM_ADDRESS_MASK; const auto ramSectionSize = ramSectionEndAddress - ramSectionStartAddress + 1; const auto memoryMap = std::string{""} + "" - + "programMemorySegmentDescriptor.size()) + "\">" - + "" + std::to_string(this->programMemorySegmentDescriptor.pageSize.value()) + "" + + "" + + "" + std::to_string(gdbTargetDescriptor.programMemorySegmentDescriptor.pageSize.value()) + "" + "" + ""; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.hpp index 37142a51..ea4349d8 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.hpp @@ -2,11 +2,7 @@ #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" - -#include "src/Targets/TargetAddressSpaceDescriptor.hpp" -#include "src/Targets/TargetMemorySegmentDescriptor.hpp" +#include "CommandPacket.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { @@ -14,13 +10,9 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The ReadMemoryMap class implements a structure for the "qXfer:memory-map:read::..." packet. Upon receiving this * packet, the server is expected to respond with the target's memory map. */ - class ReadMemoryMap: public Gdb::CommandPackets::CommandPacket + class ReadMemoryMap: public CommandPackets::CommandPacket { public: - const Targets::TargetAddressSpaceDescriptor& eepromAddressSpaceDescriptor; - const Targets::TargetMemorySegmentDescriptor& programMemorySegmentDescriptor; - const Targets::TargetMemorySegmentDescriptor& eepromMemorySegmentDescriptor; - /** * The offset of the memory map, from which to read. */ @@ -31,11 +23,11 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets */ std::uint32_t length = 0; - explicit ReadMemoryMap(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor); + explicit ReadMemoryMap(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.cpp index 6af225ea..9a40ff56 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.cpp @@ -4,7 +4,6 @@ #include "src/Targets/TargetRegisterDescriptor.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" #include "src/Services/StringService.hpp" #include "src/Logger/Logger.hpp" @@ -36,8 +35,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets } void ReadRegister::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -46,7 +45,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets try { Logger::debug("Reading GDB register ID: " + std::to_string(this->registerId)); - if (this->registerId == TargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID) { + if (this->registerId == AvrGdbTargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID) { /* * GDB has requested the program counter. We can't access this in the same way as we do with other * registers. @@ -65,7 +64,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets return; } - if (this->registerId == TargetDescriptor::STACK_POINTER_GDB_REGISTER_ID) { + if (this->registerId == AvrGdbTargetDescriptor::STACK_POINTER_GDB_REGISTER_ID) { /* * GDB has requested the program counter. We can't access this in the same way as we do with other * registers. diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.hpp index 8ed00f59..d335ae8b 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegister.hpp @@ -1,6 +1,6 @@ #pragma once -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" #include "src/DebugServer/Gdb/RegisterDescriptor.hpp" @@ -10,7 +10,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The ReadRegister class implements a structure for the "p" command packet. In response to this packet, the server * is expected to send register values for the requested register. */ - class ReadRegister: public Gdb::CommandPackets::CommandPacket + class ReadRegister: public CommandPackets::CommandPacket { public: GdbRegisterId registerId; @@ -18,8 +18,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets explicit ReadRegister(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.cpp index b60b48c5..fc48f272 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.cpp @@ -22,14 +22,13 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using Exceptions::Exception; - ReadRegisters::ReadRegisters(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor) + ReadRegisters::ReadRegisters(const RawPacket& rawPacket) : CommandPacket(rawPacket) - , gpRegistersMemorySegmentDescriptor(gdbTargetDescriptor.gpRegistersMemorySegmentDescriptor) {} void ReadRegisters::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -60,7 +59,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets } const auto bufferOffset = regDesc.startAddress - - this->gpRegistersMemorySegmentDescriptor.addressRange.startAddress; + - gdbTargetDescriptor.gpRegistersMemorySegmentDescriptor.addressRange.startAddress; assert((buffer.size() - bufferOffset) >= regVal.size()); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.hpp index 0a1834c7..7e1e4650 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadRegisters.hpp @@ -2,11 +2,9 @@ #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" #include "src/DebugServer/Gdb/RegisterDescriptor.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" -#include "src/Targets/TargetMemorySegmentDescriptor.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { @@ -14,16 +12,14 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The ReadRegisters class implements a structure for the "g" command packet. In response to this packet, the * server is expected to send register values for all registers. */ - class ReadRegisters: public Gdb::CommandPackets::CommandPacket + class ReadRegisters: public CommandPackets::CommandPacket { public: - const Targets::TargetMemorySegmentDescriptor& gpRegistersMemorySegmentDescriptor; - - explicit ReadRegisters(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor); + explicit ReadRegisters(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.cpp index ddc64c4b..8be68342 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.cpp @@ -15,8 +15,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets {} void VContContinueExecution::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.hpp index e22a8293..4dfe9886 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContContinueExecution.hpp @@ -2,7 +2,7 @@ #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { @@ -10,14 +10,14 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The VContContinueExecution class implements a structure for "vCont;c" and "vCont;C" packets. These packets * instruct the server to continue execution on the target. */ - class VContContinueExecution: public Gdb::CommandPackets::CommandPacket + class VContContinueExecution: public CommandPackets::CommandPacket { public: explicit VContContinueExecution(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.cpp index 57a3f056..284858b0 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.cpp @@ -17,10 +17,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using ResponsePackets::ErrorResponsePacket; using ::Exceptions::Exception; - VContRangeStep::VContRangeStep(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor) + VContRangeStep::VContRangeStep(const RawPacket& rawPacket) : CommandPacket(rawPacket) - , programAddressSpaceDescriptor(gdbTargetDescriptor.programAddressSpaceDescriptor) - , programMemorySegmentDescriptor(gdbTargetDescriptor.programMemorySegmentDescriptor) { using Services::StringService; @@ -44,8 +42,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets } void VContRangeStep::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -61,7 +59,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets try { const auto stepAddressRange = Targets::TargetMemoryAddressRange{this->startAddress, this->endAddress}; const auto stepByteSize = stepAddressRange.size() - 1; // -1 because the end address is exclusive - const auto& programMemoryAddressRange = this->programMemorySegmentDescriptor.addressRange; + const auto& programMemoryAddressRange = gdbTargetDescriptor.programMemorySegmentDescriptor.addressRange; if ( stepAddressRange.startAddress > stepAddressRange.endAddress @@ -91,8 +89,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets const auto instructionsByAddress = Decoder::decode( stepAddressRange.startAddress, targetControllerService.readMemory( - this->programAddressSpaceDescriptor, - this->programMemorySegmentDescriptor, + gdbTargetDescriptor.programAddressSpaceDescriptor, + gdbTargetDescriptor.programMemorySegmentDescriptor, stepAddressRange.startAddress, stepByteSize ) diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.hpp index 9d4d33fd..5fa3d4f4 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContRangeStep.hpp @@ -2,11 +2,8 @@ #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" -#include "src/Targets/TargetAddressSpaceDescriptor.hpp" -#include "src/Targets/TargetMemorySegmentDescriptor.hpp" #include "src/Targets/TargetMemory.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets @@ -16,20 +13,17 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * step through a particular address range, and only report back to GDB when execution leaves that range, or when an * external breakpoint has been reached. */ - class VContRangeStep: public Gdb::CommandPackets::CommandPacket + class VContRangeStep: public CommandPackets::CommandPacket { public: - const Targets::TargetAddressSpaceDescriptor& programAddressSpaceDescriptor; - const Targets::TargetMemorySegmentDescriptor& programMemorySegmentDescriptor; - Targets::TargetMemoryAddress startAddress; Targets::TargetMemoryAddress endAddress; - explicit VContRangeStep(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor); + explicit VContRangeStep(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.cpp index 5bec8d36..85508af5 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.cpp @@ -15,8 +15,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets {} void VContStepExecution::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.hpp index 5ee96fa7..247d75c6 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContStepExecution.hpp @@ -2,21 +2,21 @@ #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { /** * The VContStepExecution class implements a structure for "vCont;s" and "vCont;S" packets. */ - class VContStepExecution: public Gdb::CommandPackets::CommandPacket + class VContStepExecution: public CommandPackets::CommandPacket { public: explicit VContStepExecution(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.cpp index 7d6ddaf6..07b1b9d7 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.cpp @@ -13,8 +13,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets {} void VContSupportedActionsQuery::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.hpp index 4cda486c..6f6b69b3 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/VContSupportedActionsQuery.hpp @@ -3,7 +3,7 @@ #include #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { @@ -13,14 +13,14 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * * Responses to this command packet should take the form of a ResponsePackets::SupportedFeaturesResponse. */ - class VContSupportedActionsQuery: public Gdb::CommandPackets::CommandPacket + class VContSupportedActionsQuery: public CommandPackets::CommandPacket { public: explicit VContSupportedActionsQuery(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp index 694e80d0..c9c595f6 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp @@ -16,13 +16,13 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets using namespace Exceptions; - WriteMemory::WriteMemory(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor) + WriteMemory::WriteMemory(const RawPacket& rawPacket, const AvrGdbTargetDescriptor& gdbTargetDescriptor) : WriteMemory(rawPacket, gdbTargetDescriptor, WriteMemory::extractPacketData(rawPacket)) {} void WriteMemory::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { @@ -116,7 +116,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets WriteMemory::WriteMemory( const RawPacket& rawPacket, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, PacketData&& packetData ) : CommandPacket(rawPacket) diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp index 1fea029b..4f004f8f 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp @@ -3,11 +3,10 @@ #include #include -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" #include "src/Targets/TargetAddressSpaceDescriptor.hpp" #include "src/Targets/TargetMemory.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" namespace DebugServer::Gdb::AvrGdb::CommandPackets { @@ -15,7 +14,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets * The WriteMemory class implements the structure for "M" packets. Upon receiving this packet, the server is * expected to write data to the target's memory, at the specified start address. */ - class WriteMemory: public Gdb::CommandPackets::CommandPacket + class WriteMemory: public CommandPackets::CommandPacket { public: const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor; @@ -23,11 +22,11 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets Targets::TargetMemorySize bytes; Targets::TargetMemoryBuffer buffer; - explicit WriteMemory(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor); + explicit WriteMemory(const RawPacket& rawPacket, const AvrGdbTargetDescriptor& gdbTargetDescriptor); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; @@ -41,6 +40,6 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets }; static PacketData extractPacketData(const RawPacket& rawPacket); - WriteMemory(const RawPacket& rawPacket, const Gdb::TargetDescriptor& gdbTargetDescriptor, PacketData&& packetData); + WriteMemory(const RawPacket& rawPacket, const AvrGdbTargetDescriptor& gdbTargetDescriptor, PacketData&& packetData); }; } diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.cpp index aa022c9d..b7100d47 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.cpp @@ -46,15 +46,15 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets } void WriteRegister::handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, TargetControllerService& targetControllerService ) { Logger::info("Handling WriteRegister packet"); try { - if (this->registerId == TargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID) { + if (this->registerId == AvrGdbTargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID) { if (this->registerValue.size() != 4) { throw Exception{"Invalid PC value register size"}; } @@ -72,7 +72,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets return; } - if (this->registerId == TargetDescriptor::STACK_POINTER_GDB_REGISTER_ID) { + if (this->registerId == AvrGdbTargetDescriptor::STACK_POINTER_GDB_REGISTER_ID) { if (this->registerValue.size() != 2) { throw Exception{"Invalid SP register value size"}; } diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.hpp index 506e575f..4db48e32 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteRegister.hpp @@ -1,9 +1,8 @@ #pragma once -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "CommandPacket.hpp" #include "src/DebugServer/Gdb/RegisterDescriptor.hpp" -#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp" #include "src/Targets/TargetMemory.hpp" @@ -12,7 +11,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets /** * The WriteRegister class implements the structure for "P" packets. */ - class WriteRegister: public Gdb::CommandPackets::CommandPacket + class WriteRegister: public CommandPackets::CommandPacket { public: GdbRegisterId registerId; @@ -21,8 +20,8 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets explicit WriteRegister(const RawPacket& rawPacket); void handle( - Gdb::DebugSession& debugSession, - const Gdb::TargetDescriptor& gdbTargetDescriptor, + DebugSession& debugSession, + const AvrGdbTargetDescriptor& gdbTargetDescriptor, const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; diff --git a/src/DebugServer/Gdb/AvrGdb/DebugSession.cpp b/src/DebugServer/Gdb/AvrGdb/DebugSession.cpp deleted file mode 100644 index cf08d8f1..00000000 --- a/src/DebugServer/Gdb/AvrGdb/DebugSession.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "DebugSession.hpp" - -namespace DebugServer::Gdb::AvrGdb -{ - DebugSession::DebugSession( - Connection&& connection, - const std::set>>& supportedFeatures, - const GdbDebugServerConfig& serverConfig - ) - : Gdb::DebugSession(std::move(connection), supportedFeatures, serverConfig) - {} -} diff --git a/src/DebugServer/Gdb/AvrGdb/DebugSession.hpp b/src/DebugServer/Gdb/AvrGdb/DebugSession.hpp deleted file mode 100644 index 1d6418f4..00000000 --- a/src/DebugServer/Gdb/AvrGdb/DebugSession.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "src/DebugServer/Gdb/DebugSession.hpp" - -#include "TargetDescriptor.hpp" - -namespace DebugServer::Gdb::AvrGdb -{ - class DebugSession final: public Gdb::DebugSession - { - public: - DebugSession( - Connection&& connection, - const std::set>>& supportedFeatures, - const GdbDebugServerConfig& serverConfig - ); - }; -} diff --git a/src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp b/src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp index 0fbcff0a..366d0680 100644 --- a/src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp +++ b/src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp @@ -14,6 +14,8 @@ namespace DebugServer::Gdb::CommandPackets public: explicit CommandPacket(const RawPacket& rawPacket); + virtual ~CommandPacket() = default; + /** * Should handle the command for the current active debug session. * diff --git a/src/DebugServer/Gdb/DebugSession.hpp b/src/DebugServer/Gdb/DebugSession.hpp index 321461e6..52c288fc 100644 --- a/src/DebugServer/Gdb/DebugSession.hpp +++ b/src/DebugServer/Gdb/DebugSession.hpp @@ -34,6 +34,9 @@ namespace DebugServer::Gdb /** * The current server configuration. + * + * TODO: I think this should be moved out of the DebugSession struct and passed into CommandPacket::handle() + * function. Review after v1.1.0. */ const GdbDebugServerConfig& serverConfig; diff --git a/src/DebugServer/Gdb/GdbRspDebugServer.cpp b/src/DebugServer/Gdb/GdbRspDebugServer.cpp deleted file mode 100644 index ef47d8b5..00000000 --- a/src/DebugServer/Gdb/GdbRspDebugServer.cpp +++ /dev/null @@ -1,397 +0,0 @@ -#include "GdbRspDebugServer.hpp" - -#include -#include - -#include "src/EventManager/EventManager.hpp" -#include "src/Logger/Logger.hpp" - -#include "Exceptions/ClientDisconnected.hpp" -#include "Exceptions/ClientNotSupported.hpp" -#include "Exceptions/ClientCommunicationError.hpp" -#include "Exceptions/DebugSessionInitialisationFailure.hpp" -#include "Exceptions/DebugServerInterrupted.hpp" - -#include "src/Exceptions/Exception.hpp" -#include "src/Exceptions/InvalidConfig.hpp" - -// Command packets -#include "CommandPackets/CommandPacket.hpp" -#include "CommandPackets/SupportedFeaturesQuery.hpp" -#include "CommandPackets/InterruptExecution.hpp" -#include "CommandPackets/ContinueExecution.hpp" -#include "CommandPackets/StepExecution.hpp" -#include "CommandPackets/SetBreakpoint.hpp" -#include "CommandPackets/RemoveBreakpoint.hpp" -#include "CommandPackets/Monitor.hpp" -#include "CommandPackets/ResetTarget.hpp" -#include "CommandPackets/HelpMonitorInfo.hpp" -#include "CommandPackets/BloomVersion.hpp" -#include "CommandPackets/BloomVersionMachine.hpp" -#include "CommandPackets/Detach.hpp" -#include "CommandPackets/ListRegistersMonitor.hpp" -#include "CommandPackets/ReadRegistersMonitor.hpp" -#include "CommandPackets/WriteRegisterMonitor.hpp" - -#ifndef EXCLUDE_INSIGHT -#include "CommandPackets/ActivateInsight.hpp" -#endif - -// Response packets -#include "ResponsePackets/TargetStopped.hpp" - -#include "src/Services/ProcessService.hpp" -#include "src/Services/StringService.hpp" - -namespace DebugServer::Gdb -{ - using namespace Exceptions; - using namespace ::Exceptions; - - using CommandPackets::CommandPacket; - - GdbRspDebugServer::GdbRspDebugServer( - const DebugServerConfig& debugServerConfig, - const Targets::TargetDescriptor& targetDescriptor, - EventListener& eventListener, - EventFdNotifier& eventNotifier - ) - : debugServerConfig(GdbDebugServerConfig(debugServerConfig)) - , targetDescriptor(targetDescriptor) - , eventListener(eventListener) - , interruptEventNotifier(eventNotifier) - {} - - void GdbRspDebugServer::init() { - this->socketAddress.sin_family = AF_INET; - this->socketAddress.sin_port = htons(this->debugServerConfig.listeningPortNumber); - - if ( - ::inet_pton( - AF_INET, - this->debugServerConfig.listeningAddress.c_str(), - &(this->socketAddress.sin_addr) - ) == 0 - ) { - // Invalid IP address - throw InvalidConfig{ - "Invalid IP address provided in config file: (\"" + this->debugServerConfig.listeningAddress + "\")" - }; - } - - auto socketFileDescriptor = int{0}; - if ((socketFileDescriptor = ::socket(AF_INET, SOCK_STREAM, 0)) == 0) { - throw Exception{"Failed to create socket file descriptor."}; - } - - const auto enableReuseAddressSocketOption = int{1}; - if ( - ::setsockopt( - socketFileDescriptor, - SOL_SOCKET, - SO_REUSEADDR, - &(enableReuseAddressSocketOption), - sizeof(enableReuseAddressSocketOption) - ) < 0 - ) { - Logger::error("Failed to set socket SO_REUSEADDR option."); - } - - if ( - ::bind( - socketFileDescriptor, - reinterpret_cast(&(this->socketAddress)), - sizeof(this->socketAddress) - ) < 0 - ) { - throw Exception{ - "Failed to bind address. The selected port number (" - + std::to_string(this->debugServerConfig.listeningPortNumber) + ") may be in use." - }; - } - - this->serverSocketFileDescriptor = socketFileDescriptor; - - this->epollInstance.addEntry( - this->serverSocketFileDescriptor.value(), - static_cast(::EPOLL_EVENTS::EPOLLIN) - ); - - this->epollInstance.addEntry( - this->interruptEventNotifier.getFileDescriptor(), - static_cast(::EPOLL_EVENTS::EPOLLIN) - ); - - Logger::info("GDB RSP address: " + this->debugServerConfig.listeningAddress); - Logger::info("GDB RSP port: " + std::to_string(this->debugServerConfig.listeningPortNumber)); - - this->eventListener.registerCallbackForEventType( - std::bind(&GdbRspDebugServer::onTargetStateChanged, this, std::placeholders::_1) - ); - - if (Services::ProcessService::isManagedByClion()) { - Logger::warning( - "Bloom's process is being managed by CLion - Bloom will automatically shutdown upon detaching from GDB." - ); - } - } - - void GdbRspDebugServer::close() { - this->endDebugSession(); - - if (this->serverSocketFileDescriptor.has_value()) { - ::close(this->serverSocketFileDescriptor.value()); - } - } - - void GdbRspDebugServer::run() { - try { - if (this->getActiveDebugSession() == nullptr) { - Logger::info("Waiting for GDB RSP connection"); - - auto connection = this->waitForConnection(); - Logger::info("Accepted GDP RSP connection from " + connection.getIpAddress()); - - this->startDebugSession(std::move(connection)); - - this->targetControllerService.stopTargetExecution(); - this->targetControllerService.resetTarget(); - } - - const auto commandPacket = this->waitForCommandPacket(); - if (!commandPacket) { - return; - } - - commandPacket->handle( - *(this->getActiveDebugSession()), - this->getGdbTargetDescriptor(), - this->targetDescriptor, - this->targetControllerService - ); - - } catch (const ClientDisconnected&) { - Logger::info("GDB RSP client disconnected"); - this->endDebugSession(); - return; - - } catch (const ClientCommunicationError& exception) { - Logger::error( - "GDB RSP client communication error - " + exception.getMessage() + " - closing connection" - ); - this->endDebugSession(); - return; - - } catch (const ClientNotSupported& exception) { - Logger::error("Invalid GDB RSP client - " + exception.getMessage() + " - closing connection"); - this->endDebugSession(); - return; - - } catch (const DebugSessionInitialisationFailure& exception) { - Logger::warning("GDB debug session initialisation failure - " + exception.getMessage()); - this->endDebugSession(); - return; - - } catch (const DebugServerInterrupted&) { - // Server was interrupted by an event - Logger::debug("GDB RSP interrupted"); - return; - } - } - - Connection GdbRspDebugServer::waitForConnection() { - if (::listen(this->serverSocketFileDescriptor.value(), 3) != 0) { - throw Exception{"Failed to listen on server socket"}; - } - - const auto eventFileDescriptor = this->epollInstance.waitForEvent(); - if ( - !eventFileDescriptor.has_value() - || *eventFileDescriptor == this->interruptEventNotifier.getFileDescriptor() - ) { - this->interruptEventNotifier.clear(); - throw DebugServerInterrupted{}; - } - - return {this->serverSocketFileDescriptor.value(), this->interruptEventNotifier}; - } - - std::unique_ptr GdbRspDebugServer::waitForCommandPacket() { - auto* debugSession = this->getActiveDebugSession(); - const auto rawPackets = debugSession->connection.readRawPackets(); - assert(!rawPackets.empty()); - - if (rawPackets.size() > 1) { - const auto& firstRawPacket = rawPackets.front(); - - if (firstRawPacket.size() == 5 && firstRawPacket[1] == 0x03) { - // Interrupt packet that came in too quickly before another packet - debugSession->pendingInterrupt = true; - - } else { - Logger::warning("Multiple packets received from GDB - only the most recent will be processed"); - } - } - - return this->resolveCommandPacket(rawPackets.back()); - } - - std::unique_ptr GdbRspDebugServer::resolveCommandPacket(const RawPacket& rawPacket) { - if (rawPacket.size() < 2) { - throw Exception{"Invalid raw packet - no data"}; - } - - if (rawPacket.size() == 5 && rawPacket[1] == 0x03) { - // Interrupt request - return std::make_unique(rawPacket); - } - - if (rawPacket[1] == 'c') { - return std::make_unique(rawPacket); - } - - if (rawPacket[1] == 's') { - return std::make_unique(rawPacket); - } - - if (rawPacket[1] == 'Z') { - return std::make_unique(rawPacket); - } - - if (rawPacket[1] == 'z') { - return std::make_unique(rawPacket); - } - - if (rawPacket[1] == 'D') { - return std::make_unique(rawPacket); - } - - const auto rawPacketString = std::string{rawPacket.begin() + 1, rawPacket.end()}; - - /* - * First byte of the raw packet will be 0x24 ('$'), so std::string::find() should return 1, not 0, when - * looking for a command identifier string. - */ - if (rawPacketString.find("qSupported") == 0) { - return std::make_unique(rawPacket); - } - - if (rawPacketString.find("qRcmd") == 0) { - // This is a monitor packet - auto monitorCommand = std::make_unique(rawPacket); - - if (monitorCommand->command == "help") { - return std::make_unique(std::move(*(monitorCommand.release()))); - } - - if (monitorCommand->command == "version") { - return std::make_unique(std::move(*(monitorCommand.release()))); - } - - if (monitorCommand->command == "version machine") { - return std::make_unique(std::move(*(monitorCommand.release()))); - } - - if (monitorCommand->command == "reset") { - return std::make_unique(std::move(*(monitorCommand.release()))); - } - - if (monitorCommand->command.find("lr") == 0) { - return std::make_unique(std::move(*(monitorCommand.release()))); - } - - if (monitorCommand->command.find("rr") == 0) { - return std::make_unique(std::move(*(monitorCommand.release()))); - } - - if (monitorCommand->command.find("wr") == 0) { - return std::make_unique(std::move(*(monitorCommand.release()))); - } - -#ifndef EXCLUDE_INSIGHT - if (monitorCommand->command.find("insight") == 0) { - return std::make_unique(std::move(*(monitorCommand.release()))); - } -#endif - return monitorCommand; - } - - return std::make_unique(rawPacket); - } - - void GdbRspDebugServer::onTargetStateChanged(const Events::TargetStateChanged& event) { - using Targets::TargetExecutionState; - - auto* debugSession = this->getActiveDebugSession(); - if (debugSession == nullptr) { - return; - } - - if (event.newState.executionState == event.previousState.executionState) { - // Execution state hasn't changed. Probably just a mode change. Ignore... - return; - } - - const auto executionState = event.newState.executionState.load(); - - try { - if (executionState == TargetExecutionState::STOPPED && debugSession->waitingForBreak) { - this->handleTargetStoppedGdbResponse(event.newState.programCounter.load().value()); - return; - } - - if (executionState == TargetExecutionState::RUNNING || executionState == TargetExecutionState::STEPPING) { - this->handleTargetResumedGdbResponse(); - return; - } - - } catch (const ClientDisconnected&) { - Logger::info("GDB RSP client disconnected"); - this->endDebugSession(); - return; - - } catch (const ClientCommunicationError& exception) { - Logger::error( - "GDB RSP client communication error - " + exception.getMessage() + " - closing connection" - ); - this->endDebugSession(); - return; - - } catch (const DebugServerInterrupted&) { - // Server was interrupted - Logger::debug("GDB RSP interrupted"); - return; - - } catch (const Exception& exception) { - Logger::error("Failed to handle target execution stopped event - " + exception.getMessage()); - } - } - - void GdbRspDebugServer::handleTargetStoppedGdbResponse(Targets::TargetMemoryAddress programAddress) { - auto* debugSession = this->getActiveDebugSession(); - - if (debugSession->activeRangeSteppingSession.has_value()) { - debugSession->terminateRangeSteppingSession(this->targetControllerService); - } - - debugSession->connection.writePacket(ResponsePackets::TargetStopped{Signal::TRAP}); - debugSession->waitingForBreak = false; - } - - void GdbRspDebugServer::handleTargetResumedGdbResponse() { - auto* debugSession = this->getActiveDebugSession(); - - if (debugSession->waitingForBreak && debugSession->pendingInterrupt) { - Logger::info("Servicing pending interrupt"); - this->targetControllerService.stopTargetExecution(); - - if (debugSession->activeRangeSteppingSession.has_value()) { - debugSession->terminateRangeSteppingSession(this->targetControllerService); - } - - debugSession->connection.writePacket(ResponsePackets::TargetStopped{Signal::INTERRUPTED}); - debugSession->pendingInterrupt = false; - debugSession->waitingForBreak = false; - } - } -} diff --git a/src/DebugServer/Gdb/GdbRspDebugServer.hpp b/src/DebugServer/Gdb/GdbRspDebugServer.hpp index 5f4eba76..82e568da 100644 --- a/src/DebugServer/Gdb/GdbRspDebugServer.hpp +++ b/src/DebugServer/Gdb/GdbRspDebugServer.hpp @@ -5,27 +5,71 @@ #include #include #include +#include +#include #include #include +#include +#include #include "src/DebugServer/ServerInterface.hpp" #include "GdbDebugServerConfig.hpp" -#include "src/EventManager/EventListener.hpp" -#include "src/Helpers/EpollInstance.hpp" -#include "src/Helpers/EventFdNotifier.hpp" -#include "src/Services/TargetControllerService.hpp" -#include "src/Targets/TargetDescriptor.hpp" - #include "Connection.hpp" #include "TargetDescriptor.hpp" #include "DebugSession.hpp" #include "Signal.hpp" #include "RegisterDescriptor.hpp" #include "Feature.hpp" -#include "CommandPackets/CommandPacket.hpp" + +#include "src/EventManager/EventListener.hpp" +#include "src/Helpers/EpollInstance.hpp" +#include "src/Helpers/EventFdNotifier.hpp" +#include "src/Services/TargetControllerService.hpp" +#include "src/Targets/TargetDescriptor.hpp" #include "src/EventManager/Events/TargetStateChanged.hpp" +#include "src/EventManager/EventManager.hpp" + +#include "src/Logger/Logger.hpp" + +#include "Exceptions/ClientDisconnected.hpp" +#include "Exceptions/ClientNotSupported.hpp" +#include "Exceptions/ClientCommunicationError.hpp" +#include "Exceptions/DebugSessionInitialisationFailure.hpp" +#include "Exceptions/DebugServerInterrupted.hpp" + +#include "src/Exceptions/Exception.hpp" +#include "src/Exceptions/InvalidConfig.hpp" + +// Command packets +#include "CommandPackets/CommandPacket.hpp" +#include "CommandPackets/CommandPacket.hpp" +#include "CommandPackets/SupportedFeaturesQuery.hpp" +#include "CommandPackets/InterruptExecution.hpp" +#include "CommandPackets/ContinueExecution.hpp" +#include "CommandPackets/StepExecution.hpp" +#include "CommandPackets/SetBreakpoint.hpp" +#include "CommandPackets/RemoveBreakpoint.hpp" +#include "CommandPackets/Monitor.hpp" +#include "CommandPackets/ResetTarget.hpp" +#include "CommandPackets/HelpMonitorInfo.hpp" +#include "CommandPackets/BloomVersion.hpp" +#include "CommandPackets/BloomVersionMachine.hpp" +#include "CommandPackets/Detach.hpp" +#include "CommandPackets/ListRegistersMonitor.hpp" +#include "CommandPackets/ReadRegistersMonitor.hpp" +#include "CommandPackets/WriteRegisterMonitor.hpp" + +#ifndef EXCLUDE_INSIGHT +#include "CommandPackets/ActivateInsight.hpp" +#endif + +// Response packets +#include "ResponsePackets/TargetStopped.hpp" + +#include "src/Services/ProcessService.hpp" +#include "src/Services/StringService.hpp" namespace DebugServer::Gdb { @@ -38,15 +82,30 @@ namespace DebugServer::Gdb * See https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html for more info on the GDB Remote Serial * Protocol. */ + template< + typename GdbTargetDescriptorType, + typename DebugSessionType, + typename CommandPacketType + > + requires + std::is_base_of_v + && std::is_base_of_v class GdbRspDebugServer: public ServerInterface { public: explicit GdbRspDebugServer( const DebugServerConfig& debugServerConfig, const Targets::TargetDescriptor& targetDescriptor, + GdbTargetDescriptorType&& gdbTargetDescriptor, EventListener& eventListener, EventFdNotifier& eventNotifier - ); + ) + : debugServerConfig(GdbDebugServerConfig{debugServerConfig}) + , targetDescriptor(targetDescriptor) + , gdbTargetDescriptor(std::move(gdbTargetDescriptor)) + , eventListener(eventListener) + , interruptEventNotifier(eventNotifier) + {}; GdbRspDebugServer() = delete; virtual ~GdbRspDebugServer() = default; @@ -59,30 +118,183 @@ namespace DebugServer::Gdb [[nodiscard]] std::string getName() const override { return "GDB Remote Serial Protocol DebugServer"; - }; + } /** * Prepares the GDB server for listing on the selected address and port. */ - void init() override; + void init() override { + this->socketAddress.sin_family = AF_INET; + this->socketAddress.sin_port = htons(this->debugServerConfig.listeningPortNumber); + + if ( + ::inet_pton( + AF_INET, + this->debugServerConfig.listeningAddress.c_str(), + &(this->socketAddress.sin_addr) + ) == 0 + ) { + // Invalid IP address + throw ::Exceptions::InvalidConfig{ + "Invalid IP address provided in config file: (\"" + this->debugServerConfig.listeningAddress + "\")" + }; + } + + auto socketFileDescriptor = int{0}; + if ((socketFileDescriptor = ::socket(AF_INET, SOCK_STREAM, 0)) == 0) { + throw ::Exceptions::Exception{"Failed to create socket file descriptor."}; + } + + const auto enableReuseAddressSocketOption = int{1}; + if ( + ::setsockopt( + socketFileDescriptor, + SOL_SOCKET, + SO_REUSEADDR, + &(enableReuseAddressSocketOption), + sizeof(enableReuseAddressSocketOption) + ) < 0 + ) { + Logger::error("Failed to set socket SO_REUSEADDR option."); + } + + if ( + ::bind( + socketFileDescriptor, + reinterpret_cast(&(this->socketAddress)), + sizeof(this->socketAddress) + ) < 0 + ) { + throw ::Exceptions::Exception{ + "Failed to bind address. The selected port number (" + + std::to_string(this->debugServerConfig.listeningPortNumber) + ") may be in use." + }; + } + + this->serverSocketFileDescriptor = socketFileDescriptor; + + this->epollInstance.addEntry( + this->serverSocketFileDescriptor.value(), + static_cast(::EPOLL_EVENTS::EPOLLIN) + ); + + this->epollInstance.addEntry( + this->interruptEventNotifier.getFileDescriptor(), + static_cast(::EPOLL_EVENTS::EPOLLIN) + ); + + Logger::info("GDB RSP address: " + this->debugServerConfig.listeningAddress); + Logger::info("GDB RSP port: " + std::to_string(this->debugServerConfig.listeningPortNumber)); + + this->eventListener.template registerCallbackForEventType( + std::bind(&GdbRspDebugServer::onTargetStateChanged, this, std::placeholders::_1) + ); + + if (Services::ProcessService::isManagedByClion()) { + Logger::warning( + "Bloom's process is being managed by CLion - Bloom will automatically shutdown upon detaching from GDB." + ); + } + } /** * Terminates any active debug session and closes the listening socket. */ - void close() override; + void close() override { + this->endDebugSession(); + + if (this->serverSocketFileDescriptor.has_value()) { + ::close(this->serverSocketFileDescriptor.value()); + } + } /** * 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; + void run() override { + try { + if (!this->debugSession.has_value()) { + Logger::info("Waiting for GDB RSP connection"); + + auto connection = this->waitForConnection(); + Logger::info("Accepted GDP RSP connection from " + connection.getIpAddress()); + + this->debugSession.emplace( + std::move(connection), + this->getSupportedFeatures(), + this->debugServerConfig + ); + + this->targetControllerService.stopTargetExecution(); + this->targetControllerService.resetTarget(); + } + + const auto commandPacketVariant = this->waitForCommandPacket(); + + if (std::holds_alternative>(commandPacketVariant)) { + const auto& commandPacket = std::get>(commandPacketVariant); + if (!commandPacket) { + return; + } + + commandPacket->handle( + *(this->debugSession), + this->gdbTargetDescriptor, + this->targetDescriptor, + this->targetControllerService + ); + + } else { + const auto& commandPacket = std::get>( + commandPacketVariant + ); + if (!commandPacket) { + return; + } + + commandPacket->handle( + *(this->debugSession), + this->gdbTargetDescriptor, + this->targetDescriptor, + this->targetControllerService + ); + } + + } catch (const Exceptions::ClientDisconnected&) { + Logger::info("GDB RSP client disconnected"); + this->endDebugSession(); + return; + + } catch (const Exceptions::ClientCommunicationError& exception) { + Logger::error( + "GDB RSP client communication error - " + exception.getMessage() + " - closing connection" + ); + this->endDebugSession(); + return; + + } catch (const Exceptions::ClientNotSupported& exception) { + Logger::error("Invalid GDB RSP client - " + exception.getMessage() + " - closing connection"); + this->endDebugSession(); + return; + + } catch (const Exceptions::DebugSessionInitialisationFailure& exception) { + Logger::warning("GDB debug session initialisation failure - " + exception.getMessage()); + this->endDebugSession(); + return; + + } catch (const Exceptions::DebugServerInterrupted&) { + // Server was interrupted by an event + Logger::debug("GDB RSP interrupted"); + return; + } + } protected: GdbDebugServerConfig debugServerConfig; - const Targets::TargetDescriptor& targetDescriptor; - + GdbTargetDescriptorType gdbTargetDescriptor; EventListener& eventListener; /** @@ -105,88 +317,255 @@ namespace DebugServer::Gdb * See EpollInstance * See EventFdNotifier */ - EpollInstance epollInstance = EpollInstance(); + EpollInstance epollInstance = {}; - /** - * Passed to command handlers (see CommandPacket::handle()). - * - * See documentation in src/DebugServer/Gdb/README.md for more on how GDB commands are processed. - */ - Services::TargetControllerService targetControllerService = Services::TargetControllerService(); + Services::TargetControllerService targetControllerService = {}; - /** - * Listening socket address - */ struct sockaddr_in socketAddress = {}; - - /** - * Listening socket file descriptor - */ std::optional serverSocketFileDescriptor; /** - * Should start a new debug session for the newly established `connection`. - * - * @param connection - * @return + * The active debug session. */ - virtual DebugSession* startDebugSession(Connection&& connection) = 0; + std::optional debugSession; - /** - * Should end the currently active debug session, if one exists. - */ - virtual void endDebugSession() = 0; + void endDebugSession() { + this->debugSession.reset(); + } - /** - * Should return a non-owning pointer of the currently active debug session. Or nullptr if there is no active - * session. - * - * @return - */ - virtual DebugSession* getActiveDebugSession() = 0; + Connection waitForConnection() { + if (::listen(this->serverSocketFileDescriptor.value(), 3) != 0) { + throw ::Exceptions::Exception{"Failed to listen on server socket"}; + } - /** - * Waits for a GDB client to connect on the listening socket. - */ - Connection waitForConnection(); + const auto eventFileDescriptor = this->epollInstance.waitForEvent(); + if ( + !eventFileDescriptor.has_value() + || *eventFileDescriptor == this->interruptEventNotifier.getFileDescriptor() + ) { + this->interruptEventNotifier.clear(); + throw Exceptions::DebugServerInterrupted{}; + } + + return {this->serverSocketFileDescriptor.value(), this->interruptEventNotifier}; + } /** * Waits for a command packet from the connected GDB client. * + * This function will first attempt to construct a server-implementation-specific command packet, but if that + * yields nothing, it will fall back to a generic command packet. + * * @return */ - std::unique_ptr waitForCommandPacket(); + std::variant< + std::unique_ptr, + std::unique_ptr + > waitForCommandPacket() { + const auto rawPackets = this->debugSession->connection.readRawPackets(); + assert(!rawPackets.empty()); + + if (rawPackets.size() > 1) { + const auto& firstRawPacket = rawPackets.front(); + + if (firstRawPacket.size() == 5 && firstRawPacket[1] == 0x03) { + // Interrupt packet that came in too quickly before another packet + this->debugSession->pendingInterrupt = true; + + } else { + Logger::warning("Multiple packets received from GDB - only the most recent will be processed"); + } + } + + auto commandPacket = this->rawPacketToCommandPacket(rawPackets.back()); + if (commandPacket) { + return commandPacket; + } + + return this->rawPacketToGenericCommandPacket(rawPackets.back()); + } /** - * Should construct a derived instance of the CommandPackets::CommandPacket class, from a raw packet. + * Should construct a server-implementation-specific command packet 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). + * This function should return a nullptr if the server implementation does not recognise/handle the command. * * @param rawPacket * @return */ - virtual std::unique_ptr resolveCommandPacket(const RawPacket& rawPacket); + virtual std::unique_ptr rawPacketToCommandPacket(const RawPacket& rawPacket) = 0; /** - * Should return the GDB target descriptor for the connected target. + * If rawPacketToCommandPacket() returns a nullptr, we'll attempt to construct a generic command packet. * - * 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. + * @param rawPacket + * @return + */ + std::unique_ptr rawPacketToGenericCommandPacket(const RawPacket& rawPacket) { + if (rawPacket.size() < 2) { + throw ::Exceptions::Exception{"Invalid raw packet - no data"}; + } + + if (rawPacket.size() == 5 && rawPacket[1] == 0x03) { + // Interrupt request + return std::make_unique(rawPacket); + } + + if (rawPacket[1] == 'c') { + return std::make_unique(rawPacket); + } + + if (rawPacket[1] == 's') { + return std::make_unique(rawPacket); + } + + if (rawPacket[1] == 'Z') { + return std::make_unique(rawPacket); + } + + if (rawPacket[1] == 'z') { + return std::make_unique(rawPacket); + } + + if (rawPacket[1] == 'D') { + return std::make_unique(rawPacket); + } + + const auto rawPacketString = std::string{rawPacket.begin() + 1, rawPacket.end()}; + + /* + * First byte of the raw packet will be 0x24 ('$'), so std::string::find() should return 1, not 0, when + * looking for a command identifier string. + */ + if (rawPacketString.find("qSupported") == 0) { + return std::make_unique(rawPacket); + } + + if (rawPacketString.find("qRcmd") == 0) { + // This is a monitor packet + auto monitorCommand = std::make_unique(rawPacket); + + if (monitorCommand->command == "help") { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + + if (monitorCommand->command == "version") { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + + if (monitorCommand->command == "version machine") { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + + if (monitorCommand->command == "reset") { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + + if (monitorCommand->command.find("lr") == 0) { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + + if (monitorCommand->command.find("rr") == 0) { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + + if (monitorCommand->command.find("wr") == 0) { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + + #ifndef EXCLUDE_INSIGHT + if (monitorCommand->command.find("insight") == 0) { + return std::make_unique(std::move(*(monitorCommand.release()))); + } + #endif + return monitorCommand; + } + + return std::make_unique(rawPacket); + } + + /** + * Should return a set of GDB features supported by the AVR 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. * * @return */ - virtual const TargetDescriptor& getGdbTargetDescriptor() = 0; + virtual std::set>> getSupportedFeatures() = 0; - void onTargetStateChanged(const Events::TargetStateChanged& event); - virtual void handleTargetStoppedGdbResponse(Targets::TargetMemoryAddress programAddress); - virtual void handleTargetResumedGdbResponse(); + void onTargetStateChanged(const Events::TargetStateChanged& event) { + using Targets::TargetExecutionState; + + if (!this->debugSession.has_value()) { + return; + } + + if (event.newState.executionState == event.previousState.executionState) { + // Execution state hasn't changed. Probably just a mode change. Ignore... + return; + } + + const auto executionState = event.newState.executionState.load(); + + try { + if (executionState == TargetExecutionState::STOPPED && this->debugSession->waitingForBreak) { + this->handleTargetStoppedGdbResponse(event.newState.programCounter.load().value()); + return; + } + + if ( + executionState == TargetExecutionState::RUNNING + || executionState == TargetExecutionState::STEPPING + ) { + this->handleTargetResumedGdbResponse(); + return; + } + + } catch (const Exceptions::ClientDisconnected&) { + Logger::info("GDB RSP client disconnected"); + this->endDebugSession(); + return; + + } catch (const Exceptions::ClientCommunicationError& exception) { + Logger::error( + "GDB RSP client communication error - " + exception.getMessage() + " - closing connection" + ); + this->endDebugSession(); + return; + + } catch (const Exceptions::DebugServerInterrupted&) { + // Server was interrupted + Logger::debug("GDB RSP interrupted"); + return; + + } catch (const ::Exceptions::Exception& exception) { + Logger::error("Failed to handle target execution stopped event - " + exception.getMessage()); + } + } + + virtual void handleTargetStoppedGdbResponse(Targets::TargetMemoryAddress programAddress) { + if (this->debugSession->activeRangeSteppingSession.has_value()) { + this->debugSession->terminateRangeSteppingSession(this->targetControllerService); + } + + this->debugSession->connection.writePacket(ResponsePackets::TargetStopped{Signal::TRAP}); + this->debugSession->waitingForBreak = false; + } + + virtual void handleTargetResumedGdbResponse() { + if (this->debugSession->waitingForBreak && this->debugSession->pendingInterrupt) { + Logger::info("Servicing pending interrupt"); + this->targetControllerService.stopTargetExecution(); + + if (this->debugSession->activeRangeSteppingSession.has_value()) { + this->debugSession->terminateRangeSteppingSession(this->targetControllerService); + } + + this->debugSession->connection.writePacket(ResponsePackets::TargetStopped{Signal::INTERRUPTED}); + this->debugSession->pendingInterrupt = false; + this->debugSession->waitingForBreak = false; + } + } }; }