Removed MemoryAccessCommandPacket class and moved GDB memory offsets to GDB TargetDescriptor class
This commit is contained in:
@@ -43,11 +43,11 @@ namespace Bloom::DebugServer::Gdb::AvrGdb
|
|||||||
|
|
||||||
if (rawPacket.size() >= 2) {
|
if (rawPacket.size() >= 2) {
|
||||||
if (rawPacket[1] == 'm') {
|
if (rawPacket[1] == 'm') {
|
||||||
return std::make_unique<ReadMemory>(rawPacket);
|
return std::make_unique<ReadMemory>(rawPacket, this->gdbTargetDescriptor.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawPacket[1] == 'M') {
|
if (rawPacket[1] == 'M') {
|
||||||
return std::make_unique<WriteMemory>(rawPacket);
|
return std::make_unique<WriteMemory>(rawPacket, this->gdbTargetDescriptor.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto rawPacketString = std::string(rawPacket.begin() + 1, rawPacket.end());
|
const auto rawPacketString = std::string(rawPacket.begin() + 1, rawPacket.end());
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
FlashDone::FlashDone(const RawPacketType& rawPacket)
|
FlashDone::FlashDone(const RawPacketType& rawPacket)
|
||||||
: MemoryAccessCommandPacket(rawPacket)
|
: CommandPacket(rawPacket)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void FlashDone::handle(DebugSession& debugSession, TargetControllerConsole& targetControllerConsole) {
|
void FlashDone::handle(DebugSession& debugSession, TargetControllerConsole& targetControllerConsole) {
|
||||||
|
|||||||
@@ -3,14 +3,17 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#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
|
namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The FlashDone class implements the structure for the "vFlashDone" packet.
|
* The FlashDone class implements the structure for the "vFlashDone" packet.
|
||||||
*/
|
*/
|
||||||
class FlashDone: public MemoryAccessCommandPacket
|
class FlashDone: public Gdb::CommandPackets::CommandPacket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit FlashDone(const RawPacketType& rawPacket);
|
explicit FlashDone(const RawPacketType& rawPacket);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
FlashErase::FlashErase(const RawPacketType& rawPacket)
|
FlashErase::FlashErase(const RawPacketType& rawPacket)
|
||||||
: MemoryAccessCommandPacket(rawPacket)
|
: CommandPacket(rawPacket)
|
||||||
{
|
{
|
||||||
const auto packetString = QString::fromLocal8Bit(
|
const auto packetString = QString::fromLocal8Bit(
|
||||||
reinterpret_cast<const char*>(this->data.data() + 12),
|
reinterpret_cast<const char*>(this->data.data() + 12),
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#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
|
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
|
* 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.
|
* 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:
|
public:
|
||||||
std::uint32_t startAddress = 0;
|
std::uint32_t startAddress = 0;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
FlashWrite::FlashWrite(const RawPacketType& rawPacket)
|
FlashWrite::FlashWrite(const RawPacketType& rawPacket)
|
||||||
: MemoryAccessCommandPacket(rawPacket)
|
: CommandPacket(rawPacket)
|
||||||
{
|
{
|
||||||
if (this->data.size() < 15) {
|
if (this->data.size() < 15) {
|
||||||
throw Exception("Invalid packet length");
|
throw Exception("Invalid packet length");
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#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
|
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
|
* 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.
|
* 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:
|
public:
|
||||||
std::uint32_t startAddress = 0;
|
std::uint32_t startAddress = 0;
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -15,8 +15,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
|
|
||||||
using Exceptions::Exception;
|
using Exceptions::Exception;
|
||||||
|
|
||||||
ReadMemory::ReadMemory(const RawPacketType& rawPacket)
|
ReadMemory::ReadMemory(const RawPacketType& rawPacket, const TargetDescriptor& gdbTargetDescriptor)
|
||||||
: MemoryAccessCommandPacket(rawPacket)
|
: CommandPacket(rawPacket)
|
||||||
{
|
{
|
||||||
if (this->data.size() < 4) {
|
if (this->data.size() < 4) {
|
||||||
throw Exception("Invalid packet length");
|
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");
|
throw Exception("Failed to parse start address from read memory packet data");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->memoryType = this->getMemoryTypeFromGdbAddress(gdbStartAddress);
|
this->memoryType = gdbTargetDescriptor.getMemoryTypeFromGdbAddress(gdbStartAddress);
|
||||||
this->startAddress = this->removeMemoryTypeIndicatorFromGdbAddress(gdbStartAddress);
|
this->startAddress = gdbStartAddress & ~(gdbTargetDescriptor.getMemoryOffset(this->memoryType));
|
||||||
|
|
||||||
this->bytes = packetSegments.at(1).toUInt(&conversionStatus, 16);
|
this->bytes = packetSegments.at(1).toUInt(&conversionStatus, 16);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#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
|
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
|
* 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.
|
* expected to read memory from the target and send it the client.
|
||||||
*/
|
*/
|
||||||
class ReadMemory: public MemoryAccessCommandPacket
|
class ReadMemory: public Gdb::CommandPackets::CommandPacket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +32,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
*/
|
*/
|
||||||
std::uint32_t bytes = 0;
|
std::uint32_t bytes = 0;
|
||||||
|
|
||||||
explicit ReadMemory(const RawPacketType& rawPacket);
|
explicit ReadMemory(const RawPacketType& rawPacket, const Gdb::TargetDescriptor& gdbTargetDescriptor);
|
||||||
|
|
||||||
void handle(
|
void handle(
|
||||||
DebugSession& debugSession,
|
DebugSession& debugSession,
|
||||||
|
|||||||
@@ -59,6 +59,14 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
const auto& ramDescriptor = memoryDescriptorsByType.at(TargetMemoryType::RAM);
|
const auto& ramDescriptor = memoryDescriptorsByType.at(TargetMemoryType::RAM);
|
||||||
const auto& flashDescriptor = memoryDescriptorsByType.at(TargetMemoryType::FLASH);
|
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.
|
// 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 ramSize = ramDescriptor.size() + ramDescriptor.addressRange.startAddress;
|
||||||
const auto flashSize = flashDescriptor.size();
|
const auto flashSize = flashDescriptor.size();
|
||||||
@@ -66,8 +74,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
|
|
||||||
const auto memoryMap =
|
const auto memoryMap =
|
||||||
std::string("<memory-map>")
|
std::string("<memory-map>")
|
||||||
+ "<memory type=\"ram\" start=\"0x800000\" length=\"" + std::to_string(ramSize) + "\"/>"
|
+ "<memory type=\"ram\" start=\"" + std::to_string(ramGdbOffset) + "\" length=\"" + std::to_string(ramSize) + "\"/>"
|
||||||
+ "<memory type=\"flash\" start=\"0\" length=\"" + std::to_string(flashSize) + "\">"
|
+ "<memory type=\"flash\" start=\"" + std::to_string(flashGdbOffset) + "\" length=\"" + std::to_string(flashSize) + "\">"
|
||||||
+ "<property name=\"blocksize\">" + std::to_string(flashPageSize) + "</property>"
|
+ "<property name=\"blocksize\">" + std::to_string(flashPageSize) + "</property>"
|
||||||
+ "</memory>"
|
+ "</memory>"
|
||||||
+ "</memory-map>";
|
+ "</memory-map>";
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
|
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
WriteMemory::WriteMemory(const RawPacketType& rawPacket)
|
WriteMemory::WriteMemory(const RawPacketType& rawPacket, const TargetDescriptor& gdbTargetDescriptor)
|
||||||
: MemoryAccessCommandPacket(rawPacket)
|
: CommandPacket(rawPacket)
|
||||||
{
|
{
|
||||||
if (this->data.size() < 4) {
|
if (this->data.size() < 4) {
|
||||||
throw Exception("Invalid packet length");
|
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");
|
throw Exception("Failed to parse start address from write memory packet data");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->memoryType = this->getMemoryTypeFromGdbAddress(gdbStartAddress);
|
this->memoryType = gdbTargetDescriptor.getMemoryTypeFromGdbAddress(gdbStartAddress);
|
||||||
this->startAddress = this->removeMemoryTypeIndicatorFromGdbAddress(gdbStartAddress);
|
this->startAddress = gdbStartAddress & ~(gdbTargetDescriptor.getMemoryOffset(this->memoryType));
|
||||||
|
|
||||||
auto lengthAndBufferSegments = packetSegments.at(1).split(":");
|
auto lengthAndBufferSegments = packetSegments.at(1).split(":");
|
||||||
if (lengthAndBufferSegments.size() != 2) {
|
if (lengthAndBufferSegments.size() != 2) {
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#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
|
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
|
* 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.
|
* 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:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +32,7 @@ namespace Bloom::DebugServer::Gdb::AvrGdb::CommandPackets
|
|||||||
*/
|
*/
|
||||||
Targets::TargetMemoryBuffer buffer;
|
Targets::TargetMemoryBuffer buffer;
|
||||||
|
|
||||||
explicit WriteMemory(const RawPacketType& rawPacket);
|
explicit WriteMemory(const RawPacketType& rawPacket, const Gdb::TargetDescriptor& gdbTargetDescriptor);
|
||||||
|
|
||||||
void handle(
|
void handle(
|
||||||
DebugSession& debugSession,
|
DebugSession& debugSession,
|
||||||
|
|||||||
@@ -13,7 +13,13 @@ namespace Bloom::DebugServer::Gdb::AvrGdb
|
|||||||
using Bloom::Exceptions::Exception;
|
using Bloom::Exceptions::Exception;
|
||||||
|
|
||||||
TargetDescriptor::TargetDescriptor(const Bloom::Targets::TargetDescriptor& targetDescriptor)
|
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();
|
this->loadRegisterMappings();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "src/Helpers/BiMap.hpp"
|
||||||
#include "src/Targets/TargetDescriptor.hpp"
|
#include "src/Targets/TargetDescriptor.hpp"
|
||||||
#include "src/Targets/TargetRegister.hpp"
|
#include "src/Targets/TargetRegister.hpp"
|
||||||
|
#include "src/Targets/TargetMemory.hpp"
|
||||||
|
|
||||||
#include "RegisterDescriptor.hpp"
|
#include "RegisterDescriptor.hpp"
|
||||||
|
|
||||||
@@ -14,14 +17,41 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
/**
|
/**
|
||||||
* GDB target descriptor.
|
* GDB target descriptor.
|
||||||
*/
|
*/
|
||||||
struct TargetDescriptor
|
class TargetDescriptor
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
Targets::TargetDescriptor targetDescriptor;
|
Targets::TargetDescriptor targetDescriptor;
|
||||||
|
|
||||||
explicit TargetDescriptor(const Targets::TargetDescriptor& targetDescriptor)
|
explicit TargetDescriptor(
|
||||||
|
const Targets::TargetDescriptor& targetDescriptor,
|
||||||
|
const BiMap<Targets::TargetMemoryType, std::uint32_t>& memoryOffsetsByType
|
||||||
|
)
|
||||||
: targetDescriptor(targetDescriptor)
|
: 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
|
* 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.
|
* register descriptor isn't mapped to any GDB register.
|
||||||
@@ -57,5 +87,9 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual const std::vector<GdbRegisterNumberType>& getRegisterNumbers() const = 0;
|
virtual const std::vector<GdbRegisterNumberType>& getRegisterNumbers() const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BiMap<Targets::TargetMemoryType, std::uint32_t> memoryOffsetsByType;
|
||||||
|
std::set<std::uint32_t> memoryOffsets;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace Bloom
|
namespace Bloom
|
||||||
{
|
{
|
||||||
@@ -67,6 +68,26 @@ namespace Bloom
|
|||||||
return this->map;
|
return this->map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::set<TypeB> getKeys() const {
|
||||||
|
auto keys = std::set<TypeB>();
|
||||||
|
|
||||||
|
for (const auto& [key, value] : this->map) {
|
||||||
|
keys.insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::set<TypeB> getValues() const {
|
||||||
|
auto values = std::set<TypeB>();
|
||||||
|
|
||||||
|
for (const auto& [key, value] : this->map) {
|
||||||
|
values.insert(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
void insert(const std::pair<TypeA, TypeB>& pair) {
|
void insert(const std::pair<TypeA, TypeB>& pair) {
|
||||||
auto insertResultPair = this->map.insert(pair);
|
auto insertResultPair = this->map.insert(pair);
|
||||||
this->flippedMap.insert(std::pair<TypeB, TypeA>(pair.second, pair.first));
|
this->flippedMap.insert(std::pair<TypeB, TypeA>(pair.second, pair.first));
|
||||||
|
|||||||
Reference in New Issue
Block a user