Massive refactor to accommodate RISC-V targets

- Refactored entire codebase (excluding the Insight component) to accommodate multiple target architectures (no longer specific to AVR)
- Deleted 'generate SVD' GDB monitor command - I will eventually move this functionality to the Bloom website
- Added unit size property to address spaces
- Many other changes which I couldn't be bothered to describe here
This commit is contained in:
Nav
2024-07-23 21:14:22 +01:00
parent 2986934485
commit 6cdbfbe950
331 changed files with 8815 additions and 8565 deletions

View File

@@ -3,9 +3,7 @@
#include "src/DebugServer/Gdb/ResponsePackets/OkResponsePacket.hpp"
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
#include "src/DebugServer/Gdb/AvrGdb/TargetDescriptor.hpp"
#include "src/Targets/TargetRegister.hpp"
#include "src/Services/StringService.hpp"
#include "src/Logger/Logger.hpp"
#include "src/Exceptions/Exception.hpp"
@@ -13,9 +11,6 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
{
using Services::TargetControllerService;
using Targets::TargetRegister;
using Targets::TargetRegisterDescriptors;
using ResponsePackets::ResponsePacket;
using ResponsePackets::OkResponsePacket;
using ResponsePackets::ErrorResponsePacket;
@@ -25,87 +20,88 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
WriteRegister::WriteRegister(const RawPacket& rawPacket)
: CommandPacket(rawPacket)
{
using Services::StringService;
if (this->data.size() < 4) {
throw Exception{"Invalid WriteRegister command packet - insufficient data in packet."};
}
// The P packet updates a single register
auto packet = std::string(this->data.begin(), this->data.end());
auto command = std::string{this->data.begin() + 1, this->data.end()};
if (packet.size() < 4) {
throw Exception("Invalid WriteRegister command packet - insufficient data in packet.");
const auto delimiterPos = command.find_first_of('=');
if (delimiterPos == std::string::npos) {
throw Exception{"Invalid packet"};
}
if (packet.find('=') == std::string::npos) {
throw Exception("Invalid WriteRegister command packet - unexpected format");
}
const auto packetSegments = QString::fromStdString(packet).split("=");
this->registerId = static_cast<GdbRegisterId>(packetSegments.front().mid(1).toUInt(nullptr, 16));
this->registerValue = Packet::hexToData(packetSegments.back().toStdString());
this->registerId = static_cast<GdbRegisterId>(StringService::toUint32(command.substr(0, delimiterPos), 16));
this->registerValue = Services::StringService::dataFromHex(command.substr(delimiterPos + 1));
if (this->registerValue.empty()) {
throw Exception("Invalid WriteRegister command packet - missing register value");
throw Exception{"Invalid WriteRegister command packet - missing register value"};
}
// LSB to MSB
std::reverse(this->registerValue.begin(), this->registerValue.end());
}
void WriteRegister::handle(Gdb::DebugSession& debugSession, TargetControllerService& targetControllerService) {
void WriteRegister::handle(
Gdb::DebugSession& debugSession,
const Gdb::TargetDescriptor& gdbTargetDescriptor,
const Targets::TargetDescriptor& targetDescriptor,
TargetControllerService& targetControllerService
) {
Logger::info("Handling WriteRegister packet");
try {
if (this->registerId == TargetDescriptor::PROGRAM_COUNTER_GDB_REGISTER_ID) {
if (this->registerValue.size() != 4) {
throw Exception{"Invalid PC value register size"};
}
targetControllerService.setProgramCounter(
static_cast<Targets::TargetMemoryAddress>(
(this->registerValue.size() >= 1 ? this->registerValue[0] : 0x00) << 24
| (this->registerValue.size() >= 2 ? this->registerValue[1] : 0x00) << 16
| (this->registerValue.size() >= 3 ? this->registerValue[2] : 0x00) << 8
| (this->registerValue.size() >= 4 ? this->registerValue[3] : 0x00)
this->registerValue[0] << 24
| this->registerValue[1] << 16
| this->registerValue[2] << 8
| this->registerValue[3]
)
);
debugSession.connection.writePacket(OkResponsePacket());
debugSession.connection.writePacket(OkResponsePacket{});
return;
}
const auto& gdbTargetDescriptor = debugSession.gdbTargetDescriptor;
const auto descriptorId = gdbTargetDescriptor.getTargetRegisterDescriptorIdFromGdbRegisterId(
if (this->registerId == TargetDescriptor::STACK_POINTER_GDB_REGISTER_ID) {
if (this->registerValue.size() != 2) {
throw Exception{"Invalid SP register value size"};
}
targetControllerService.setStackPointer(
static_cast<Targets::TargetStackPointer>(this->registerValue[0] << 8 | this->registerValue[1])
);
debugSession.connection.writePacket(OkResponsePacket{});
return;
}
const auto gdbRegisterDescriptorIt = gdbTargetDescriptor.gdbRegisterDescriptorsById.find(this->registerId);
const auto targetRegisterDescriptorIt = gdbTargetDescriptor.targetRegisterDescriptorsByGdbId.find(
this->registerId
);
if (!descriptorId.has_value()) {
throw Exception("Invalid/unknown register");
if (
gdbRegisterDescriptorIt == gdbTargetDescriptor.gdbRegisterDescriptorsById.end()
|| targetRegisterDescriptorIt == gdbTargetDescriptor.targetRegisterDescriptorsByGdbId.end()
) {
throw Exception{"Unknown GDB register ID (" + std::to_string(this->registerId) + ")"};
}
const auto& descriptor = gdbTargetDescriptor.targetDescriptor.registerDescriptorsById.at(*descriptorId);
if (this->registerValue.size() > descriptor.size) {
// Attempt to trim the higher zero-value bytes from the register value, until we reach the correct size.
for (auto i = this->registerValue.size() - 1; i >= descriptor.size; --i) {
if (this->registerValue.at(i) != 0x00) {
// If we reach a non-zero byte, we cannot trim anymore without changing the data
break;
}
this->registerValue.erase(this->registerValue.begin() + i);
}
if (this->registerValue.size() > descriptor.size) {
const auto& gdbRegisterDescriptor = gdbTargetDescriptor.gdbRegisterDescriptorsById.at(
this->registerId
);
throw Exception(
"Cannot set value for " + gdbRegisterDescriptor.name + " - value size exceeds register size."
);
}
}
targetControllerService.writeRegisters({
TargetRegister(descriptor.id, this->registerValue)
});
debugSession.connection.writePacket(OkResponsePacket());
targetControllerService.writeRegister(*(targetRegisterDescriptorIt->second), this->registerValue);
debugSession.connection.writePacket(OkResponsePacket{});
} catch (const Exception& exception) {
Logger::error("Failed to write registers - " + exception.getMessage());
debugSession.connection.writePacket(ErrorResponsePacket());
debugSession.connection.writePacket(ErrorResponsePacket{});
}
}
}