Initial commit

This commit is contained in:
Nav
2021-04-04 21:04:12 +01:00
commit a29c5e1fec
549 changed files with 441216 additions and 0 deletions

View File

@@ -0,0 +1,531 @@
#include <thread>
#include <filesystem>
#include <typeindex>
#include "TargetController.hpp"
#include "src/Exceptions/InvalidConfig.hpp"
#include "src/Exceptions/TargetControllerStartupFailure.hpp"
#include "src/Application.hpp"
using namespace Bloom;
using namespace Exceptions;
void TargetController::run() {
try {
this->startup();
this->setStateAndEmitEvent(ThreadState::READY);
Logger::debug("TargetController ready and waiting for events.");
while (this->getState() == ThreadState::READY) {
this->fireTargetEvents();
this->eventListener->waitAndDispatch(60);
}
} catch (const TargetControllerStartupFailure& exception) {
Logger::error("TargetController failed to startup. See below for errors:");
Logger::error(exception.getMessage());
} catch (const Exception& exception) {
Logger::error("The TargetController encountered a fatal error. See below for errors:");
Logger::error(exception.getMessage());
} catch (const std::exception& exception) {
Logger::error("The TargetController encountered a fatal error. See below for errors:");
Logger::error(std::string(exception.what()));
}
this->shutdown();
}
void TargetController::startup() {
this->setName("TC");
Logger::info("Starting TargetController");
this->setState(ThreadState::STARTING);
this->blockAllSignalsOnCurrentThread();
this->eventManager.registerListener(this->eventListener);
// Install Bloom's udev rules if not already installed
this->checkUdevRules();
auto debugToolName = this->environmentConfig.debugToolName;
auto targetName = this->environmentConfig.targetConfig.name;
auto supportedDebugTools = TargetController::getSupportedDebugTools();
auto supportedTargets = TargetController::getSupportedTargets();
if (supportedDebugTools.find(debugToolName) == supportedDebugTools.end()) {
throw Exceptions::InvalidConfig(
"Debug tool name (\"" + debugToolName + "\") not recognised. Please check your configuration!"
);
}
if (supportedTargets.find(targetName) == supportedTargets.end()) {
throw Exceptions::InvalidConfig(
"Target name (\"" + targetName + "\") not recognised. Please check your configuration!"
);
}
// Initiate debug tool and target
this->setDebugTool(std::move(supportedDebugTools.find(debugToolName)->second()));
Logger::info("Connecting to debug tool");
this->debugTool->init();
Logger::info("Debug tool connected");
Logger::info("Debug tool name: " + debugTool->getName());
Logger::info("Debug tool serial: " + debugTool->getSerialNumber());
this->setTarget(supportedTargets.find(targetName)->second());
if (!this->target->isDebugToolSupported(debugTool.get())) {
throw Exceptions::InvalidConfig(
"Debug tool (\"" + debugTool->getName() + "\") not supported " +
"by target (\"" + this->target->getName() + "\")."
);
}
this->target->setDebugTool(debugTool.get());
this->target->preActivationConfigure(this->environmentConfig.targetConfig);
Logger::info("Activating target");
this->target->activate();
Logger::info("Target activated");
this->target->postActivationConfigure();
while (this->target->supportsPromotion()) {
auto promotedTarget = this->target->promote();
if (promotedTarget == nullptr
|| std::type_index(typeid(*promotedTarget)) == std::type_index(typeid(*this->target))
) {
break;
}
this->target.reset(promotedTarget.release());
this->target->postPromotionConfigure();
}
Logger::info("Target ID: " + target->getHumanReadableId());
Logger::info("Target name: " + target->getName());
if (this->target->getState() == TargetState::STOPPED) {
this->target->run();
}
// Register event handlers
this->eventListener->registerCallbackForEventType<Events::ShutdownTargetController>(
std::bind(&TargetController::onShutdownTargetControllerEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::DebugSessionStarted>(
std::bind(&TargetController::onDebugSessionStartedEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::DebugSessionFinished>(
std::bind(&TargetController::onDebugSessionFinishedEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::ExtractTargetDescriptor>(
std::bind(&TargetController::onExtractTargetDescriptor, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::StopTargetExecution>(
std::bind(&TargetController::onStopTargetExecutionEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::StepTargetExecution>(
std::bind(&TargetController::onStepTargetExecutionEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::ResumeTargetExecution>(
std::bind(&TargetController::onResumeTargetExecutionEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::RetrieveRegistersFromTarget>(
std::bind(&TargetController::onReadRegistersEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::WriteRegistersToTarget>(
std::bind(&TargetController::onWriteRegistersEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::RetrieveMemoryFromTarget>(
std::bind(&TargetController::onReadMemoryEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::WriteMemoryToTarget>(
std::bind(&TargetController::onWriteMemoryEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::SetBreakpointOnTarget>(
std::bind(&TargetController::onSetBreakpointEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::RemoveBreakpointOnTarget>(
std::bind(&TargetController::onRemoveBreakpointEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::SetProgramCounterOnTarget>(
std::bind(&TargetController::onSetProgramCounterEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::InsightStateChanged>(
std::bind(&TargetController::onInsightStateChangedEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::RetrieveTargetPinStates>(
std::bind(&TargetController::onRetrieveTargetPinStatesEvent, this, std::placeholders::_1)
);
this->eventListener->registerCallbackForEventType<Events::SetTargetPinState>(
std::bind(&TargetController::onSetPinStateEvent, this, std::placeholders::_1)
);
}
void TargetController::checkUdevRules() {
auto bloomRulesPath = std::string("/etc/udev/rules.d/99-bloom.rules");
auto latestBloomRulesPath = Application::getResourcesDirPath() + "/UDevRules/99-bloom.rules";
if (!std::filesystem::exists(bloomRulesPath)) {
Logger::warning("Bloom udev rules missing - attempting installation");
// We can only install them if we're running as root
if (!Application::isRunningAsRoot()) {
Logger::error("Bloom udev rules missing - cannot install udev rules without root privileges.\n"
"Running Bloom once with root privileges will allow it to automatically install the udev rules."
" Alternatively, instructions on manually installing the udev rules can be found "
"here: https://bloom.oscillate.io/some/link.\nBloom may fail to connect to some debug tools "
"until this is resolved.");
return;
}
if (!std::filesystem::exists(latestBloomRulesPath)) {
// This shouldn't happen, but it can if someone has been messing with the installation files
Logger::error("Unable to install Bloom udev rules - \"" + latestBloomRulesPath + "\" does not exist.");
return;
}
std::filesystem::copy(latestBloomRulesPath, bloomRulesPath);
Logger::warning("Bloom udev rules installed - a reconnect of the debug tool may be required "
"before the new udev rules come into effect.");
}
}
void TargetController::shutdown() {
if (this->getState() == ThreadState::STOPPED) {
return;
}
try {
Logger::info("Shutting down TargetController");
//this->targetControllerEventListener->clearAllCallbacks();
this->eventManager.deregisterListener(this->eventListener->getId());
auto target = this->getTarget();
auto debugTool = this->getDebugTool();
if (debugTool != nullptr && debugTool->isInitialised()) {
if (target != nullptr) {
/*
* We call deactivate() without checking if the target is activated. This will address any cases
* where a target is only partially activated (where the call to activate() failed).
*/
Logger::info("Deactivating target");
target->deactivate();
}
Logger::info("Closing debug tool");
debugTool->close();
}
} catch (const std::exception& exception) {
Logger::error("Failed to properly shutdown TargetController. Error: " + std::string(exception.what()));
}
this->setStateAndEmitEvent(ThreadState::STOPPED);
}
void TargetController::fireTargetEvents() {
auto newTargetState = this->target->getState();
if (newTargetState != this->lastTargetState) {
this->lastTargetState = newTargetState;
if (newTargetState == TargetState::STOPPED) {
Logger::debug("Target state changed - STOPPED");
this->eventManager.triggerEvent(std::make_shared<TargetExecutionStopped>(
this->target->getProgramCounter(),
TargetBreakCause::UNKNOWN
));
}
if (newTargetState == TargetState::RUNNING) {
Logger::debug("Target state changed - RUNNING");
this->eventManager.triggerEvent(std::make_shared<TargetExecutionResumed>());
}
}
}
void TargetController::emitErrorEvent(int correlationId) {
auto errorEvent = std::make_shared<Events::TargetControllerErrorOccurred>();
errorEvent->correlationId = correlationId;
this->eventManager.triggerEvent(errorEvent);
}
void TargetController::onShutdownTargetControllerEvent(EventPointer<Events::ShutdownTargetController> event) {
this->shutdown();
}
void TargetController::onExtractTargetDescriptor(EventPointer<Events::ExtractTargetDescriptor> event) {
if (!this->cachedTargetDescriptor.has_value()) {
this->cachedTargetDescriptor = this->target->getDescriptor();
}
auto targetDescriptorExtracted = std::make_shared<TargetDescriptorExtracted>();
targetDescriptorExtracted->targetDescriptor = this->cachedTargetDescriptor.value();
targetDescriptorExtracted->correlationId = event->id;
this->eventManager.triggerEvent(targetDescriptorExtracted);
}
void TargetController::onStopTargetExecutionEvent(EventPointer<Events::StopTargetExecution> event) {
if (this->target->getState() != TargetState::STOPPED) {
this->target->stop();
this->lastTargetState = TargetState::STOPPED;
}
auto executionStoppedEvent = std::make_shared<TargetExecutionStopped>(
this->target->getProgramCounter(),
TargetBreakCause::UNKNOWN
);
executionStoppedEvent->correlationId = event->id;
this->eventManager.triggerEvent(executionStoppedEvent);
}
void TargetController::onStepTargetExecutionEvent(EventPointer<Events::StepTargetExecution> event) {
try {
if (this->target->getState() != TargetState::STOPPED) {
// We can't step the target if it's already running.
throw Exception("Target is already running");
}
if (event->fromProgramCounter.has_value()) {
this->target->setProgramCounter(event->fromProgramCounter.value());
}
this->target->step();
this->lastTargetState = TargetState::RUNNING;
auto executionResumedEvent = std::make_shared<TargetExecutionResumed>();
executionResumedEvent->correlationId = event->id;
this->eventManager.triggerEvent(executionResumedEvent);
} catch (const Exception& exception) {
Logger::error("Failed to step execution on target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onResumeTargetExecutionEvent(EventPointer<Events::ResumeTargetExecution> event) {
try {
if (this->target->getState() != TargetState::RUNNING) {
if (event->fromProgramCounter.has_value()) {
this->target->setProgramCounter(event->fromProgramCounter.value());
}
this->target->run();
this->lastTargetState = TargetState::RUNNING;
}
auto executionResumedEvent = std::make_shared<Events::TargetExecutionResumed>();
executionResumedEvent->correlationId = event->id;
this->eventManager.triggerEvent(executionResumedEvent);
} catch (const Exception& exception) {
Logger::error("Failed to stop execution on target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onReadRegistersEvent(EventPointer<Events::RetrieveRegistersFromTarget> event) {
try {
auto registers = this->target->readRegisters(event->descriptors);
if (registers.size() > 0) {
auto registersRetrievedEvent = std::make_shared<Events::RegistersRetrievedFromTarget>();
registersRetrievedEvent->correlationId = event->id;
registersRetrievedEvent->registers = registers;
this->eventManager.triggerEvent(registersRetrievedEvent);
}
} catch (const Exception& exception) {
Logger::error("Failed to read general registers from target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onWriteRegistersEvent(EventPointer<Events::WriteRegistersToTarget> event) {
try {
this->target->writeRegisters(event->registers);
auto registersWrittenEvent = std::make_shared<Events::RegistersWrittenToTarget>();
registersWrittenEvent->correlationId = event->id;
this->eventManager.triggerEvent(registersWrittenEvent);
} catch (const Exception& exception) {
Logger::error("Failed to write registers to target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onReadMemoryEvent(EventPointer<Events::RetrieveMemoryFromTarget> event) {
try {
auto memoryReadEvent = std::make_shared<Events::MemoryRetrievedFromTarget>();
memoryReadEvent->correlationId = event->id;
memoryReadEvent->data = this->target->readMemory(event->memoryType, event->startAddress, event->bytes);
this->eventManager.triggerEvent(memoryReadEvent);
} catch (const Exception& exception) {
Logger::error("Failed to read memory from target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onWriteMemoryEvent(EventPointer<Events::WriteMemoryToTarget> event) {
try {
this->target->writeMemory(event->memoryType, event->startAddress, event->buffer);
auto memoryWrittenEvent = std::make_shared<Events::MemoryWrittenToTarget>();
memoryWrittenEvent->correlationId = event->id;
this->eventManager.triggerEvent(memoryWrittenEvent);
if (this->target->willMemoryWriteAffectIoPorts(
event->memoryType,
event->startAddress,
static_cast<std::uint32_t>(event->buffer.size())
)) {
// This memory write has affected the target's IO port values
this->eventManager.triggerEvent(std::make_shared<Events::TargetIoPortsUpdated>());
}
} catch (const Exception& exception) {
Logger::error("Failed to write memory to target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onSetBreakpointEvent(EventPointer<Events::SetBreakpointOnTarget> event) {
try {
this->target->setBreakpoint(event->breakpoint.address);
auto breakpointSetEvent = std::make_shared<Events::BreakpointSetOnTarget>();
breakpointSetEvent->correlationId = event->id;
this->eventManager.triggerEvent(breakpointSetEvent);
} catch (const Exception& exception) {
Logger::error("Failed to set breakpoint on target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onRemoveBreakpointEvent(EventPointer<Events::RemoveBreakpointOnTarget> event) {
try {
this->target->removeBreakpoint(event->breakpoint.address);
auto breakpointRemovedEvent = std::make_shared<Events::BreakpointRemovedOnTarget>();
breakpointRemovedEvent->correlationId = event->id;
this->eventManager.triggerEvent(breakpointRemovedEvent);
} catch (const Exception& exception) {
Logger::error("Failed to remove breakpoint on target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onDebugSessionStartedEvent(EventPointer<Events::DebugSessionStarted>) {
this->target->reset();
if (this->target->getState() != TargetState::STOPPED) {
this->target->stop();
}
}
void TargetController::onDebugSessionFinishedEvent(EventPointer<DebugSessionFinished>) {
if (this->target->getState() != TargetState::RUNNING) {
this->target->run();
}
}
void TargetController::onSetProgramCounterEvent(EventPointer<Events::SetProgramCounterOnTarget> event) {
try {
if (this->target->getState() != TargetState::STOPPED) {
throw Exception("Invalid target state - target must be stopped before the program counter can be updated");
}
this->target->setProgramCounter(event->address);
auto programCounterSetEvent = std::make_shared<Events::ProgramCounterSetOnTarget>();
programCounterSetEvent->correlationId = event->id;
this->eventManager.triggerEvent(programCounterSetEvent);
} catch (const Exception& exception) {
Logger::error("Failed to set program counter on target - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
// TODO: remove this
void TargetController::onInsightStateChangedEvent(EventPointer<Events::InsightStateChanged> event) {
if (event->getState() == ThreadState::READY) {
/*
* Insight has just started up.
*
* Refresh the target state and kick off a target stop/resume execution event. Setting the lastTargetState
* to UNKNOWN will be enough to do this. See TargetController::fireTargetEvents().
*/
this->lastTargetState = TargetState::UNKNOWN;
}
}
void TargetController::onRetrieveTargetPinStatesEvent(EventPointer<Events::RetrieveTargetPinStates> event) {
try {
if (this->target->getState() != TargetState::STOPPED) {
throw Exception("Invalid target state - target must be stopped before pin states can be retrieved");
}
auto pinStatesRetrieved = std::make_shared<Events::TargetPinStatesRetrieved>();
pinStatesRetrieved->correlationId = event->id;
pinStatesRetrieved->variantId = event->variantId;
pinStatesRetrieved->pinSatesByNumber = this->target->getPinStates(event->variantId);
this->eventManager.triggerEvent(pinStatesRetrieved);
} catch (const Exception& exception) {
Logger::error("Failed to retrieve target pin states - " + exception.getMessage());
this->emitErrorEvent(event->id);
}
}
void TargetController::onSetPinStateEvent(EventPointer<Events::SetTargetPinState> event) {
try {
if (this->target->getState() != TargetState::STOPPED) {
throw Exception("Invalid target state - target must be stopped before pin state can be set");
}
this->target->setPinState(event->variantId, event->pinDescriptor, event->pinState);
auto pinStatesUpdateEvent = std::make_shared<Events::TargetPinStatesRetrieved>();
pinStatesUpdateEvent->correlationId = event->id;
pinStatesUpdateEvent->variantId = event->variantId;
pinStatesUpdateEvent->pinSatesByNumber = {
{event->pinDescriptor.number, event->pinState}
};
this->eventManager.triggerEvent(pinStatesUpdateEvent);
} catch (const Exception& exception) {
Logger::error("Failed to set target pin state for pin " + event->pinDescriptor.name + " - "
+ exception.getMessage());
this->emitErrorEvent(event->id);
}
}

View File

@@ -0,0 +1,222 @@
#pragma once
#include <memory>
#include <map>
#include <string>
#include <functional>
#include <QJsonObject>
#include <QJsonArray>
#include "src/Helpers/Thread.hpp"
#include "src/Logger/Logger.hpp"
#include "src/EventManager/EventListener.hpp"
#include "src/DebugToolDrivers/DebugTools.hpp"
#include "src/Targets/Target.hpp"
#include "src/Targets/Targets.hpp"
#include "src/EventManager/EventManager.hpp"
#include "src/EventManager/Events/Events.hpp"
namespace Bloom
{
using namespace Targets;
using namespace DebugToolDrivers;
using namespace Targets::Microchip::Avr;
using Avr8Bit::Avr8;
using Events::EventPointer;
/**
* The TargetController possesses full control of the debugging target and the debug tool.
*
` * The TargetController runs on a dedicated thread. Its sole purpose is to handle communication to &from the
* debug tool and target.
*
* The TargetController should be oblivious to any manufacture/device specific functionality. It should
* only ever interface with the base Target and DebugTool classes.
*/
class TargetController: public Thread
{
private:
ApplicationConfig applicationConfig;
EnvironmentConfig environmentConfig;
std::unique_ptr<Targets::Target> target = nullptr;
std::unique_ptr<DebugTool> debugTool = nullptr;
EventManager& eventManager;
EventListenerPointer eventListener = std::make_shared<EventListener>("TargetControllerEventListener");
TargetState lastTargetState = TargetState::UNKNOWN;
std::optional<TargetDescriptor> cachedTargetDescriptor;
/**
* Constructs a mapping of supported debug tool names to lambdas. The lambdas should *only* instantiate
* and return an instance to the derived DebugTool class. They should never attempt to establish
* a connection to the device.
*
* Currently, the only debug tool we support is the Atmel-ICE.
*
* @return
*/
static auto getSupportedDebugTools() {
return std::map<std::string, std::function<std::unique_ptr<DebugTool>()>> {
{
"atmel-ice",
[]() -> std::unique_ptr<DebugTool> {
return std::make_unique<AtmelIce>();
}
},
{
"power-debugger",
[]() -> std::unique_ptr<DebugTool> {
return std::make_unique<PowerDebugger>();
}
},
};
}
/**
* Constructs a mapping of supported target names to lambdas. The lambdas should instantiate and return an
* instance to the appropriate Target class.
*
* @return
*/
static auto getSupportedTargets() {
auto mapping = std::map<std::string, std::function<std::unique_ptr<Targets::Target>()>> {
{
"avr8",
[]() -> std::unique_ptr<Targets::Target> {
return std::make_unique<Avr8>();
}
},
};
// Include all targets from AVR8 part description files
auto avr8PdMapping = Avr8Bit::PartDescriptionFile::getPartDescriptionMapping();
for (auto mapIt = avr8PdMapping.begin(); mapIt != avr8PdMapping.end(); mapIt++) {
// Each target signature maps to an array of targets, as numerous targets can possess the same signature.
auto targets = mapIt.value().toArray();
for (auto targetIt = targets.begin(); targetIt != targets.end(); targetIt++) {
auto targetName = targetIt->toObject().find("targetName").value().toString()
.toLower().toStdString();
if (mapping.find(targetName) == mapping.end()) {
mapping.insert({
targetName,
[targetName]() -> std::unique_ptr<Targets::Target> {
return std::make_unique<Avr8>(targetName);
}
});
}
}
}
return mapping;
}
void setDebugTool(std::unique_ptr<DebugTool> debugTool) {
this->debugTool = std::move(debugTool);
}
void setTarget(std::unique_ptr<Targets::Target> target) {
this->target = std::move(target);
}
Targets::Target* getTarget() {
return this->target.get();
}
DebugTool* getDebugTool() {
return this->debugTool.get();
}
/**
* Updates the state of the TargetController and emits a state changed event.
*
* @param state
* @param emitEvent
*/
void setStateAndEmitEvent(ThreadState state) {
this->setState(state);
this->eventManager.triggerEvent(
std::make_shared<Events::TargetControllerStateChanged>(state)
);
};
/**
* Installs Bloom's udev rules on user's machine. Rules are copied from build/Distribution/Resources/UdevRules
* to /etc/udev/rules.d/. This method will report an error if Bloom isn't running as root (as root privileges
* are required for writing to files in /etc/udev).
*/
void checkUdevRules();
/**
* Because the TargetController hogs the thread, this method must be called in a dedicated thread.
*/
void startup();
/**
* Exit point - must be called before the TargetController thread is terminated.
*
* Handles deactivating the target among other clean-up related things.
*/
void shutdown();
/**
* Should fire any events queued on the target.
*/
void fireTargetEvents();
void emitErrorEvent(int correlationId);
public:
TargetController(EventManager& eventManager) : eventManager(eventManager) {};
void setApplicationConfig(const ApplicationConfig& applicationConfig) {
this->applicationConfig = applicationConfig;
}
void setEnvironmentConfig(const EnvironmentConfig& environmentConfig) {
this->environmentConfig = environmentConfig;
}
/**
* Entry point for the TargetController.
*/
void run();
void onExtractTargetDescriptor(EventPointer<Events::ExtractTargetDescriptor> event);
/**
* Callback for StopTargetExecution event.
*
* Will attempt to stop the target and emit a TargetExecutionStopped event.
*/
void onStopTargetExecutionEvent(EventPointer<Events::StopTargetExecution> event);
void onStepTargetExecutionEvent(EventPointer<Events::StepTargetExecution> event);
/**
* Callback for ResumeTargetExecution event.
*/
void onResumeTargetExecutionEvent(EventPointer<Events::ResumeTargetExecution> event);
/**
* Callback for ShutdownTargetController event.
*/
void onShutdownTargetControllerEvent(EventPointer<Events::ShutdownTargetController> event);
void onReadRegistersEvent(EventPointer<Events::RetrieveRegistersFromTarget> event);
void onWriteRegistersEvent(EventPointer<Events::WriteRegistersToTarget> event);
void onReadMemoryEvent(EventPointer<Events::RetrieveMemoryFromTarget> event);
void onWriteMemoryEvent(EventPointer<Events::WriteMemoryToTarget> event);
void onSetBreakpointEvent(EventPointer<Events::SetBreakpointOnTarget> event);
void onRemoveBreakpointEvent(EventPointer<Events::RemoveBreakpointOnTarget> event);
void onDebugSessionStartedEvent(EventPointer<Events::DebugSessionStarted> event);
void onDebugSessionFinishedEvent(EventPointer<Events::DebugSessionFinished> event);
void onSetProgramCounterEvent(EventPointer<Events::SetProgramCounterOnTarget> event);
void onInsightStateChangedEvent(EventPointer<Events::InsightStateChanged> event);
void onRetrieveTargetPinStatesEvent(EventPointer<Events::RetrieveTargetPinStates> event);
void onSetPinStateEvent(EventPointer<Events::SetTargetPinState> event);
};
}