2022-03-24 19:06:09 +00:00
|
|
|
#include "AvrGdbRsp.hpp"
|
|
|
|
|
|
2023-09-10 22:27:10 +01:00
|
|
|
#include "src/Services/StringService.hpp"
|
|
|
|
|
|
2022-03-27 19:44:02 +01:00
|
|
|
// Command packets
|
2023-05-21 21:08:25 +01:00
|
|
|
#include "CommandPackets/ReadRegister.hpp"
|
|
|
|
|
#include "CommandPackets/ReadRegisters.hpp"
|
|
|
|
|
#include "CommandPackets/WriteRegister.hpp"
|
2022-03-27 19:44:02 +01:00
|
|
|
#include "CommandPackets/ReadMemory.hpp"
|
|
|
|
|
#include "CommandPackets/WriteMemory.hpp"
|
2022-05-14 22:43:08 +01:00
|
|
|
#include "CommandPackets/ReadMemoryMap.hpp"
|
2022-05-28 22:47:25 +01:00
|
|
|
#include "CommandPackets/FlashErase.hpp"
|
2022-05-29 17:18:29 +01:00
|
|
|
#include "CommandPackets/FlashWrite.hpp"
|
2022-06-05 16:15:12 +01:00
|
|
|
#include "CommandPackets/FlashDone.hpp"
|
2023-09-10 22:27:10 +01:00
|
|
|
#include "CommandPackets/VContSupportedActionsQuery.hpp"
|
|
|
|
|
#include "CommandPackets/VContContinueExecution.hpp"
|
|
|
|
|
#include "CommandPackets/VContStepExecution.hpp"
|
|
|
|
|
#include "CommandPackets/VContRangeStep.hpp"
|
2022-03-27 19:44:02 +01:00
|
|
|
|
2023-08-13 15:47:51 +01:00
|
|
|
namespace DebugServer::Gdb::AvrGdb
|
2022-03-24 19:06:09 +00:00
|
|
|
{
|
2023-08-13 15:47:51 +01:00
|
|
|
using namespace Exceptions;
|
2022-03-24 19:06:09 +00:00
|
|
|
|
2023-08-13 15:47:51 +01:00
|
|
|
using Targets::TargetRegisterDescriptor;
|
|
|
|
|
using Targets::TargetRegisterType;
|
2022-03-24 19:06:09 +00:00
|
|
|
|
2022-03-27 18:32:13 +01:00
|
|
|
AvrGdbRsp::AvrGdbRsp(
|
|
|
|
|
const DebugServerConfig& debugServerConfig,
|
2022-04-15 22:05:50 +01:00
|
|
|
EventListener& eventListener,
|
|
|
|
|
EventFdNotifier& eventNotifier
|
2022-03-27 18:32:13 +01:00
|
|
|
)
|
2022-04-15 22:05:50 +01:00
|
|
|
: GdbRspDebugServer(debugServerConfig, eventListener, eventNotifier)
|
2023-09-10 22:27:10 +01:00
|
|
|
, gdbTargetDescriptor(TargetDescriptor(this->targetControllerService.getTargetDescriptor()))
|
2022-03-27 18:32:13 +01:00
|
|
|
{}
|
|
|
|
|
|
2023-09-10 22:27:10 +01:00
|
|
|
DebugSession* AvrGdbRsp::startDebugSession(Connection&& connection) {
|
|
|
|
|
this->activeDebugSession.emplace(
|
|
|
|
|
std::move(connection),
|
|
|
|
|
this->getSupportedFeatures(),
|
|
|
|
|
this->gdbTargetDescriptor,
|
|
|
|
|
this->debugServerConfig
|
2022-03-27 18:32:13 +01:00
|
|
|
);
|
2023-09-10 22:27:10 +01:00
|
|
|
|
|
|
|
|
return &*(this->activeDebugSession);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AvrGdbRsp::endDebugSession() {
|
|
|
|
|
this->activeDebugSession.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Gdb::TargetDescriptor& AvrGdbRsp::getGdbTargetDescriptor() {
|
|
|
|
|
return this->gdbTargetDescriptor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DebugSession* AvrGdbRsp::getActiveDebugSession() {
|
|
|
|
|
return this->activeDebugSession.has_value() ? &*(this->activeDebugSession) : nullptr;
|
2022-03-24 19:06:09 +00:00
|
|
|
}
|
2022-03-27 19:44:02 +01:00
|
|
|
|
|
|
|
|
std::unique_ptr<Gdb::CommandPackets::CommandPacket> AvrGdbRsp::resolveCommandPacket(
|
2022-10-01 21:01:37 +01:00
|
|
|
const RawPacket& rawPacket
|
2022-03-27 19:44:02 +01:00
|
|
|
) {
|
2023-05-21 21:08:25 +01:00
|
|
|
using AvrGdb::CommandPackets::ReadRegister;
|
|
|
|
|
using AvrGdb::CommandPackets::ReadRegisters;
|
|
|
|
|
using AvrGdb::CommandPackets::WriteRegister;
|
2022-03-27 19:44:02 +01:00
|
|
|
using AvrGdb::CommandPackets::ReadMemory;
|
|
|
|
|
using AvrGdb::CommandPackets::WriteMemory;
|
2022-05-14 22:43:08 +01:00
|
|
|
using AvrGdb::CommandPackets::ReadMemoryMap;
|
2022-05-28 22:47:25 +01:00
|
|
|
using AvrGdb::CommandPackets::FlashErase;
|
2022-05-29 17:18:29 +01:00
|
|
|
using AvrGdb::CommandPackets::FlashWrite;
|
2022-06-05 16:15:12 +01:00
|
|
|
using AvrGdb::CommandPackets::FlashDone;
|
2023-09-10 22:27:10 +01:00
|
|
|
using AvrGdb::CommandPackets::VContSupportedActionsQuery;
|
|
|
|
|
using AvrGdb::CommandPackets::VContContinueExecution;
|
|
|
|
|
using AvrGdb::CommandPackets::VContStepExecution;
|
|
|
|
|
using AvrGdb::CommandPackets::VContRangeStep;
|
2022-03-27 19:44:02 +01:00
|
|
|
|
|
|
|
|
if (rawPacket.size() >= 2) {
|
2023-05-21 21:08:25 +01:00
|
|
|
if (rawPacket[1] == 'p') {
|
|
|
|
|
return std::make_unique<ReadRegister>(rawPacket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rawPacket[1] == 'g') {
|
|
|
|
|
return std::make_unique<ReadRegisters>(rawPacket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rawPacket[1] == 'P') {
|
|
|
|
|
return std::make_unique<WriteRegister>(rawPacket);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-27 19:44:02 +01:00
|
|
|
if (rawPacket[1] == 'm') {
|
2023-09-10 22:27:10 +01:00
|
|
|
return std::make_unique<ReadMemory>(rawPacket, this->gdbTargetDescriptor);
|
2022-03-27 19:44:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rawPacket[1] == 'M') {
|
2023-09-10 22:27:10 +01:00
|
|
|
return std::make_unique<WriteMemory>(rawPacket, this->gdbTargetDescriptor);
|
2022-03-27 19:44:02 +01:00
|
|
|
}
|
2022-05-14 22:43:08 +01:00
|
|
|
|
|
|
|
|
const auto rawPacketString = std::string(rawPacket.begin() + 1, rawPacket.end());
|
|
|
|
|
|
|
|
|
|
if (rawPacketString.find("qXfer:memory-map:read::") == 0) {
|
|
|
|
|
return std::make_unique<ReadMemoryMap>(rawPacket);
|
|
|
|
|
}
|
2022-05-28 22:47:25 +01:00
|
|
|
|
|
|
|
|
if (rawPacketString.find("vFlashErase") == 0) {
|
|
|
|
|
return std::make_unique<FlashErase>(rawPacket);
|
|
|
|
|
}
|
2022-05-29 17:18:29 +01:00
|
|
|
|
|
|
|
|
if (rawPacketString.find("vFlashWrite") == 0) {
|
|
|
|
|
return std::make_unique<FlashWrite>(rawPacket);
|
|
|
|
|
}
|
2022-06-05 16:15:12 +01:00
|
|
|
|
|
|
|
|
if (rawPacketString.find("vFlashDone") == 0) {
|
|
|
|
|
return std::make_unique<FlashDone>(rawPacket);
|
|
|
|
|
}
|
2023-09-10 22:27:10 +01:00
|
|
|
|
|
|
|
|
if (rawPacketString.find("vCont?") == 0) {
|
|
|
|
|
return std::make_unique<VContSupportedActionsQuery>(rawPacket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rawPacketString.find("vCont;c") == 0 || rawPacketString.find("vCont;C") == 0) {
|
|
|
|
|
return std::make_unique<VContContinueExecution>(rawPacket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rawPacketString.find("vCont;s") == 0 || rawPacketString.find("vCont;S") == 0) {
|
|
|
|
|
return std::make_unique<VContStepExecution>(rawPacket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->debugServerConfig.rangeSteppingEnabled) {
|
|
|
|
|
if (rawPacketString.find("vCont;r") == 0) {
|
|
|
|
|
return std::make_unique<VContRangeStep>(rawPacket);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-27 19:44:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return GdbRspDebugServer::resolveCommandPacket(rawPacket);
|
|
|
|
|
}
|
2022-05-14 22:43:08 +01:00
|
|
|
|
|
|
|
|
std::set<std::pair<Feature, std::optional<std::string>>> AvrGdbRsp::getSupportedFeatures() {
|
2023-09-10 22:27:10 +01:00
|
|
|
return {
|
|
|
|
|
{Feature::SOFTWARE_BREAKPOINTS, std::nullopt},
|
|
|
|
|
{Feature::MEMORY_MAP_READ, std::nullopt},
|
|
|
|
|
{Feature::VCONT_ACTIONS_QUERY, std::nullopt},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AvrGdbRsp::handleTargetStoppedGdbResponse(Targets::TargetProgramCounter programAddress) {
|
|
|
|
|
using Services::StringService;
|
|
|
|
|
|
|
|
|
|
Logger::debug("Target stopped at byte address: 0x" + StringService::toHex(programAddress));
|
|
|
|
|
|
|
|
|
|
auto& activeRangeSteppingSession = this->activeDebugSession->activeRangeSteppingSession;
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
activeRangeSteppingSession.has_value()
|
|
|
|
|
&& programAddress >= activeRangeSteppingSession->range.startAddress
|
|
|
|
|
&& programAddress < activeRangeSteppingSession->range.endAddress
|
|
|
|
|
) {
|
|
|
|
|
/*
|
|
|
|
|
* The target stopped within the stepping range of an active range stepping session.
|
|
|
|
|
*
|
|
|
|
|
* We need to figure out why, and determine whether the stop should be reported to GDB.
|
|
|
|
|
*/
|
|
|
|
|
if (this->activeDebugSession->externalBreakpointAddresses.contains(programAddress)) {
|
|
|
|
|
/*
|
|
|
|
|
* The target stopped due to an external breakpoint, set by GDB.
|
|
|
|
|
*
|
|
|
|
|
* We have to end the range stepping session and report this to GDB.
|
|
|
|
|
*/
|
|
|
|
|
Logger::debug("Reached external breakpoint within stepping range");
|
|
|
|
|
|
|
|
|
|
this->activeDebugSession->terminateRangeSteppingSession(this->targetControllerService);
|
|
|
|
|
return GdbRspDebugServer::handleTargetStoppedGdbResponse(programAddress);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (activeRangeSteppingSession->interceptedAddresses.contains(programAddress)) {
|
|
|
|
|
/*
|
|
|
|
|
* The target stopped due to an intercepting breakpoint, but we're still within the stepping range,
|
|
|
|
|
* which can only mean that we weren't sure where this instruction would lead to.
|
|
|
|
|
*
|
|
|
|
|
* We must perform a single step and see what happens.
|
|
|
|
|
*/
|
|
|
|
|
Logger::debug("Reached intercepting breakpoint within stepping range");
|
|
|
|
|
Logger::debug("Attempting single step from 0x" + StringService::toHex(programAddress));
|
|
|
|
|
|
|
|
|
|
activeRangeSteppingSession->singleStepping = true;
|
|
|
|
|
this->targetControllerService.stepTargetExecution(std::nullopt);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-05-14 22:43:08 +01:00
|
|
|
|
2023-09-10 22:27:10 +01:00
|
|
|
if (activeRangeSteppingSession->singleStepping) {
|
|
|
|
|
/*
|
|
|
|
|
* We performed a single step once and we're still within the stepping range, so we're good to
|
|
|
|
|
* continue the range stepping session.
|
|
|
|
|
*/
|
|
|
|
|
Logger::debug("Completed single step from an intercepted address - PC still within stepping range");
|
|
|
|
|
Logger::debug("Continuing range stepping");
|
|
|
|
|
|
|
|
|
|
activeRangeSteppingSession->singleStepping = false;
|
|
|
|
|
this->targetControllerService.continueTargetExecution(std::nullopt, std::nullopt);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we get here, the target stopped for an unknown reason that doesn't seem to have anything to do with
|
|
|
|
|
* the active range stepping session.
|
|
|
|
|
*
|
|
|
|
|
* This could be due to a permanent breakpoint in the target's program code.
|
|
|
|
|
*
|
|
|
|
|
* We have to end the range stepping session and report the stop to GDB.
|
|
|
|
|
*/
|
|
|
|
|
Logger::debug("Target stopped within stepping range, but for an unknown reason");
|
|
|
|
|
|
|
|
|
|
this->activeDebugSession->terminateRangeSteppingSession(this->targetControllerService);
|
|
|
|
|
return GdbRspDebugServer::handleTargetStoppedGdbResponse(programAddress);
|
|
|
|
|
}
|
2022-05-14 22:43:08 +01:00
|
|
|
|
2023-09-10 22:27:10 +01:00
|
|
|
// Report the stop to GDB
|
|
|
|
|
return GdbRspDebugServer::handleTargetStoppedGdbResponse(programAddress);
|
2022-05-14 22:43:08 +01:00
|
|
|
}
|
2022-03-24 19:06:09 +00:00
|
|
|
}
|