diff --git a/src/DebugServer/CMakeLists.txt b/src/DebugServer/CMakeLists.txt index 9de5551e..5a0c50fc 100755 --- a/src/DebugServer/CMakeLists.txt +++ b/src/DebugServer/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/BloomVersionMachine.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/Detach.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/ReadRegistersMonitor.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/CommandPackets/ListRegistersMonitor.cpp # AVR GDB RSP Server ${CMAKE_CURRENT_SOURCE_DIR}/Gdb/AvrGdb/AvrGdbRsp.cpp diff --git a/src/DebugServer/Gdb/CommandPackets/ListRegistersMonitor.cpp b/src/DebugServer/Gdb/CommandPackets/ListRegistersMonitor.cpp new file mode 100644 index 00000000..f3b33665 --- /dev/null +++ b/src/DebugServer/Gdb/CommandPackets/ListRegistersMonitor.cpp @@ -0,0 +1,142 @@ +#include "ListRegistersMonitor.hpp" + +#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp" +#include "src/DebugServer/Gdb/ResponsePackets/PartialResponsePacket.hpp" +#include "src/DebugServer/Gdb/ResponsePackets/ResponsePacket.hpp" + +#include "src/Services/StringService.hpp" +#include "src/Logger/Logger.hpp" + +#include "src/Exceptions/Exception.hpp" + +namespace DebugServer::Gdb::CommandPackets +{ + using Services::TargetControllerService; + using Services::StringService; + + using ResponsePackets::ErrorResponsePacket; + using ResponsePackets::PartialResponsePacket; + using ResponsePackets::ResponsePacket; + + using ::Exceptions::Exception; + + ListRegistersMonitor::ListRegistersMonitor(Monitor&& monitorPacket) + : Monitor(std::move(monitorPacket)) + {} + + void ListRegistersMonitor::handle( + DebugSession& debugSession, + const TargetDescriptor& gdbTargetDescriptor, + const Targets::TargetDescriptor& targetDescriptor, + TargetControllerService& targetControllerService + ) { + Logger::info("Handling ReadRegisterMonitor packet"); + + try { + const auto argCount = this->commandArguments.size(); + if (argCount < 2) { + for (const auto& [peripheralKey, peripheralDescriptor] : targetDescriptor.peripheralDescriptorsByKey) { + this->handlePeripheralOutput(peripheralDescriptor, debugSession); + debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex("\n")}); + } + + debugSession.connection.writePacket(ResponsePacket{StringService::toHex("\n")}); + return; + } + + const auto& peripheralKey = this->commandArguments[1]; + const auto peripheralDescriptorOpt = targetDescriptor.tryGetPeripheralDescriptor(peripheralKey); + + if (!peripheralDescriptorOpt.has_value()) { + throw Exception{"Unknown peripheral key \"" + peripheralKey + "\""}; + } + + const auto& peripheralDescriptor = peripheralDescriptorOpt->get(); + + if (argCount < 3) { + debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex( + peripheralDescriptor.name + " peripheral registers:\n\n" + )}); + this->handlePeripheralOutput(peripheralDescriptor, debugSession); + debugSession.connection.writePacket(ResponsePacket{StringService::toHex("\n")}); + + return; + } + + const auto& registerGroupKey = this->commandArguments[2]; + + auto registerGroupDescriptorOpt = peripheralDescriptor.tryGetRegisterGroupDescriptor( + registerGroupKey + ); + + if (!registerGroupDescriptorOpt.has_value()) { + throw Exception{"Unknown register group key \"" + registerGroupKey + "\""}; + } + + const auto& registerGroupDescriptor = registerGroupDescriptorOpt->get(); + + debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex( + peripheralDescriptor.name + " peripheral registers, in " + registerGroupDescriptor.name + + " register group:\n\n" + )}); + this->handleRegisterGroupOutput(registerGroupDescriptor, debugSession); + debugSession.connection.writePacket(ResponsePacket{StringService::toHex("\n")}); + + } catch (const Exception& exception) { + debugSession.connection.writePacket(ResponsePacket{ + StringService::toHex( + StringService::applyTerminalColor( + "Error: " + exception.getMessage() + "\n", + StringService::TerminalColor::DARK_RED + ) + ) + }); + } + } + + void ListRegistersMonitor::handlePeripheralOutput( + const Targets::TargetPeripheralDescriptor& peripheralDescriptor, + DebugSession& debugSession + ) { + debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex( + "---------- " + StringService::applyTerminalColor( + peripheralDescriptor.name, + StringService::TerminalColor::DARK_GREEN + ) + " (" + StringService::applyTerminalColor( + peripheralDescriptor.key, + StringService::TerminalColor::DARK_YELLOW + ) + ") peripheral registers ----------\n\n" + )}); + + for (const auto& [groupKey, groupDescriptor] : peripheralDescriptor.registerGroupDescriptorsByKey) { + this->handleRegisterGroupOutput(groupDescriptor, debugSession); + } + } + + void ListRegistersMonitor::handleRegisterGroupOutput( + const Targets::TargetRegisterGroupDescriptor& groupDescriptor, + DebugSession& debugSession + ) { + for (const auto& [registerKey, registerDescriptor] : groupDescriptor.registerDescriptorsByKey) { + auto output = std::string{registerDescriptor.absoluteGroupKey + ", "}; + output += registerDescriptor.key + ", "; + output += registerDescriptor.name + ", "; + output += StringService::applyTerminalColor( + "0x" + StringService::asciiToUpper(StringService::toHex(registerDescriptor.startAddress)), + StringService::TerminalColor::DARK_BLUE + ) + ", "; + output += std::to_string(registerDescriptor.size) + " byte(s)"; + + if (registerDescriptor.description.has_value()) { + output += ", \"" + *(registerDescriptor.description) + "\""; + } + + output += "\n"; + debugSession.connection.writePacket(PartialResponsePacket{StringService::toHex(output)}); + } + + for (const auto& [subGroupKey, subGroupDescriptor] : groupDescriptor.subgroupDescriptorsByKey) { + this->handleRegisterGroupOutput(subGroupDescriptor, debugSession); + } + } +} diff --git a/src/DebugServer/Gdb/CommandPackets/ListRegistersMonitor.hpp b/src/DebugServer/Gdb/CommandPackets/ListRegistersMonitor.hpp new file mode 100644 index 00000000..8705d3ab --- /dev/null +++ b/src/DebugServer/Gdb/CommandPackets/ListRegistersMonitor.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include "Monitor.hpp" + +#include "src/Targets/TargetRegisterDescriptor.hpp" +#include "src/Targets/TargetRegisterGroupDescriptor.hpp" +#include "src/Targets/TargetPeripheralDescriptor.hpp" + +namespace DebugServer::Gdb::CommandPackets +{ + class ListRegistersMonitor: public Monitor + { + public: + explicit ListRegistersMonitor(Monitor&& monitorPacket); + + void handle( + DebugSession& debugSession, + const TargetDescriptor& gdbTargetDescriptor, + const Targets::TargetDescriptor& targetDescriptor, + Services::TargetControllerService& targetControllerService + ) override; + + protected: + void handlePeripheralOutput( + const Targets::TargetPeripheralDescriptor& peripheralDescriptor, + DebugSession& debugSession + ); + + void handleRegisterGroupOutput( + const Targets::TargetRegisterGroupDescriptor& groupDescriptor, + DebugSession& debugSession + ); + }; +} diff --git a/src/DebugServer/Gdb/GdbRspDebugServer.cpp b/src/DebugServer/Gdb/GdbRspDebugServer.cpp index 001ca7ca..060f5b92 100644 --- a/src/DebugServer/Gdb/GdbRspDebugServer.cpp +++ b/src/DebugServer/Gdb/GdbRspDebugServer.cpp @@ -30,6 +30,7 @@ #include "CommandPackets/BloomVersionMachine.hpp" #include "CommandPackets/Detach.hpp" #include "CommandPackets/ReadRegistersMonitor.hpp" +#include "CommandPackets/ListRegistersMonitor.hpp" #ifndef EXCLUDE_INSIGHT #include "CommandPackets/ActivateInsight.hpp" @@ -296,6 +297,10 @@ namespace DebugServer::Gdb return std::make_unique(std::move(*(monitorCommand.release()))); } + if (monitorCommand->command.find("lr") == 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())));