From 2ae378613088658139a002ee8f679b0c6470ab43 Mon Sep 17 00:00:00 2001 From: Nav Date: Tue, 30 Aug 2022 02:04:35 +0100 Subject: [PATCH] Removed MemoryAccessCommandPacket class and moved GDB memory offsets to GDB TargetDescriptor class --- src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp | 4 +- .../Gdb/AvrGdb/CommandPackets/FlashDone.cpp | 2 +- .../Gdb/AvrGdb/CommandPackets/FlashDone.hpp | 7 ++- .../Gdb/AvrGdb/CommandPackets/FlashErase.cpp | 2 +- .../Gdb/AvrGdb/CommandPackets/FlashErase.hpp | 7 ++- .../Gdb/AvrGdb/CommandPackets/FlashWrite.cpp | 2 +- .../Gdb/AvrGdb/CommandPackets/FlashWrite.hpp | 7 ++- .../MemoryAccessCommandPacket.hpp | 62 ------------------- .../Gdb/AvrGdb/CommandPackets/ReadMemory.cpp | 8 +-- .../Gdb/AvrGdb/CommandPackets/ReadMemory.hpp | 9 ++- .../AvrGdb/CommandPackets/ReadMemoryMap.cpp | 12 +++- .../Gdb/AvrGdb/CommandPackets/WriteMemory.cpp | 8 +-- .../Gdb/AvrGdb/CommandPackets/WriteMemory.hpp | 9 ++- .../Gdb/AvrGdb/TargetDescriptor.cpp | 8 ++- src/DebugServer/Gdb/TargetDescriptor.hpp | 38 +++++++++++- src/Helpers/BiMap.hpp | 21 +++++++ 16 files changed, 114 insertions(+), 92 deletions(-) delete mode 100644 src/DebugServer/Gdb/AvrGdb/CommandPackets/MemoryAccessCommandPacket.hpp diff --git a/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp b/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp index 8fe6f1ba..4ee0e89f 100644 --- a/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp +++ b/src/DebugServer/Gdb/AvrGdb/AvrGdbRsp.cpp @@ -43,11 +43,11 @@ namespace Bloom::DebugServer::Gdb::AvrGdb if (rawPacket.size() >= 2) { if (rawPacket[1] == 'm') { - return std::make_unique(rawPacket); + return std::make_unique(rawPacket, this->gdbTargetDescriptor.value()); } if (rawPacket[1] == 'M') { - return std::make_unique(rawPacket); + return std::make_unique(rawPacket, this->gdbTargetDescriptor.value()); } const auto rawPacketString = std::string(rawPacket.begin() + 1, rawPacket.end()); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp index bf4a0d99..d3f0eb6b 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.cpp @@ -16,7 +16,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets using namespace Bloom::Exceptions; FlashDone::FlashDone(const RawPacketType& rawPacket) - : MemoryAccessCommandPacket(rawPacket) + : CommandPacket(rawPacket) {} void FlashDone::handle(DebugSession& debugSession, TargetControllerConsole& targetControllerConsole) { diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp index af31b8b3..d7b1aa33 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashDone.hpp @@ -3,14 +3,17 @@ #include #include -#include "MemoryAccessCommandPacket.hpp" +#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "src/DebugServer/Gdb/TargetDescriptor.hpp" + +#include "src/Targets/TargetMemory.hpp" namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets { /** * The FlashDone class implements the structure for the "vFlashDone" packet. */ - class FlashDone: public MemoryAccessCommandPacket + class FlashDone: public Gdb::CommandPackets::CommandPacket { public: explicit FlashDone(const RawPacketType& rawPacket); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp index cdf42090..8da7b47d 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.cpp @@ -16,7 +16,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets using namespace Bloom::Exceptions; FlashErase::FlashErase(const RawPacketType& rawPacket) - : MemoryAccessCommandPacket(rawPacket) + : CommandPacket(rawPacket) { const auto packetString = QString::fromLocal8Bit( reinterpret_cast(this->data.data() + 12), diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp index 9825a44c..9dd4693d 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashErase.hpp @@ -3,7 +3,10 @@ #include #include -#include "MemoryAccessCommandPacket.hpp" +#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "src/DebugServer/Gdb/TargetDescriptor.hpp" + +#include "src/Targets/TargetMemory.hpp" namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets { @@ -11,7 +14,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets * The FlashErase class implements the structure for the "vFlashErase" packet. Upon receiving this packet, the * server is expected to erase a particular region of the target's flash memory. */ - class FlashErase: public MemoryAccessCommandPacket + class FlashErase: public Gdb::CommandPackets::CommandPacket { public: std::uint32_t startAddress = 0; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp index e8a0dd17..87d62a10 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.cpp @@ -18,7 +18,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets using namespace Bloom::Exceptions; FlashWrite::FlashWrite(const RawPacketType& rawPacket) - : MemoryAccessCommandPacket(rawPacket) + : CommandPacket(rawPacket) { if (this->data.size() < 15) { throw Exception("Invalid packet length"); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp index ea320fe5..83a2b8bc 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/FlashWrite.hpp @@ -3,7 +3,10 @@ #include #include -#include "MemoryAccessCommandPacket.hpp" +#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "src/DebugServer/Gdb/TargetDescriptor.hpp" + +#include "src/Targets/TargetMemory.hpp" namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets { @@ -11,7 +14,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets * The FlashWrite class implements the structure for the "vFlashWrite" packet. Upon receiving this packet, the * server is expected to write to a particular region of the target's flash memory. */ - class FlashWrite: public MemoryAccessCommandPacket + class FlashWrite: public Gdb::CommandPackets::CommandPacket { public: std::uint32_t startAddress = 0; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/MemoryAccessCommandPacket.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/MemoryAccessCommandPacket.hpp deleted file mode 100644 index 66b6307a..00000000 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/MemoryAccessCommandPacket.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include -#include - -#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" - -#include "src/Targets/TargetMemory.hpp" - -namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets -{ - /** - * The MemoryAccessCommandPacket class is a base class for memory access GDB commands that are specific to the AVR - * architecture. - * - * With the GDB implementation for the AVR architecture, read/write memory commands include a special memory - * address. The memory type (FLASH, RAM, EEPROM, etc) is embedded within the 7 most significant bits of the second - * most significant byte of the memory address. - * - * This class provides functions to extract and remove the memory type from a given memory address. - */ - class MemoryAccessCommandPacket: public Bloom::DebugServer::Gdb::CommandPackets::CommandPacket - { - public: - explicit MemoryAccessCommandPacket(const RawPacketType& rawPacket) - : CommandPacket(rawPacket) - {}; - - protected: - /** - * The mask used by the AVR GDB client to encode the memory type into memory addresses. - */ - static constexpr std::uint32_t AVR_GDB_MEMORY_ADDRESS_MASK = 0x00FE0000U; - - /** - * avr-gdb uses the most significant 15 bits in memory addresses to indicate the type of memory being - * addressed. - * - * @param address - * @return - */ - Targets::TargetMemoryType getMemoryTypeFromGdbAddress(std::uint32_t address) { - if ((address & MemoryAccessCommandPacket::AVR_GDB_MEMORY_ADDRESS_MASK) != 0U) { - return Targets::TargetMemoryType::RAM; - } - - return Targets::TargetMemoryType::FLASH; - } - - /** - * Strips the most significant 15 bits from a GDB memory address. - * - * @param address - * @return - */ - std::uint32_t removeMemoryTypeIndicatorFromGdbAddress(std::uint32_t address) { - return (address & MemoryAccessCommandPacket::AVR_GDB_MEMORY_ADDRESS_MASK) != 0U - ? (address & ~(MemoryAccessCommandPacket::AVR_GDB_MEMORY_ADDRESS_MASK)) - : address; - } - }; -} diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp index 4a0dca3a..6c0d2cd8 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.cpp @@ -15,8 +15,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets using Exceptions::Exception; - ReadMemory::ReadMemory(const RawPacketType& rawPacket) - : MemoryAccessCommandPacket(rawPacket) + ReadMemory::ReadMemory(const RawPacketType& rawPacket, const TargetDescriptor& gdbTargetDescriptor) + : CommandPacket(rawPacket) { if (this->data.size() < 4) { throw Exception("Invalid packet length"); @@ -46,8 +46,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets throw Exception("Failed to parse start address from read memory packet data"); } - this->memoryType = this->getMemoryTypeFromGdbAddress(gdbStartAddress); - this->startAddress = this->removeMemoryTypeIndicatorFromGdbAddress(gdbStartAddress); + this->memoryType = gdbTargetDescriptor.getMemoryTypeFromGdbAddress(gdbStartAddress); + this->startAddress = gdbStartAddress & ~(gdbTargetDescriptor.getMemoryOffset(this->memoryType)); this->bytes = packetSegments.at(1).toUInt(&conversionStatus, 16); diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp index 9ad58859..12e1cb31 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemory.hpp @@ -3,7 +3,10 @@ #include #include -#include "MemoryAccessCommandPacket.hpp" +#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "src/DebugServer/Gdb/TargetDescriptor.hpp" + +#include "src/Targets/TargetMemory.hpp" namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets { @@ -11,7 +14,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets * The ReadMemory class implements a structure for "m" packets. Upon receiving these packets, the server is * expected to read memory from the target and send it the client. */ - class ReadMemory: public MemoryAccessCommandPacket + class ReadMemory: public Gdb::CommandPackets::CommandPacket { public: /** @@ -29,7 +32,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets */ std::uint32_t bytes = 0; - explicit ReadMemory(const RawPacketType& rawPacket); + explicit ReadMemory(const RawPacketType& rawPacket, const Gdb::TargetDescriptor& gdbTargetDescriptor); void handle( DebugSession& debugSession, diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp index 599c4b55..f43794ec 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/ReadMemoryMap.cpp @@ -59,6 +59,14 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets const auto& ramDescriptor = memoryDescriptorsByType.at(TargetMemoryType::RAM); const auto& flashDescriptor = memoryDescriptorsByType.at(TargetMemoryType::FLASH); + const auto ramGdbOffset = debugSession.gdbTargetDescriptor.getMemoryOffset( + Targets::TargetMemoryType::RAM + ); + + const auto flashGdbOffset = debugSession.gdbTargetDescriptor.getMemoryOffset( + Targets::TargetMemoryType::FLASH + ); + // We include the start address in ramSize to account for AVR registers in the data address space. const auto ramSize = ramDescriptor.size() + ramDescriptor.addressRange.startAddress; const auto flashSize = flashDescriptor.size(); @@ -66,8 +74,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets const auto memoryMap = std::string("") - + "" - + "" + + "" + + "" + "" + std::to_string(flashPageSize) + "" + "" + ""; diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp index abcdd954..0d91657d 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.cpp @@ -15,8 +15,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets using namespace Bloom::Exceptions; - WriteMemory::WriteMemory(const RawPacketType& rawPacket) - : MemoryAccessCommandPacket(rawPacket) + WriteMemory::WriteMemory(const RawPacketType& rawPacket, const TargetDescriptor& gdbTargetDescriptor) + : CommandPacket(rawPacket) { if (this->data.size() < 4) { throw Exception("Invalid packet length"); @@ -45,8 +45,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets throw Exception("Failed to parse start address from write memory packet data"); } - this->memoryType = this->getMemoryTypeFromGdbAddress(gdbStartAddress); - this->startAddress = this->removeMemoryTypeIndicatorFromGdbAddress(gdbStartAddress); + this->memoryType = gdbTargetDescriptor.getMemoryTypeFromGdbAddress(gdbStartAddress); + this->startAddress = gdbStartAddress & ~(gdbTargetDescriptor.getMemoryOffset(this->memoryType)); auto lengthAndBufferSegments = packetSegments.at(1).split(":"); if (lengthAndBufferSegments.size() != 2) { diff --git a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp index 328b8c58..9389095e 100644 --- a/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp +++ b/src/DebugServer/Gdb/AvrGdb/CommandPackets/WriteMemory.hpp @@ -3,7 +3,10 @@ #include #include -#include "MemoryAccessCommandPacket.hpp" +#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp" +#include "src/DebugServer/Gdb/TargetDescriptor.hpp" + +#include "src/Targets/TargetMemory.hpp" namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets { @@ -11,7 +14,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets * The WriteMemory class implements the structure for "M" packets. Upon receiving this packet, the server is * expected to write data to the target's memory, at the specified start address. */ - class WriteMemory: public MemoryAccessCommandPacket + class WriteMemory: public Gdb::CommandPackets::CommandPacket { public: /** @@ -29,7 +32,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets */ Targets::TargetMemoryBuffer buffer; - explicit WriteMemory(const RawPacketType& rawPacket); + explicit WriteMemory(const RawPacketType& rawPacket, const Gdb::TargetDescriptor& gdbTargetDescriptor); void handle( DebugSession& debugSession, diff --git a/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.cpp b/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.cpp index 42832e35..4695992a 100644 --- a/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.cpp +++ b/src/DebugServer/Gdb/AvrGdb/TargetDescriptor.cpp @@ -13,7 +13,13 @@ namespace Bloom::DebugServer::Gdb::AvrGdb using Bloom::Exceptions::Exception; TargetDescriptor::TargetDescriptor(const Bloom::Targets::TargetDescriptor& targetDescriptor) - : DebugServer::Gdb::TargetDescriptor(targetDescriptor) + : DebugServer::Gdb::TargetDescriptor( + targetDescriptor, + { + {Targets::TargetMemoryType::FLASH, 0}, + {Targets::TargetMemoryType::RAM, 0x00800000U}, + } + ) { this->loadRegisterMappings(); } diff --git a/src/DebugServer/Gdb/TargetDescriptor.hpp b/src/DebugServer/Gdb/TargetDescriptor.hpp index 390a053e..0676bf6d 100644 --- a/src/DebugServer/Gdb/TargetDescriptor.hpp +++ b/src/DebugServer/Gdb/TargetDescriptor.hpp @@ -3,9 +3,12 @@ #include #include #include +#include +#include "src/Helpers/BiMap.hpp" #include "src/Targets/TargetDescriptor.hpp" #include "src/Targets/TargetRegister.hpp" +#include "src/Targets/TargetMemory.hpp" #include "RegisterDescriptor.hpp" @@ -14,14 +17,41 @@ namespace Bloom::DebugServer::Gdb /** * GDB target descriptor. */ - struct TargetDescriptor + class TargetDescriptor { + public: Targets::TargetDescriptor targetDescriptor; - explicit TargetDescriptor(const Targets::TargetDescriptor& targetDescriptor) + explicit TargetDescriptor( + const Targets::TargetDescriptor& targetDescriptor, + const BiMap& memoryOffsetsByType + ) : targetDescriptor(targetDescriptor) + , memoryOffsetsByType(memoryOffsetsByType) + , memoryOffsets(memoryOffsetsByType.getValues()) {} + virtual ~TargetDescriptor() = default; + + virtual std::uint32_t getMemoryOffset(Targets::TargetMemoryType memoryType) const { + return this->memoryOffsetsByType.valueAt(memoryType).value_or(0); + } + + Targets::TargetMemoryType getMemoryTypeFromGdbAddress(std::uint32_t address) const { + // Start with the largest offset until we find a match + for ( + auto memoryOffsetIt = this->memoryOffsets.rbegin(); + memoryOffsetIt != this->memoryOffsets.rend(); + ++memoryOffsetIt + ) { + if ((address & *memoryOffsetIt) != 0U) { + return this->memoryOffsetsByType.at(*memoryOffsetIt); + } + } + + return Targets::TargetMemoryType::FLASH; + } + /** * Should retrieve the GDB register number, given a target register descriptor. Or std::nullopt if the target * register descriptor isn't mapped to any GDB register. @@ -57,5 +87,9 @@ namespace Bloom::DebugServer::Gdb * @return */ virtual const std::vector& getRegisterNumbers() const = 0; + + private: + BiMap memoryOffsetsByType; + std::set memoryOffsets; }; } diff --git a/src/Helpers/BiMap.hpp b/src/Helpers/BiMap.hpp index 70a101ed..f6c723ee 100644 --- a/src/Helpers/BiMap.hpp +++ b/src/Helpers/BiMap.hpp @@ -2,6 +2,7 @@ #include #include +#include namespace Bloom { @@ -67,6 +68,26 @@ namespace Bloom return this->map; } + [[nodiscard]] std::set getKeys() const { + auto keys = std::set(); + + for (const auto& [key, value] : this->map) { + keys.insert(key); + } + + return keys; + } + + [[nodiscard]] std::set getValues() const { + auto values = std::set(); + + for (const auto& [key, value] : this->map) { + values.insert(value); + } + + return values; + } + void insert(const std::pair& pair) { auto insertResultPair = this->map.insert(pair); this->flippedMap.insert(std::pair(pair.second, pair.first));