CaptureMemorySnapshot insight worker task

This commit is contained in:
Nav
2022-12-24 02:40:57 +00:00
parent 59776f1a0e
commit be5127feda
3 changed files with 150 additions and 0 deletions

View File

@@ -32,6 +32,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/GetTargetState.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/GetTargetState.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/GetTargetDescriptor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/GetTargetDescriptor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ConstructHexViewerByteItems.cpp ${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ConstructHexViewerByteItems.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/CaptureMemorySnapshot.cpp
# Error dialogue window # Error dialogue window
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/ErrorDialogue/ErrorDialogue.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/ErrorDialogue/ErrorDialogue.cpp

View File

@@ -0,0 +1,107 @@
#include "CaptureMemorySnapshot.hpp"
#include <QFile>
#include <QDir>
#include <QJsonDocument>
#include "src/Helpers/Paths.hpp"
#include "src/Helpers/EnumToStringMappings.hpp"
#include "src/Logger/Logger.hpp"
namespace Bloom
{
using TargetController::TargetControllerConsole;
CaptureMemorySnapshot::CaptureMemorySnapshot(
const QString& name,
const QString& description,
Targets::TargetMemoryType memoryType,
const std::vector<FocusedMemoryRegion>& focusedRegions,
const std::vector<ExcludedMemoryRegion>& excludedRegions,
const std::optional<Targets::TargetMemoryBuffer>& data
)
: name(name)
, description(description)
, memoryType(memoryType)
, focusedRegions(focusedRegions)
, excludedRegions(excludedRegions)
, data(data)
{}
void CaptureMemorySnapshot::run(TargetControllerConsole& targetControllerConsole) {
using Targets::TargetMemorySize;
Logger::info("Capturing snapshot");
const auto& targetDescriptor = targetControllerConsole.getTargetDescriptor();
const auto memoryDescriptorIt = targetDescriptor.memoryDescriptorsByType.find(this->memoryType);
if (memoryDescriptorIt == targetDescriptor.memoryDescriptorsByType.end()) {
throw Exceptions::Exception("Invalid memory type");
}
const auto& memoryDescriptor = memoryDescriptorIt->second;
const auto memorySize = memoryDescriptor.size();
if (!this->data.has_value()) {
Logger::info("Reading data for snapshot capture");
this->data = Targets::TargetMemoryBuffer();
this->data->reserve(memorySize);
const auto readSize = std::max(
TargetMemorySize(256),
memoryDescriptor.pageSize.value_or(TargetMemorySize(0))
);
const auto readsRequired = static_cast<std::uint32_t>(
std::ceil(static_cast<float>(memorySize) / static_cast<float>(readSize))
);
for (std::uint32_t i = 0; i < readsRequired; i++) {
auto dataSegment = targetControllerConsole.readMemory(
this->memoryType,
memoryDescriptor.addressRange.startAddress + static_cast<Targets::TargetMemoryAddress>(readSize * i),
(memorySize - this->data->size()) >= readSize
? readSize
: static_cast<Targets::TargetMemorySize>(memorySize - this->data->size()),
{}
);
std::move(dataSegment.begin(), dataSegment.end(), std::back_inserter(*this->data));
}
}
assert(this->data->size() == memorySize);
auto snapshot = MemorySnapshot(
std::move(this->name),
std::move(this->description),
this->memoryType,
std::move(*this->data),
targetControllerConsole.getProgramCounter(),
std::move(this->focusedRegions),
std::move(this->excludedRegions)
);
const auto snapshotDirPath = QString::fromStdString(Paths::projectSettingsDirPath())
+ "/memory_snapshots/" + EnumToStringMappings::targetMemoryTypes.at(snapshot.memoryType);
QDir().mkpath(snapshotDirPath);
const auto snapshotFilePath = snapshotDirPath + "/" + snapshot.id + ".json";
auto outputFile = QFile(snapshotFilePath);
if (!outputFile.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
Logger::error("Failed to save snapshot - cannot open " + snapshotFilePath.toStdString());
return;
}
outputFile.write(QJsonDocument(snapshot.toJson()).toJson(QJsonDocument::JsonFormat::Compact));
outputFile.close();
Logger::info("Snapshot captured - UUID: " + snapshot.id.toStdString());
emit this->memorySnapshotCaptured(std::move(snapshot));
}
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include <QString>
#include <optional>
#include "InsightWorkerTask.hpp"
#include "src/Targets/TargetMemory.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemorySnapshot.hpp"
namespace Bloom
{
class CaptureMemorySnapshot: public InsightWorkerTask
{
Q_OBJECT
public:
CaptureMemorySnapshot(
const QString& name,
const QString& description,
Targets::TargetMemoryType memoryType,
const std::vector<FocusedMemoryRegion>& focusedRegions,
const std::vector<ExcludedMemoryRegion>& excludedRegions,
const std::optional<Targets::TargetMemoryBuffer>& data
);
signals:
void memorySnapshotCaptured(MemorySnapshot snapshot);
protected:
void run(TargetController::TargetControllerConsole& targetControllerConsole) override;
private:
QString name;
QString description;
Targets::TargetMemoryType memoryType;
std::vector<FocusedMemoryRegion> focusedRegions;
std::vector<ExcludedMemoryRegion> excludedRegions;
std::optional<Targets::TargetMemoryBuffer> data;
};
}