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

@@ -2,6 +2,7 @@
#include "src/DebugServer/Gdb/ResponsePackets/ResponsePacket.hpp"
#include "src/Services/StringService.hpp"
#include "src/Exceptions/Exception.hpp"
namespace DebugServer::Gdb::AvrGdb::CommandPackets
@@ -12,111 +13,74 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
using Exceptions::Exception;
ReadMemoryMap::ReadMemoryMap(const RawPacket& rawPacket)
ReadMemoryMap::ReadMemoryMap(const RawPacket& rawPacket, const TargetDescriptor& gdbTargetDescriptor)
: CommandPacket(rawPacket)
, eepromAddressSpaceDescriptor(gdbTargetDescriptor.eepromAddressSpaceDescriptor)
, programMemorySegmentDescriptor(gdbTargetDescriptor.programMemorySegmentDescriptor)
, eepromMemorySegmentDescriptor(gdbTargetDescriptor.eepromMemorySegmentDescriptor)
{
if (this->data.size() < 26) {
throw Exception("Invalid packet length");
}
using Services::StringService;
auto packetString = QString::fromLocal8Bit(
reinterpret_cast<const char*>(this->data.data() + 23), // +23 to exclude the "qXfer:memory-map:read::"
static_cast<int>(this->data.size() - 23)
);
if (this->data.size() < 26) {
throw Exception{"Invalid packet length"};
}
/*
* The read memory map ('qXfer:memory-map:read::...') packet consists of two segments, an offset and a length.
* These are separated by a comma character.
*/
auto packetSegments = packetString.split(",");
const auto command = std::string{this->data.begin() + 23, this->data.end()};
if (packetSegments.size() != 2) {
throw Exception(
"Unexpected number of segments in packet data: " + std::to_string(packetSegments.size())
);
const auto delimiterPos = command.find_first_of(',');
if (delimiterPos == std::string::npos) {
throw Exception{"Invalid packet"};
}
bool conversionStatus = false;
this->offset = packetSegments.at(0).toUInt(&conversionStatus, 16);
if (!conversionStatus) {
throw Exception("Failed to parse offset from read memory map packet data");
}
this->length = packetSegments.at(1).toUInt(&conversionStatus, 16);
if (!conversionStatus) {
throw Exception("Failed to parse read length from read memory map packet data");
}
this->offset = StringService::toUint32(command.substr(0, delimiterPos), 16);
this->length = StringService::toUint32(command.substr(delimiterPos + 1), 16);
}
void ReadMemoryMap::handle(Gdb::DebugSession& debugSession, TargetControllerService& targetControllerService) {
void ReadMemoryMap::handle(
Gdb::DebugSession& debugSession,
const Gdb::TargetDescriptor& gdbTargetDescriptor,
const Targets::TargetDescriptor& targetDescriptor,
TargetControllerService& targetControllerService
) {
Logger::info("Handling ReadMemoryMap packet");
using Targets::TargetMemoryType;
const auto& memoryDescriptorsByType = debugSession.gdbTargetDescriptor.targetDescriptor.memoryDescriptorsByType;
const auto& ramDescriptor = memoryDescriptorsByType.at(TargetMemoryType::RAM);
const auto& flashDescriptor = memoryDescriptorsByType.at(TargetMemoryType::FLASH);
const auto eepromDescriptorIt = memoryDescriptorsByType.find(TargetMemoryType::EEPROM);
const auto eepromDescriptor = eepromDescriptorIt != memoryDescriptorsByType.end()
? std::optional(eepromDescriptorIt->second)
: std::nullopt;
const auto ramGdbOffset = debugSession.gdbTargetDescriptor.getMemoryOffset(
Targets::TargetMemoryType::RAM
);
const auto eepromGdbOffset = debugSession.gdbTargetDescriptor.getMemoryOffset(
Targets::TargetMemoryType::EEPROM
);
const auto flashGdbOffset = debugSession.gdbTargetDescriptor.getMemoryOffset(
Targets::TargetMemoryType::FLASH
);
/*
* We include register and EEPROM memory in our RAM section. This allows GDB to access registers and EEPROM
* data via memory read/write packets.
*
* Like SRAM, GDB applies an offset to EEPROM addresses. We account for that offset in our ramSectionSize.
*
* The SRAM and EEPROM offsets allow for a maximum of 65KB of SRAM. But that must also accommodate the
* register addresses, which can vary in size.
*
* As of writing this (Dec 2022), there are no 8-bit AVR targets on sale today, with 65KB+ of SRAM.
*/
const auto eepromEndAddress = eepromGdbOffset + (eepromDescriptor.has_value() ? eepromDescriptor->size() : 0);
const auto ramSectionSize = eepromEndAddress - ramGdbOffset;
const auto flashSize = flashDescriptor.size();
const auto flashPageSize = flashDescriptor.pageSize.value();
const auto ramSectionEndAddress = gdbTargetDescriptor.translateTargetMemoryAddress(
this->eepromMemorySegmentDescriptor.addressRange.endAddress,
this->eepromAddressSpaceDescriptor,
this->eepromMemorySegmentDescriptor
);
const auto ramSectionStartAddress = TargetDescriptor::SRAM_ADDRESS_MASK;
const auto ramSectionSize = ramSectionEndAddress - ramSectionStartAddress + 1;
const auto memoryMap =
std::string("<memory-map>")
+ "<memory type=\"ram\" start=\"" + std::to_string(ramGdbOffset) + "\" length=\"" + std::to_string(ramSectionSize) + "\"/>"
+ "<memory type=\"flash\" start=\"" + std::to_string(flashGdbOffset) + "\" length=\"" + std::to_string(flashSize) + "\">"
+ "<property name=\"blocksize\">" + std::to_string(flashPageSize) + "</property>"
std::string{"<memory-map>"}
+ "<memory type=\"ram\" start=\"" + std::to_string(ramSectionStartAddress) + "\" length=\"" + std::to_string(ramSectionSize) + "\"/>"
+ "<memory type=\"flash\" start=\"0\" length=\"" + std::to_string(this->programMemorySegmentDescriptor.size()) + "\">"
+ "<property name=\"blocksize\">" + std::to_string(this->programMemorySegmentDescriptor.pageSize.value()) + "</property>"
+ "</memory>"
+ "</memory-map>";
auto responseData = std::vector<unsigned char>{'l'};
if (this->offset < memoryMap.size() && this->length > 0) {
auto memoryMapData = std::vector<unsigned char>(
responseData.insert(
responseData.end(),
memoryMap.begin() + this->offset,
memoryMap.begin() + std::min(
static_cast<long>(this->offset + this->length),
static_cast<long>(memoryMap.size())
memoryMap.begin() + this->offset + std::min(
static_cast<long>(this->length),
static_cast<long>(memoryMap.size() - this->offset)
)
);
auto responseData = std::vector<unsigned char>({'l'});
std::move(memoryMapData.begin(), memoryMapData.end(), std::back_inserter(responseData));
debugSession.connection.writePacket(ResponsePacket(responseData));
return;
}
debugSession.connection.writePacket(ResponsePacket(std::vector<unsigned char>({'l'})));
debugSession.connection.writePacket(ResponsePacket{responseData});
}
}