From 34b26c3d06dc3a59ddda8faf9195673eb8448c97 Mon Sep 17 00:00:00 2001 From: Nav Date: Sat, 24 Aug 2024 20:11:30 +0100 Subject: [PATCH] Replaced `commandOptions` member with `commandArguments` in the GDB Monitor command base class Updated the `eeprom fill` monitor command to take the fill value from the third command argument. Also updated help text --- .../Gdb/AvrGdb/CommandPackets/EepromFill.cpp | 29 +++---- .../Gdb/AvrGdb/CommandPackets/EepromFill.hpp | 3 - .../Gdb/CommandPackets/Monitor.cpp | 80 +++++++------------ .../Gdb/CommandPackets/Monitor.hpp | 20 +---- .../Gdb/Resources/GdbHelpMonitorInfo.txt.in | 18 ++--- 5 files changed, 56 insertions(+), 94 deletions(-) diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp index be0a9b14..7f556d7f 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "src/DebugServer/Gdb/ResponsePackets/ResponsePacket.hpp" #include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp" @@ -26,12 +27,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets : Monitor(std::move(monitorPacket)) , eepromAddressSpaceDescriptor(gdbTargetDescriptor.eepromAddressSpaceDescriptor) , eepromMemorySegmentDescriptor(gdbTargetDescriptor.eepromMemorySegmentDescriptor) - { - const auto fillValueOptionIt = this->commandOptions.find("value"); - if (fillValueOptionIt != this->commandOptions.end() && fillValueOptionIt->second.has_value()) { - this->fillValue = Services::StringService::dataFromHex(*(fillValueOptionIt->second)); - } - } + {} void EepromFill::handle( Gdb::DebugSession& debugSession, @@ -42,13 +38,14 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets Logger::info("Handling EepromFill packet"); try { - const auto eepromSize = this->eepromMemorySegmentDescriptor.size(); - const auto fillValueSize = this->fillValue.size(); - - if (fillValueSize == 0) { + if (this->commandArguments.size() < 3 || this->commandArguments[2].empty()) { throw InvalidCommandOption{"Fill value required"}; } + const auto eepromSize = this->eepromMemorySegmentDescriptor.size(); + const auto& fillValue = Services::StringService::dataFromHex(this->commandArguments[2]); + const auto fillValueSize = fillValue.size(); + if (fillValueSize > eepromSize) { throw InvalidCommandOption{ "Fill value size (" + std::to_string(fillValueSize) + " bytes) exceeds EEPROM size (" @@ -68,12 +65,12 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets auto data = Targets::TargetMemoryBuffer{}; data.reserve(eepromSize); - // Repeat this->fillValue until we've filled `data` + // Repeat fillValue until we've filled `data` while (data.size() < eepromSize) { data.insert( data.end(), - this->fillValue.begin(), - this->fillValue.begin() + static_cast( + fillValue.begin(), + fillValue.begin() + static_cast( std::min(fillValueSize, (eepromSize - data.size())) ) ); @@ -94,11 +91,15 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets )}); } catch (const InvalidCommandOption& exception) { - Logger::error(exception.getMessage()); debugSession.connection.writePacket( ResponsePacket{Services::StringService::toHex(exception.getMessage() + "\n")} ); + } catch (const std::invalid_argument& exception) { + debugSession.connection.writePacket( + ResponsePacket{Services::StringService::toHex("Invalid fill value\n")} + ); + } catch (const Exception& exception) { Logger::error("Failed to fill EEPROM - " + exception.getMessage()); debugSession.connection.writePacket(ErrorResponsePacket{}); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp index 0f3e2837..727733c8 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/EepromFill.hpp @@ -30,8 +30,5 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets const Targets::TargetDescriptor& targetDescriptor, Services::TargetControllerService& targetControllerService ) override; - - private: - Targets::TargetMemoryBuffer fillValue; }; } diff --git a/src/DebugServer/Gdb/CommandPackets/Monitor.cpp b/src/DebugServer/Gdb/CommandPackets/Monitor.cpp index 55bf9189..b588bd99 100644 --- a/src/DebugServer/Gdb/CommandPackets/Monitor.cpp +++ b/src/DebugServer/Gdb/CommandPackets/Monitor.cpp @@ -25,7 +25,7 @@ namespace DebugServer::Gdb::CommandPackets this->command = std::string{decodedCommand.begin(), decodedCommand.end()}; this->command.erase(this->command.find_last_not_of(" ") + 1); - this->commandOptions = this->extractCommandOptions(this->command); + this->commandArguments = Monitor::extractCommandArguments(this->command); } void Monitor::handle( @@ -38,61 +38,39 @@ namespace DebugServer::Gdb::CommandPackets debugSession.connection.writePacket(EmptyResponsePacket{}); } - std::map> Monitor::extractCommandOptions(const std::string& command) { - auto output = std::map>{}; + std::vector Monitor::extractCommandArguments(const std::string& command) { + auto output = std::vector{}; - for (std::string::size_type cmdIndex = 1; cmdIndex < command.size(); ++cmdIndex) { - const auto cmdChar = command.at(cmdIndex); + auto quoteEnabled = false; + auto argument = std::string{}; - if (cmdChar == '-') { - if (command.at(cmdIndex - 1) != '-') { - continue; + const auto commit = [&output, &argument] () { + output.emplace_back(std::move(argument)); + argument.clear(); + }; + + for (auto i = std::string::size_type{0}; i < command.size(); ++i) { + const auto cmdChar = command.at(i); + + if (cmdChar == '"') { + if (quoteEnabled) { + commit(); } - auto option = std::string{}; - auto optionValue = std::optional{}; - - bool quoted = false; - - auto optIndex = std::string::size_type{0}; - for (optIndex = cmdIndex + 1; optIndex < command.size(); ++optIndex) { - const auto optChar = command.at(optIndex); - - if (!option.empty() && ((!quoted && optChar == ' ') || (quoted && optChar == '"'))) { - output.emplace(option, optionValue); - - option.clear(); - optionValue.reset(); - quoted = false; - - cmdIndex = optIndex; - break; - } - - if (optionValue.has_value()) { - if (optChar == '"' && !quoted && optionValue->empty()) { - quoted = true; - continue; - } - - optionValue->push_back(optChar); - continue; - } - - if (optChar == '=') { - optionValue = std::string{}; - continue; - } - - option.push_back(optChar); - continue; - } - - if (!option.empty()) { - output.emplace(option, optionValue); - cmdIndex = optIndex; - } + quoteEnabled = !quoteEnabled; + continue; } + + if (!quoteEnabled && cmdChar == ' ') { + commit(); + continue; + } + + argument.push_back(cmdChar); + } + + if (!argument.empty()) { + commit(); } return output; diff --git a/src/DebugServer/Gdb/CommandPackets/Monitor.hpp b/src/DebugServer/Gdb/CommandPackets/Monitor.hpp index e24a108f..33c12bb7 100644 --- a/src/DebugServer/Gdb/CommandPackets/Monitor.hpp +++ b/src/DebugServer/Gdb/CommandPackets/Monitor.hpp @@ -2,8 +2,7 @@ #include #include -#include -#include +#include #include "CommandPacket.hpp" @@ -20,14 +19,7 @@ namespace DebugServer::Gdb::CommandPackets */ std::string command; - /** - * A mapping of any command options included in this->command. A command option must begin with "--" and - * can optionally have a value. - * - * The key of this map is the option name. The map value is the option value, or std::nullopt if no value was - * provided. - */ - std::map> commandOptions; + std::vector commandArguments; explicit Monitor(const RawPacket& rawPacket); @@ -39,12 +31,6 @@ namespace DebugServer::Gdb::CommandPackets ) override; private: - /** - * Extracts command options from a command string. - * - * @param command - * @return - */ - std::map> extractCommandOptions(const std::string& command); + static std::vector extractCommandArguments(const std::string& command); }; } diff --git a/src/DebugServer/Gdb/Resources/GdbHelpMonitorInfo.txt.in b/src/DebugServer/Gdb/Resources/GdbHelpMonitorInfo.txt.in index 5d735558..deddb2ca 100644 --- a/src/DebugServer/Gdb/Resources/GdbHelpMonitorInfo.txt.in +++ b/src/DebugServer/Gdb/Resources/GdbHelpMonitorInfo.txt.in @@ -1,14 +1,14 @@ Supported Bloom commands: - help Displays this help text. - version Outputs Bloom's version information. - version machine Outputs Bloom's version information in JSON format. + help Displays this help text. + version Outputs Bloom's version information. + version machine Outputs Bloom's version information in JSON format. @ACTIVATE_INSIGHT_HELP_TEXT@ - reset Resets the target and holds it in a stopped state. + reset Resets the target and holds it in a stopped state. - eeprom fill Fills the target's EEPROM with a specified value. The value should be specified via the - --value option. The value should be in hexadecimal format: "--value=AABBCC". If the specified - value is smaller than the EEPROM capacity, it will be repeated across the entire EEPROM address - range. If the value size is not a multiple of the EEPROM capacity, the value will be truncated - in the final repetition. The value size must not exceed the EEPROM capacity. + eeprom fill [VALUE] Fills the target's EEPROM with the specified value. The value should be in hexadecimal + format: "monitor eeprom fill AABBCC". If the specified value is smaller than the EEPROM + memory segment size, it will be repeated across the entire segment address range. If the + value size is not a multiple of the segment size, the value will be truncated in the final + repetition. The value size must not exceed the segment size.