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:
@@ -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{});
|
||||||
|
|||||||
@@ -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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
quoteEnabled = !quoteEnabled;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto option = std::string{};
|
if (!quoteEnabled && cmdChar == ' ') {
|
||||||
auto optionValue = std::optional<std::string>{};
|
commit();
|
||||||
|
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
optionValue->push_back(optChar);
|
argument.push_back(cmdChar);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optChar == '=') {
|
if (!argument.empty()) {
|
||||||
optionValue = std::string{};
|
commit();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
option.push_back(optChar);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!option.empty()) {
|
|
||||||
output.emplace(option, optionValue);
|
|
||||||
cmdIndex = optIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@@ -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);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ Supported Bloom commands:
|
|||||||
|
|
||||||
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user