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
This commit is contained in:
Nav
2024-08-24 20:11:30 +01:00
parent 34ca7d4289
commit 34b26c3d06
5 changed files with 56 additions and 94 deletions

View File

@@ -2,6 +2,7 @@
#include <QByteArray> #include <QByteArray>
#include <algorithm> #include <algorithm>
#include <stdexcept>
#include "src/DebugServer/Gdb/ResponsePackets/ResponsePacket.hpp" #include "src/DebugServer/Gdb/ResponsePackets/ResponsePacket.hpp"
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp" #include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
@@ -26,12 +27,7 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
: Monitor(std::move(monitorPacket)) : Monitor(std::move(monitorPacket))
, eepromAddressSpaceDescriptor(gdbTargetDescriptor.eepromAddressSpaceDescriptor) , eepromAddressSpaceDescriptor(gdbTargetDescriptor.eepromAddressSpaceDescriptor)
, eepromMemorySegmentDescriptor(gdbTargetDescriptor.eepromMemorySegmentDescriptor) , 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( void EepromFill::handle(
Gdb::DebugSession& debugSession, Gdb::DebugSession& debugSession,
@@ -42,13 +38,14 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
Logger::info("Handling EepromFill packet"); Logger::info("Handling EepromFill packet");
try { try {
const auto eepromSize = this->eepromMemorySegmentDescriptor.size(); if (this->commandArguments.size() < 3 || this->commandArguments[2].empty()) {
const auto fillValueSize = this->fillValue.size();
if (fillValueSize == 0) {
throw InvalidCommandOption{"Fill value required"}; 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) { if (fillValueSize > eepromSize) {
throw InvalidCommandOption{ throw InvalidCommandOption{
"Fill value size (" + std::to_string(fillValueSize) + " bytes) exceeds EEPROM size (" "Fill value size (" + std::to_string(fillValueSize) + " bytes) exceeds EEPROM size ("
@@ -68,12 +65,12 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
auto data = Targets::TargetMemoryBuffer{}; auto data = Targets::TargetMemoryBuffer{};
data.reserve(eepromSize); data.reserve(eepromSize);
// Repeat this->fillValue until we've filled `data` // Repeat fillValue until we've filled `data`
while (data.size() < eepromSize) { while (data.size() < eepromSize) {
data.insert( data.insert(
data.end(), data.end(),
this->fillValue.begin(), fillValue.begin(),
this->fillValue.begin() + static_cast<std::int32_t>( fillValue.begin() + static_cast<std::int32_t>(
std::min(fillValueSize, (eepromSize - data.size())) std::min(fillValueSize, (eepromSize - data.size()))
) )
); );
@@ -94,11 +91,15 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
)}); )});
} catch (const InvalidCommandOption& exception) { } catch (const InvalidCommandOption& exception) {
Logger::error(exception.getMessage());
debugSession.connection.writePacket( debugSession.connection.writePacket(
ResponsePacket{Services::StringService::toHex(exception.getMessage() + "\n")} 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) { } catch (const Exception& exception) {
Logger::error("Failed to fill EEPROM - " + exception.getMessage()); Logger::error("Failed to fill EEPROM - " + exception.getMessage());
debugSession.connection.writePacket(ErrorResponsePacket{}); debugSession.connection.writePacket(ErrorResponsePacket{});

View File

@@ -30,8 +30,5 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
const Targets::TargetDescriptor& targetDescriptor, const Targets::TargetDescriptor& targetDescriptor,
Services::TargetControllerService& targetControllerService Services::TargetControllerService& targetControllerService
) override; ) override;
private:
Targets::TargetMemoryBuffer fillValue;
}; };
} }

View File

@@ -25,7 +25,7 @@ namespace DebugServer::Gdb::CommandPackets
this->command = std::string{decodedCommand.begin(), decodedCommand.end()}; this->command = std::string{decodedCommand.begin(), decodedCommand.end()};
this->command.erase(this->command.find_last_not_of(" ") + 1); 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( void Monitor::handle(
@@ -38,61 +38,39 @@ namespace DebugServer::Gdb::CommandPackets
debugSession.connection.writePacket(EmptyResponsePacket{}); debugSession.connection.writePacket(EmptyResponsePacket{});
} }
std::map<std::string, std::optional<std::string>> Monitor::extractCommandOptions(const std::string& command) { std::vector<std::string> Monitor::extractCommandArguments(const std::string& command) {
auto output = std::map<std::string, std::optional<std::string>>{}; auto output = std::vector<std::string>{};
for (std::string::size_type cmdIndex = 1; cmdIndex < command.size(); ++cmdIndex) { auto quoteEnabled = false;
const auto cmdChar = command.at(cmdIndex); auto argument = std::string{};
if (cmdChar == '-') { const auto commit = [&output, &argument] () {
if (command.at(cmdIndex - 1) != '-') { output.emplace_back(std::move(argument));
continue; 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{}; quoteEnabled = !quoteEnabled;
auto optionValue = std::optional<std::string>{}; continue;
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;
}
} }
if (!quoteEnabled && cmdChar == ' ') {
commit();
continue;
}
argument.push_back(cmdChar);
}
if (!argument.empty()) {
commit();
} }
return output; return output;

View File

@@ -2,8 +2,7 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <map> #include <vector>
#include <optional>
#include "CommandPacket.hpp" #include "CommandPacket.hpp"
@@ -20,14 +19,7 @@ namespace DebugServer::Gdb::CommandPackets
*/ */
std::string command; std::string command;
/** std::vector<std::string> commandArguments;
* 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<std::string, std::optional<std::string>> commandOptions;
explicit Monitor(const RawPacket& rawPacket); explicit Monitor(const RawPacket& rawPacket);
@@ -39,12 +31,6 @@ namespace DebugServer::Gdb::CommandPackets
) override; ) override;
private: private:
/** static std::vector<std::string> extractCommandArguments(const std::string& command);
* Extracts command options from a command string.
*
* @param command
* @return
*/
std::map<std::string, std::optional<std::string>> extractCommandOptions(const std::string& command);
}; };
} }

View File

@@ -1,14 +1,14 @@
Supported Bloom commands: Supported Bloom commands:
help Displays this help text. help Displays this help text.
version Outputs Bloom's version information. version Outputs Bloom's version information.
version machine Outputs Bloom's version information in JSON format. version machine Outputs Bloom's version information in JSON format.
@ACTIVATE_INSIGHT_HELP_TEXT@ @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 eeprom fill [VALUE] Fills the target's EEPROM with the specified value. The value should be in hexadecimal
--value option. The value should be in hexadecimal format: "--value=AABBCC". If the specified format: "monitor eeprom fill AABBCC". If the specified value is smaller than the EEPROM
value is smaller than the EEPROM capacity, it will be repeated across the entire EEPROM address memory segment size, it will be repeated across the entire segment address range. If the
range. If the value size is not a multiple of the EEPROM capacity, the value will be truncated value size is not a multiple of the segment size, the value will be truncated in the final
in the final repetition. The value size must not exceed the EEPROM capacity. repetition. The value size must not exceed the segment size.