WCH RISC-V software breakpoints, and a few other bits of refactoring/tidying
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
#include "CommandPackets/ReadMemory.hpp"
|
||||
#include "CommandPackets/WriteMemory.hpp"
|
||||
#include "CommandPackets/ReadMemoryMap.hpp"
|
||||
#include "CommandPackets/SetBreakpoint.hpp"
|
||||
#include "CommandPackets/RemoveBreakpoint.hpp"
|
||||
#include "CommandPackets/FlashErase.hpp"
|
||||
#include "CommandPackets/FlashWrite.hpp"
|
||||
#include "CommandPackets/FlashDone.hpp"
|
||||
@@ -56,6 +58,8 @@ namespace DebugServer::Gdb::AvrGdb
|
||||
using CommandPackets::ReadMemory;
|
||||
using CommandPackets::WriteMemory;
|
||||
using CommandPackets::ReadMemoryMap;
|
||||
using CommandPackets::SetBreakpoint;
|
||||
using CommandPackets::RemoveBreakpoint;
|
||||
using CommandPackets::FlashErase;
|
||||
using CommandPackets::FlashWrite;
|
||||
using CommandPackets::FlashDone;
|
||||
@@ -87,6 +91,14 @@ namespace DebugServer::Gdb::AvrGdb
|
||||
return std::make_unique<WriteMemory>(rawPacket, this->gdbTargetDescriptor);
|
||||
}
|
||||
|
||||
if (rawPacket[1] == 'Z') {
|
||||
return std::make_unique<SetBreakpoint>(rawPacket);
|
||||
}
|
||||
|
||||
if (rawPacket[1] == 'z') {
|
||||
return std::make_unique<RemoveBreakpoint>(rawPacket);
|
||||
}
|
||||
|
||||
if (rawPacket.size() > 1) {
|
||||
const auto rawPacketString = std::string{rawPacket.begin() + 1, rawPacket.end()};
|
||||
|
||||
@@ -161,7 +173,12 @@ namespace DebugServer::Gdb::AvrGdb
|
||||
*
|
||||
* We need to figure out why, and determine whether the stop should be reported to GDB.
|
||||
*/
|
||||
if (this->debugSession->externalBreakpointsByAddress.contains(programAddress)) {
|
||||
if (
|
||||
this->debugSession->externalBreakpointRegistry.contains(
|
||||
activeRangeSteppingSession->addressSpaceDescriptor.id,
|
||||
programAddress
|
||||
)
|
||||
) {
|
||||
/*
|
||||
* The target stopped due to an external breakpoint, set by GDB.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "RemoveBreakpoint.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/OkResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/EmptyResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
|
||||
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::AvrGdb::CommandPackets
|
||||
{
|
||||
using Services::TargetControllerService;
|
||||
|
||||
using ResponsePackets::OkResponsePacket;
|
||||
using ResponsePackets::ErrorResponsePacket;
|
||||
using ResponsePackets::EmptyResponsePacket;
|
||||
|
||||
using ::Exceptions::Exception;
|
||||
|
||||
RemoveBreakpoint::RemoveBreakpoint(const RawPacket& rawPacket)
|
||||
: CommandPacket(rawPacket)
|
||||
{
|
||||
const auto packetString = std::string{this->data.begin(), this->data.end()};
|
||||
|
||||
if (packetString.size() < 6) {
|
||||
throw Exception{"Unexpected RemoveBreakpoint packet size"};
|
||||
}
|
||||
|
||||
this->type = (packetString[1] == '0')
|
||||
? BreakpointType::SOFTWARE_BREAKPOINT
|
||||
: (packetString[1] == '1') ? BreakpointType::HARDWARE_BREAKPOINT : BreakpointType::UNKNOWN;
|
||||
|
||||
const auto firstCommaPos = packetString.find_first_of(',');
|
||||
const auto secondCommaPos = packetString.find_first_of(',', firstCommaPos + 1);
|
||||
if (firstCommaPos == std::string::npos || secondCommaPos == std::string::npos) {
|
||||
throw Exception{"Invalid RemoveBreakpoint packet"};
|
||||
}
|
||||
|
||||
const auto addressString = packetString.substr(firstCommaPos + 1, secondCommaPos - firstCommaPos - 1);
|
||||
const auto sizeString = packetString.substr(
|
||||
secondCommaPos + 1,
|
||||
packetString.find_first_of(';', secondCommaPos) - secondCommaPos - 1
|
||||
);
|
||||
|
||||
this->address = Services::StringService::toUint32(addressString, 16);
|
||||
this->size = Services::StringService::toUint32(sizeString, 10);
|
||||
}
|
||||
|
||||
void RemoveBreakpoint::handle(
|
||||
DebugSession& debugSession,
|
||||
const AvrGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor&,
|
||||
TargetControllerService& targetControllerService
|
||||
) {
|
||||
Logger::info("Handling RemoveBreakpoint packet");
|
||||
|
||||
try {
|
||||
debugSession.removeExternalBreakpoint(
|
||||
gdbTargetDescriptor.programAddressSpaceDescriptor,
|
||||
this->address,
|
||||
targetControllerService
|
||||
);
|
||||
debugSession.connection.writePacket(OkResponsePacket{});
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
Logger::error("Failed to remove breakpoint on target - " + exception.getMessage());
|
||||
debugSession.connection.writePacket(ErrorResponsePacket{});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "AvrGdbCommandPacketInterface.hpp"
|
||||
#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp"
|
||||
#include "src/DebugServer/Gdb/BreakpointType.hpp"
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::AvrGdb::CommandPackets
|
||||
{
|
||||
/**
|
||||
* The RemoveBreakpoint class implements the structure for "Z" command packets. Upon receiving this command, the
|
||||
* server is expected to set a breakpoint at the specified address.
|
||||
*/
|
||||
class RemoveBreakpoint
|
||||
: public CommandPackets::AvrGdbCommandPacketInterface
|
||||
, private Gdb::CommandPackets::CommandPacket
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The requested breakpoint type.
|
||||
*
|
||||
* We don't actually honor this. GDB assumes flash memory cannot be written to outside of a programming
|
||||
* session, so it refuses to even attempt to insert software breakpoints in flash memory. It always requests
|
||||
* hardware breakpoints. This is why ignore the requested breakpoint type and just insert whatever type we can.
|
||||
*/
|
||||
BreakpointType type = BreakpointType::UNKNOWN;
|
||||
Targets::TargetMemoryAddress address = 0;
|
||||
Targets::TargetMemorySize size = 0;
|
||||
|
||||
explicit RemoveBreakpoint(const RawPacket& rawPacket);
|
||||
|
||||
void handle(
|
||||
DebugSession& debugSession,
|
||||
const AvrGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) override;
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "SetBreakpoint.hpp"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <string>
|
||||
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/OkResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/EmptyResponsePacket.hpp"
|
||||
@@ -8,15 +8,15 @@
|
||||
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::CommandPackets
|
||||
namespace DebugServer::Gdb::AvrGdb::CommandPackets
|
||||
{
|
||||
using Services::TargetControllerService;
|
||||
|
||||
using Targets::TargetBreakpoint;
|
||||
|
||||
using ResponsePackets::OkResponsePacket;
|
||||
using ResponsePackets::ErrorResponsePacket;
|
||||
using ResponsePackets::EmptyResponsePacket;
|
||||
@@ -26,36 +26,36 @@ namespace DebugServer::Gdb::CommandPackets
|
||||
SetBreakpoint::SetBreakpoint(const RawPacket& rawPacket)
|
||||
: CommandPacket(rawPacket)
|
||||
{
|
||||
if (this->data.size() < 6) {
|
||||
const auto packetString = std::string{this->data.begin(), this->data.end()};
|
||||
|
||||
if (packetString.size() < 6) {
|
||||
throw Exception{"Unexpected SetBreakpoint packet size"};
|
||||
}
|
||||
|
||||
// Z0 = SW breakpoint, Z1 = HW breakpoint
|
||||
this->type = (this->data[1] == '0')
|
||||
this->type = (packetString[1] == '0')
|
||||
? BreakpointType::SOFTWARE_BREAKPOINT
|
||||
: (this->data[1] == '1') ? BreakpointType::HARDWARE_BREAKPOINT : BreakpointType::UNKNOWN;
|
||||
: (packetString[1] == '1') ? BreakpointType::HARDWARE_BREAKPOINT : BreakpointType::UNKNOWN;
|
||||
|
||||
auto packetData = QString::fromLocal8Bit(
|
||||
reinterpret_cast<const char*>(this->data.data() + 2),
|
||||
static_cast<int>(this->data.size() - 2)
|
||||
const auto firstCommaPos = packetString.find_first_of(',');
|
||||
const auto secondCommaPos = packetString.find_first_of(',', firstCommaPos + 1);
|
||||
if (firstCommaPos == std::string::npos || secondCommaPos == std::string::npos) {
|
||||
throw Exception{"Invalid SetBreakpoint packet"};
|
||||
}
|
||||
|
||||
const auto addressString = packetString.substr(firstCommaPos + 1, secondCommaPos - firstCommaPos - 1);
|
||||
const auto sizeString = packetString.substr(
|
||||
secondCommaPos + 1,
|
||||
packetString.find_first_of(';', secondCommaPos) - secondCommaPos - 1
|
||||
);
|
||||
|
||||
auto packetSegments = packetData.split(",");
|
||||
if (packetSegments.size() < 3) {
|
||||
throw Exception{"Unexpected number of packet segments in SetBreakpoint packet"};
|
||||
}
|
||||
|
||||
bool conversionStatus = true;
|
||||
this->address = packetSegments.at(1).toUInt(&conversionStatus, 16);
|
||||
|
||||
if (!conversionStatus) {
|
||||
throw Exception{"Failed to convert address hex value from SetBreakpoint packet."};
|
||||
}
|
||||
this->address = Services::StringService::toUint32(addressString, 16);
|
||||
this->size = Services::StringService::toUint32(sizeString, 10);
|
||||
}
|
||||
|
||||
void SetBreakpoint::handle(
|
||||
DebugSession& debugSession,
|
||||
const TargetDescriptor& gdbTargetDescriptor,
|
||||
const AvrGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor&,
|
||||
TargetControllerService& targetControllerService
|
||||
) {
|
||||
@@ -71,7 +71,11 @@ namespace DebugServer::Gdb::CommandPackets
|
||||
return;
|
||||
}
|
||||
|
||||
debugSession.setExternalBreakpoint(this->address, targetControllerService);
|
||||
debugSession.setExternalBreakpoint(
|
||||
gdbTargetDescriptor.programAddressSpaceDescriptor,
|
||||
gdbTargetDescriptor.programMemorySegmentDescriptor,
|
||||
this->address, this->size, targetControllerService
|
||||
);
|
||||
debugSession.connection.writePacket(OkResponsePacket{});
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
31
src/DebugServer/Gdb/AvrGdb/CommandPackets/SetBreakpoint.hpp
Normal file
31
src/DebugServer/Gdb/AvrGdb/CommandPackets/SetBreakpoint.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "AvrGdbCommandPacketInterface.hpp"
|
||||
#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp"
|
||||
#include "src/DebugServer/Gdb/BreakpointType.hpp"
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::AvrGdb::CommandPackets
|
||||
{
|
||||
class SetBreakpoint
|
||||
: public CommandPackets::AvrGdbCommandPacketInterface
|
||||
, private Gdb::CommandPackets::CommandPacket
|
||||
{
|
||||
public:
|
||||
BreakpointType type = BreakpointType::UNKNOWN;
|
||||
Targets::TargetMemoryAddress address = 0;
|
||||
Targets::TargetMemorySize size = 0;
|
||||
|
||||
explicit SetBreakpoint(const RawPacket& rawPacket);
|
||||
|
||||
void handle(
|
||||
DebugSession& debugSession,
|
||||
const AvrGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) override;
|
||||
};
|
||||
}
|
||||
@@ -84,7 +84,12 @@ namespace DebugServer::Gdb::AvrGdb::CommandPackets
|
||||
return;
|
||||
}
|
||||
|
||||
auto rangeSteppingSession = RangeSteppingSession{stepAddressRange, {}};
|
||||
auto rangeSteppingSession = RangeSteppingSession{
|
||||
gdbTargetDescriptor.programAddressSpaceDescriptor,
|
||||
gdbTargetDescriptor.programMemorySegmentDescriptor,
|
||||
stepAddressRange,
|
||||
{}
|
||||
};
|
||||
|
||||
const auto instructionsByAddress = Decoder::decode(
|
||||
stepAddressRange.startAddress,
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "RemoveBreakpoint.hpp"
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/OkResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
|
||||
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::CommandPackets
|
||||
{
|
||||
using Services::TargetControllerService;
|
||||
|
||||
using Targets::TargetBreakpoint;
|
||||
|
||||
using ResponsePackets::OkResponsePacket;
|
||||
using ResponsePackets::ErrorResponsePacket;
|
||||
|
||||
using ::Exceptions::Exception;
|
||||
|
||||
RemoveBreakpoint::RemoveBreakpoint(const RawPacket& rawPacket)
|
||||
: CommandPacket(rawPacket)
|
||||
{
|
||||
if (this->data.size() < 6) {
|
||||
throw Exception{"Unexpected RemoveBreakpoint packet size"};
|
||||
}
|
||||
|
||||
// z0 = SW breakpoint, z1 = HW breakpoint
|
||||
this->type = (this->data[1] == '0')
|
||||
? BreakpointType::SOFTWARE_BREAKPOINT
|
||||
: (this->data[1] == '1') ? BreakpointType::HARDWARE_BREAKPOINT : BreakpointType::UNKNOWN;
|
||||
|
||||
const auto packetData = QString::fromLocal8Bit(
|
||||
reinterpret_cast<const char*>(this->data.data() + 2),
|
||||
static_cast<int>(this->data.size() - 2)
|
||||
);
|
||||
|
||||
auto packetSegments = packetData.split(",");
|
||||
if (packetSegments.size() < 3) {
|
||||
throw Exception{"Unexpected number of packet segments in RemoveBreakpoint packet"};
|
||||
}
|
||||
|
||||
bool conversionStatus = true;
|
||||
this->address = packetSegments.at(1).toUInt(&conversionStatus, 16);
|
||||
|
||||
if (!conversionStatus) {
|
||||
throw Exception{"Failed to convert address hex value from RemoveBreakpoint packet."};
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveBreakpoint::handle(
|
||||
DebugSession& debugSession,
|
||||
const TargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor&,
|
||||
TargetControllerService& targetControllerService
|
||||
) {
|
||||
Logger::info("Handling RemoveBreakpoint packet");
|
||||
|
||||
try {
|
||||
debugSession.removeExternalBreakpoint(this->address, targetControllerService);
|
||||
debugSession.connection.writePacket(OkResponsePacket{});
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
Logger::error("Failed to remove breakpoint on target - " + exception.getMessage());
|
||||
debugSession.connection.writePacket(ErrorResponsePacket{});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "CommandPacket.hpp"
|
||||
#include "src/DebugServer/Gdb/BreakpointType.hpp"
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::CommandPackets
|
||||
{
|
||||
/**
|
||||
* The RemoveBreakpoint class implements the structure for "z" command packets. Upon receiving this command, the
|
||||
* server is expected to remove a breakpoint at the specified address.
|
||||
*/
|
||||
class RemoveBreakpoint: public CommandPacket
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Breakpoint type (Software or Hardware)
|
||||
*/
|
||||
BreakpointType type = BreakpointType::UNKNOWN;
|
||||
|
||||
/**
|
||||
* Address at which the breakpoint should be located.
|
||||
*/
|
||||
Targets::TargetMemoryAddress address = 0;
|
||||
|
||||
explicit RemoveBreakpoint(const RawPacket& rawPacket);
|
||||
|
||||
void handle(
|
||||
DebugSession& debugSession,
|
||||
const TargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) override;
|
||||
};
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "CommandPacket.hpp"
|
||||
#include "src/DebugServer/Gdb/BreakpointType.hpp"
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::CommandPackets
|
||||
{
|
||||
/**
|
||||
* The SetBreakpoint class implements the structure for "Z" command packets. Upon receiving this command, the
|
||||
* server is expected to set a breakpoint at the specified address.
|
||||
*/
|
||||
class SetBreakpoint: public CommandPacket
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Breakpoint type (Software or Hardware)
|
||||
*/
|
||||
BreakpointType type = BreakpointType::UNKNOWN;
|
||||
|
||||
/**
|
||||
* Address at which the breakpoint should be located.
|
||||
*/
|
||||
Targets::TargetMemoryAddress address = 0;
|
||||
|
||||
explicit SetBreakpoint(const RawPacket& rawPacket);
|
||||
|
||||
void handle(
|
||||
DebugSession& debugSession,
|
||||
const TargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) override;
|
||||
};
|
||||
}
|
||||
@@ -26,78 +26,93 @@ namespace DebugServer::Gdb
|
||||
}
|
||||
|
||||
void DebugSession::setInternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Targets::TargetMemorySize size,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) {
|
||||
if (this->internalBreakpointsByAddress.contains(address)) {
|
||||
if (this->internalBreakpointRegistry.contains(addressSpaceDescriptor.id, address)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto externalBreakpointIt = this->externalBreakpointsByAddress.find(address);
|
||||
if (externalBreakpointIt != this->externalBreakpointsByAddress.end()) {
|
||||
const auto externalBreakpoint = this->externalBreakpointRegistry.find(addressSpaceDescriptor.id, address);
|
||||
if (externalBreakpoint.has_value()) {
|
||||
// We already have an external breakpoint at this address
|
||||
this->internalBreakpointsByAddress.emplace(address, externalBreakpointIt->second);
|
||||
this->internalBreakpointRegistry.insert(externalBreakpoint->get());
|
||||
return;
|
||||
}
|
||||
|
||||
this->internalBreakpointsByAddress.emplace(
|
||||
address,
|
||||
targetControllerService.setBreakpoint(address, Targets::TargetBreakpoint::Type::HARDWARE)
|
||||
this->internalBreakpointRegistry.insert(
|
||||
targetControllerService.setProgramBreakpointAnyType(
|
||||
addressSpaceDescriptor,
|
||||
memorySegmentDescriptor,
|
||||
address,
|
||||
size
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void DebugSession::removeInternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) {
|
||||
const auto breakpointIt = this->internalBreakpointsByAddress.find(address);
|
||||
if (breakpointIt == this->internalBreakpointsByAddress.end()) {
|
||||
const auto breakpoint = this->internalBreakpointRegistry.find(addressSpaceDescriptor.id, address);
|
||||
if (!breakpoint.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->externalBreakpointsByAddress.contains(address)) {
|
||||
targetControllerService.removeBreakpoint(breakpointIt->second);
|
||||
if (!this->externalBreakpointRegistry.contains(addressSpaceDescriptor.id, address)) {
|
||||
targetControllerService.removeProgramBreakpoint(breakpoint->get());
|
||||
}
|
||||
|
||||
this->internalBreakpointsByAddress.erase(breakpointIt);
|
||||
this->internalBreakpointRegistry.remove(addressSpaceDescriptor.id, address);
|
||||
}
|
||||
|
||||
void DebugSession::setExternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Targets::TargetMemorySize size,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) {
|
||||
if (this->externalBreakpointsByAddress.contains(address)) {
|
||||
if (this->externalBreakpointRegistry.contains(addressSpaceDescriptor.id, address)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto internalBreakpointIt = this->internalBreakpointsByAddress.find(address);
|
||||
|
||||
if (internalBreakpointIt != this->internalBreakpointsByAddress.end()) {
|
||||
const auto internalBreakpoint = this->internalBreakpointRegistry.find(addressSpaceDescriptor.id, address);
|
||||
if (internalBreakpoint.has_value()) {
|
||||
// We already have an internal breakpoint at this address
|
||||
this->externalBreakpointsByAddress.emplace(address, internalBreakpointIt->second);
|
||||
this->externalBreakpointRegistry.insert(internalBreakpoint->get());
|
||||
return;
|
||||
}
|
||||
|
||||
this->externalBreakpointsByAddress.emplace(
|
||||
address,
|
||||
targetControllerService.setBreakpoint(address, Targets::TargetBreakpoint::Type::HARDWARE)
|
||||
this->externalBreakpointRegistry.insert(
|
||||
targetControllerService.setProgramBreakpointAnyType(
|
||||
addressSpaceDescriptor,
|
||||
memorySegmentDescriptor,
|
||||
address,
|
||||
size
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void DebugSession::removeExternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) {
|
||||
const auto breakpointIt = this->externalBreakpointsByAddress.find(address);
|
||||
if (breakpointIt == this->externalBreakpointsByAddress.end()) {
|
||||
const auto breakpoint = this->externalBreakpointRegistry.find(addressSpaceDescriptor.id, address);
|
||||
if (!breakpoint.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->internalBreakpointsByAddress.contains(address)) {
|
||||
targetControllerService.removeBreakpoint(breakpointIt->second);
|
||||
if (!this->internalBreakpointRegistry.contains(addressSpaceDescriptor.id, address)) {
|
||||
targetControllerService.removeProgramBreakpoint(breakpoint->get());
|
||||
}
|
||||
|
||||
this->externalBreakpointsByAddress.erase(breakpointIt);
|
||||
this->externalBreakpointRegistry.remove(addressSpaceDescriptor.id, address);
|
||||
}
|
||||
|
||||
void DebugSession::startRangeSteppingSession(
|
||||
@@ -105,10 +120,22 @@ namespace DebugServer::Gdb
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) {
|
||||
for (const auto& interceptAddress : session.interceptedAddresses) {
|
||||
this->setInternalBreakpoint(interceptAddress, targetControllerService);
|
||||
/*
|
||||
* Have hard-coded the breakpoint size here, as range stepping is only supported on AVR targets.
|
||||
*
|
||||
* TODO: Review this after v2.0.0. Maybe move this range-stepping code out to an AVR-specific DebugSession
|
||||
* struct. Or, refactor the range stepping session object to accommodate breakpoint sizes.
|
||||
*/
|
||||
this->setInternalBreakpoint(
|
||||
session.addressSpaceDescriptor,
|
||||
session.memorySegmentDescriptor,
|
||||
interceptAddress,
|
||||
2,
|
||||
targetControllerService
|
||||
);
|
||||
}
|
||||
|
||||
this->activeRangeSteppingSession = std::move(session);
|
||||
this->activeRangeSteppingSession.emplace(std::move(session));
|
||||
}
|
||||
|
||||
void DebugSession::terminateRangeSteppingSession(Services::TargetControllerService& targetControllerService) {
|
||||
@@ -118,7 +145,11 @@ namespace DebugServer::Gdb
|
||||
|
||||
// Clear all intercepting breakpoints
|
||||
for (const auto& interceptAddress : this->activeRangeSteppingSession->interceptedAddresses) {
|
||||
this->removeInternalBreakpoint(interceptAddress, targetControllerService);
|
||||
this->removeInternalBreakpoint(
|
||||
this->activeRangeSteppingSession->addressSpaceDescriptor,
|
||||
interceptAddress,
|
||||
targetControllerService
|
||||
);
|
||||
}
|
||||
|
||||
this->activeRangeSteppingSession.reset();
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
#include "RangeSteppingSession.hpp"
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
#include "src/Targets/TargetAddressSpaceDescriptor.hpp"
|
||||
#include "src/Targets/TargetMemorySegmentDescriptor.hpp"
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
#include "src/Targets/ProgramBreakpointRegistry.hpp"
|
||||
|
||||
#include "src/Services/TargetControllerService.hpp"
|
||||
|
||||
@@ -53,8 +56,8 @@ namespace DebugServer::Gdb
|
||||
*
|
||||
* We track internal and external breakpoints separately.
|
||||
*/
|
||||
std::map<Targets::TargetMemoryAddress, Targets::TargetBreakpoint> internalBreakpointsByAddress;
|
||||
std::map<Targets::TargetMemoryAddress, Targets::TargetBreakpoint> externalBreakpointsByAddress;
|
||||
Targets::ProgramBreakpointRegistry internalBreakpointRegistry;
|
||||
Targets::ProgramBreakpointRegistry externalBreakpointRegistry;
|
||||
|
||||
/**
|
||||
* When the GDB client is waiting for the target to halt, this is set to true so we know when to notify the
|
||||
@@ -102,21 +105,29 @@ namespace DebugServer::Gdb
|
||||
virtual ~DebugSession();
|
||||
|
||||
virtual void setInternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Targets::TargetMemorySize size,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
);
|
||||
|
||||
virtual void removeInternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
);
|
||||
|
||||
virtual void setExternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Targets::TargetMemorySize size,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
);
|
||||
|
||||
virtual void removeExternalBreakpoint(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
Targets::TargetMemoryAddress address,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
);
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include "CommandPackets/InterruptExecution.hpp"
|
||||
#include "CommandPackets/ContinueExecution.hpp"
|
||||
#include "CommandPackets/StepExecution.hpp"
|
||||
#include "CommandPackets/SetBreakpoint.hpp"
|
||||
#include "CommandPackets/RemoveBreakpoint.hpp"
|
||||
#include "CommandPackets/Monitor.hpp"
|
||||
#include "CommandPackets/ResetTarget.hpp"
|
||||
#include "CommandPackets/HelpMonitorInfo.hpp"
|
||||
@@ -332,6 +330,26 @@ namespace DebugServer::Gdb
|
||||
std::optional<DebugSessionType> debugSession;
|
||||
|
||||
void endDebugSession() {
|
||||
if (!debugSession.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When GDB is configured to leave breakpoints in place, it will sometimes not even bother to remove them
|
||||
* at the end of the debug session.
|
||||
*/
|
||||
for (const auto& [addressSpaceId, breakpointsByAddress] : this->debugSession->internalBreakpointRegistry) {
|
||||
for (const auto& [address, breakpoint] : breakpointsByAddress) {
|
||||
this->targetControllerService.removeProgramBreakpoint(breakpoint);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [addressSpaceId, breakpointsByAddress] : this->debugSession->externalBreakpointRegistry) {
|
||||
for (const auto& [address, breakpoint] : breakpointsByAddress) {
|
||||
this->targetControllerService.removeProgramBreakpoint(breakpoint);
|
||||
}
|
||||
}
|
||||
|
||||
this->debugSession.reset();
|
||||
}
|
||||
|
||||
@@ -421,14 +439,6 @@ namespace DebugServer::Gdb
|
||||
return std::make_unique<CommandPackets::StepExecution>(rawPacket);
|
||||
}
|
||||
|
||||
if (rawPacket[1] == 'Z') {
|
||||
return std::make_unique<CommandPackets::SetBreakpoint>(rawPacket);
|
||||
}
|
||||
|
||||
if (rawPacket[1] == 'z') {
|
||||
return std::make_unique<CommandPackets::RemoveBreakpoint>(rawPacket);
|
||||
}
|
||||
|
||||
if (rawPacket[1] == 'D') {
|
||||
return std::make_unique<CommandPackets::Detach>(rawPacket);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <set>
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
#include "src/Targets/TargetAddressSpaceDescriptor.hpp"
|
||||
#include "src/Targets/TargetMemorySegmentDescriptor.hpp"
|
||||
|
||||
namespace DebugServer::Gdb
|
||||
{
|
||||
@@ -15,6 +17,12 @@ namespace DebugServer::Gdb
|
||||
*/
|
||||
struct RangeSteppingSession
|
||||
{
|
||||
/**
|
||||
* The address space and memory segment of the program memory which we are stepping over.
|
||||
*/
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor;
|
||||
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor;
|
||||
|
||||
/**
|
||||
* The (byte) address range we're stepping over.
|
||||
*
|
||||
@@ -36,11 +44,23 @@ namespace DebugServer::Gdb
|
||||
bool singleStepping = false;
|
||||
|
||||
RangeSteppingSession(
|
||||
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
||||
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
||||
const Targets::TargetMemoryAddressRange& range,
|
||||
const std::set<Targets::TargetMemoryAddress>& interceptedAddresses
|
||||
)
|
||||
: range(range)
|
||||
: addressSpaceDescriptor(addressSpaceDescriptor)
|
||||
, memorySegmentDescriptor(memorySegmentDescriptor)
|
||||
, range(range)
|
||||
, interceptedAddresses(interceptedAddresses)
|
||||
{};
|
||||
|
||||
RangeSteppingSession(RangeSteppingSession&& other) noexcept
|
||||
: addressSpaceDescriptor(other.addressSpaceDescriptor)
|
||||
, memorySegmentDescriptor(other.memorySegmentDescriptor)
|
||||
, range(other.range)
|
||||
, interceptedAddresses(std::move(other.interceptedAddresses))
|
||||
, singleStepping(other.singleStepping)
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "RemoveBreakpoint.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/OkResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/EmptyResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
|
||||
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::RiscVGdb::CommandPackets
|
||||
{
|
||||
using Services::TargetControllerService;
|
||||
|
||||
using ResponsePackets::OkResponsePacket;
|
||||
using ResponsePackets::ErrorResponsePacket;
|
||||
using ResponsePackets::EmptyResponsePacket;
|
||||
|
||||
using ::Exceptions::Exception;
|
||||
|
||||
RemoveBreakpoint::RemoveBreakpoint(const RawPacket& rawPacket)
|
||||
: CommandPacket(rawPacket)
|
||||
{
|
||||
const auto packetString = std::string{this->data.begin(), this->data.end()};
|
||||
|
||||
if (packetString.size() < 6) {
|
||||
throw Exception{"Unexpected RemoveBreakpoint packet size"};
|
||||
}
|
||||
|
||||
this->type = (packetString[1] == '0')
|
||||
? BreakpointType::SOFTWARE_BREAKPOINT
|
||||
: (packetString[1] == '1') ? BreakpointType::HARDWARE_BREAKPOINT : BreakpointType::UNKNOWN;
|
||||
|
||||
const auto firstCommaPos = packetString.find_first_of(',');
|
||||
const auto secondCommaPos = packetString.find_first_of(',', firstCommaPos + 1);
|
||||
if (firstCommaPos == std::string::npos || secondCommaPos == std::string::npos) {
|
||||
throw Exception{"Invalid RemoveBreakpoint packet"};
|
||||
}
|
||||
|
||||
const auto addressString = packetString.substr(firstCommaPos + 1, secondCommaPos - firstCommaPos - 1);
|
||||
const auto sizeString = packetString.substr(
|
||||
secondCommaPos + 1,
|
||||
packetString.find_first_of(';', secondCommaPos) - secondCommaPos - 1
|
||||
);
|
||||
|
||||
this->address = Services::StringService::toUint32(addressString, 16);
|
||||
this->size = Services::StringService::toUint32(sizeString, 10);
|
||||
}
|
||||
|
||||
void RemoveBreakpoint::handle(
|
||||
DebugSession& debugSession,
|
||||
const RiscVGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor&,
|
||||
TargetControllerService& targetControllerService
|
||||
) {
|
||||
Logger::info("Handling RemoveBreakpoint packet");
|
||||
|
||||
try {
|
||||
debugSession.removeExternalBreakpoint(
|
||||
gdbTargetDescriptor.systemAddressSpaceDescriptor,
|
||||
this->address,
|
||||
targetControllerService
|
||||
);
|
||||
debugSession.connection.writePacket(OkResponsePacket{});
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
Logger::error("Failed to remove breakpoint on target - " + exception.getMessage());
|
||||
debugSession.connection.writePacket(ErrorResponsePacket{});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "RiscVGdbCommandPacketInterface.hpp"
|
||||
#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp"
|
||||
#include "src/DebugServer/Gdb/BreakpointType.hpp"
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::RiscVGdb::CommandPackets
|
||||
{
|
||||
class RemoveBreakpoint
|
||||
: public CommandPackets::RiscVGdbCommandPacketInterface
|
||||
, private Gdb::CommandPackets::CommandPacket
|
||||
{
|
||||
public:
|
||||
BreakpointType type = BreakpointType::UNKNOWN;
|
||||
Targets::TargetMemoryAddress address = 0;
|
||||
Targets::TargetMemorySize size = 0;
|
||||
|
||||
explicit RemoveBreakpoint(const RawPacket& rawPacket);
|
||||
|
||||
void handle(
|
||||
DebugSession& debugSession,
|
||||
const RiscVGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) override;
|
||||
};
|
||||
}
|
||||
103
src/DebugServer/Gdb/RiscVGdb/CommandPackets/SetBreakpoint.cpp
Normal file
103
src/DebugServer/Gdb/RiscVGdb/CommandPackets/SetBreakpoint.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "SetBreakpoint.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/OkResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/EmptyResponsePacket.hpp"
|
||||
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
|
||||
|
||||
#include "src/Targets/TargetBreakpoint.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::RiscVGdb::CommandPackets
|
||||
{
|
||||
using Services::TargetControllerService;
|
||||
|
||||
using ResponsePackets::OkResponsePacket;
|
||||
using ResponsePackets::ErrorResponsePacket;
|
||||
using ResponsePackets::EmptyResponsePacket;
|
||||
|
||||
using ::Exceptions::Exception;
|
||||
|
||||
SetBreakpoint::SetBreakpoint(const RawPacket& rawPacket)
|
||||
: CommandPacket(rawPacket)
|
||||
{
|
||||
const auto packetString = std::string{this->data.begin(), this->data.end()};
|
||||
|
||||
if (packetString.size() < 6) {
|
||||
throw Exception{"Unexpected SetBreakpoint packet size"};
|
||||
}
|
||||
|
||||
// Z0 = SW breakpoint, Z1 = HW breakpoint
|
||||
this->type = (packetString[1] == '0')
|
||||
? BreakpointType::SOFTWARE_BREAKPOINT
|
||||
: (packetString[1] == '1') ? BreakpointType::HARDWARE_BREAKPOINT : BreakpointType::UNKNOWN;
|
||||
|
||||
const auto firstCommaPos = packetString.find_first_of(',');
|
||||
const auto secondCommaPos = packetString.find_first_of(',', firstCommaPos + 1);
|
||||
if (firstCommaPos == std::string::npos || secondCommaPos == std::string::npos) {
|
||||
throw Exception{"Invalid SetBreakpoint packet"};
|
||||
}
|
||||
|
||||
const auto addressString = packetString.substr(firstCommaPos + 1, secondCommaPos - firstCommaPos - 1);
|
||||
const auto sizeString = packetString.substr(
|
||||
secondCommaPos + 1,
|
||||
packetString.find_first_of(';', secondCommaPos) - secondCommaPos - 1
|
||||
);
|
||||
|
||||
this->address = Services::StringService::toUint32(addressString, 16);
|
||||
this->size = Services::StringService::toUint32(sizeString, 10);
|
||||
}
|
||||
|
||||
void SetBreakpoint::handle(
|
||||
DebugSession& debugSession,
|
||||
const RiscVGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor&,
|
||||
TargetControllerService& targetControllerService
|
||||
) {
|
||||
Logger::info("Handling SetBreakpoint packet");
|
||||
|
||||
try {
|
||||
if (this->type == BreakpointType::UNKNOWN) {
|
||||
Logger::debug(
|
||||
"Rejecting breakpoint at address " + std::to_string(this->address)
|
||||
+ " - unsupported breakpoint type"
|
||||
);
|
||||
debugSession.connection.writePacket(EmptyResponsePacket{});
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->type == BreakpointType::SOFTWARE_BREAKPOINT && this->size != 2 && this->size != 4) {
|
||||
throw Exception{"Invalid breakpoint size - expected 2 or 4, got " + std::to_string(this->size)};
|
||||
}
|
||||
|
||||
const auto memorySegmentDescriptors = gdbTargetDescriptor.systemAddressSpaceDescriptor.getIntersectingMemorySegmentDescriptors(
|
||||
Targets::TargetMemoryAddressRange{this->address, this->address + this->size - 1}
|
||||
);
|
||||
|
||||
if (memorySegmentDescriptors.size() != 1) {
|
||||
throw Exception{
|
||||
memorySegmentDescriptors.empty()
|
||||
? "Invalid breakpoint address - no containing memory segments found for the given address"
|
||||
: "Invalid breakpoint address - the address range intersects with multiple memory segments"
|
||||
};
|
||||
}
|
||||
|
||||
debugSession.setExternalBreakpoint(
|
||||
gdbTargetDescriptor.systemAddressSpaceDescriptor,
|
||||
*(memorySegmentDescriptors.front()),
|
||||
this->address,
|
||||
this->size, targetControllerService
|
||||
);
|
||||
debugSession.connection.writePacket(OkResponsePacket{});
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
Logger::error("Failed to set breakpoint on target - " + exception.getMessage());
|
||||
debugSession.connection.writePacket(ErrorResponsePacket{});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "RiscVGdbCommandPacketInterface.hpp"
|
||||
#include "src/DebugServer/Gdb/CommandPackets/CommandPacket.hpp"
|
||||
#include "src/DebugServer/Gdb/BreakpointType.hpp"
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
|
||||
namespace DebugServer::Gdb::RiscVGdb::CommandPackets
|
||||
{
|
||||
class SetBreakpoint
|
||||
: public CommandPackets::RiscVGdbCommandPacketInterface
|
||||
, private Gdb::CommandPackets::CommandPacket
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The requested breakpoint type.
|
||||
*
|
||||
* We don't actually honor this. GDB assumes flash memory cannot be written to outside of a programming
|
||||
* session, so it refuses to even attempt to insert software breakpoints in flash memory. It always requests
|
||||
* hardware breakpoints. This is why ignore the requested breakpoint type and just insert whatever type we can.
|
||||
*/
|
||||
BreakpointType type = BreakpointType::UNKNOWN;
|
||||
Targets::TargetMemoryAddress address = 0;
|
||||
Targets::TargetMemorySize size = 0;
|
||||
|
||||
explicit SetBreakpoint(const RawPacket& rawPacket);
|
||||
|
||||
void handle(
|
||||
DebugSession& debugSession,
|
||||
const RiscVGdbTargetDescriptor& gdbTargetDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
Services::TargetControllerService& targetControllerService
|
||||
) override;
|
||||
};
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "CommandPackets/ReadMemory.hpp"
|
||||
#include "CommandPackets/WriteMemory.hpp"
|
||||
#include "CommandPackets/ReadMemoryMap.hpp"
|
||||
#include "CommandPackets/SetBreakpoint.hpp"
|
||||
#include "CommandPackets/RemoveBreakpoint.hpp"
|
||||
#include "CommandPackets/FlashErase.hpp"
|
||||
#include "CommandPackets/FlashWrite.hpp"
|
||||
#include "CommandPackets/FlashDone.hpp"
|
||||
@@ -53,6 +55,8 @@ namespace DebugServer::Gdb::RiscVGdb
|
||||
using CommandPackets::ReadMemory;
|
||||
using CommandPackets::WriteMemory;
|
||||
using CommandPackets::ReadMemoryMap;
|
||||
using CommandPackets::SetBreakpoint;
|
||||
using CommandPackets::RemoveBreakpoint;
|
||||
using CommandPackets::FlashErase;
|
||||
using CommandPackets::FlashWrite;
|
||||
using CommandPackets::FlashDone;
|
||||
@@ -82,6 +86,14 @@ namespace DebugServer::Gdb::RiscVGdb
|
||||
return std::make_unique<WriteMemory>(rawPacket, this->gdbTargetDescriptor);
|
||||
}
|
||||
|
||||
if (rawPacket[1] == 'Z') {
|
||||
return std::make_unique<SetBreakpoint>(rawPacket);
|
||||
}
|
||||
|
||||
if (rawPacket[1] == 'z') {
|
||||
return std::make_unique<RemoveBreakpoint>(rawPacket);
|
||||
}
|
||||
|
||||
if (rawPacket.size() > 1) {
|
||||
const auto rawPacketString = std::string{rawPacket.begin() + 1, rawPacket.end()};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user