Qt: Let memory access logs be loaded read-only

This commit is contained in:
Vicki Pfau 2025-01-18 23:46:24 -08:00
parent 7012f9c666
commit 4cc49a6700
5 changed files with 155 additions and 33 deletions

View File

@ -65,7 +65,9 @@ void MemoryAccessLogController::updateRegion(const QString& internalName, bool c
if (!m_active) {
return;
}
if (checked && !m_regionMapping.contains(internalName)) {
m_regionMapping[internalName] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, internalName.toUtf8().constData(), activeFlags());
}
emit regionMappingChanged(internalName, checked);
}
@ -74,6 +76,38 @@ void MemoryAccessLogController::setFile(const QString& path) {
}
void MemoryAccessLogController::start(bool loadExisting, bool logExtra) {
if (!m_loaded) {
load(loadExisting);
}
if (!m_loaded) {
return;
}
CoreController::Interrupter interrupter(m_controller);
mDebuggerAccessLoggerStart(&m_logger);
m_logExtra = logExtra;
m_active = true;
for (const auto& region : m_watchedRegions) {
m_regionMapping[region] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, region.toUtf8().constData(), activeFlags());
}
emit loggingChanged(true);
}
void MemoryAccessLogController::stop() {
if (!m_active) {
return;
}
CoreController::Interrupter interrupter(m_controller);
mDebuggerAccessLoggerStop(&m_logger);
emit loggingChanged(false);
interrupter.resume();
m_active = false;
}
void MemoryAccessLogController::load(bool loadExisting) {
if (m_loaded) {
return;
}
int flags = O_CREAT | O_RDWR;
if (!loadExisting) {
flags |= O_TRUNC;
@ -83,7 +117,6 @@ void MemoryAccessLogController::start(bool loadExisting, bool logExtra) {
LOG(QT, ERROR) << tr("Failed to open memory log file");
return;
}
m_logExtra = logExtra;
mDebuggerAccessLoggerInit(&m_logger);
CoreController::Interrupter interrupter(m_controller);
@ -93,26 +126,22 @@ void MemoryAccessLogController::start(bool loadExisting, bool logExtra) {
LOG(QT, ERROR) << tr("Failed to open memory log file");
return;
}
mDebuggerAccessLoggerStart(&m_logger);
m_active = true;
emit loggingChanged(true);
for (const auto& region : m_watchedRegions) {
m_regionMapping[region] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, region.toUtf8().constData(), activeFlags());
}
interrupter.resume();
emit loaded(true);
m_loaded = true;
}
void MemoryAccessLogController::stop() {
if (!m_active) {
void MemoryAccessLogController::unload() {
if (m_active) {
stop();
}
if (m_active) {
return;
}
CoreController::Interrupter interrupter(m_controller);
m_controller->detachDebuggerModule(&m_logger.d);
mDebuggerAccessLoggerDeinit(&m_logger);
emit loggingChanged(false);
interrupter.resume();
m_active = false;
emit loaded(false);
m_loaded = false;
}
mDebuggerAccessLogRegionFlags MemoryAccessLogController::activeFlags() const {

View File

@ -49,6 +49,7 @@ public:
QString file() const { return m_path; }
bool active() const { return m_active; }
bool isLoaded() const { return m_loaded; }
public slots:
void updateRegion(const QString& internalName, bool enable);
@ -57,9 +58,13 @@ public slots:
void start(bool loadExisting, bool logExtra);
void stop();
void load(bool loadExisting);
void unload();
void exportFile(const QString& filename);
signals:
void loaded(bool loaded);
void loggingChanged(bool active);
void regionMappingChanged(const QString& internalName, bool active);
@ -71,6 +76,7 @@ private:
QHash<QString, int> m_regionMapping;
QVector<Region> m_regions;
struct mDebuggerAccessLogger m_logger{};
bool m_loaded = false;
bool m_active = false;
mDebuggerAccessLogRegion* m_cachedRegion = nullptr;

View File

@ -26,8 +26,10 @@ MemoryAccessLogView::MemoryAccessLogView(std::weak_ptr<MemoryAccessLogController
connect(m_ui.exportButton, &QAbstractButton::clicked, this, &MemoryAccessLogView::exportFile);
connect(controllerPtr.get(), &MemoryAccessLogController::regionMappingChanged, this, &MemoryAccessLogView::updateRegion);
connect(controllerPtr.get(), &MemoryAccessLogController::loggingChanged, this, &MemoryAccessLogView::handleStartStop);
connect(controllerPtr.get(), &MemoryAccessLogController::loaded, this, &MemoryAccessLogView::handleLoadUnload);
bool active = controllerPtr->active();
bool loaded = controllerPtr->isLoaded();
auto watchedRegions = controllerPtr->watchedRegions();
QVBoxLayout* regionBox = static_cast<QVBoxLayout*>(m_ui.regionBox->layout());
@ -46,11 +48,14 @@ MemoryAccessLogView::MemoryAccessLogView(std::weak_ptr<MemoryAccessLogController
});
}
handleLoadUnload(loaded);
handleStartStop(active);
}
void MemoryAccessLogView::updateRegion(const QString& internalName, bool) {
void MemoryAccessLogView::updateRegion(const QString& internalName, bool checked) {
if (checked) {
m_regionBoxes[internalName]->setEnabled(false);
}
}
void MemoryAccessLogView::start() {
@ -68,10 +73,23 @@ void MemoryAccessLogView::stop() {
return;
}
controllerPtr->stop();
for (const auto& region : controllerPtr->watchedRegions()) {
m_regionBoxes[region]->setEnabled(true);
}
void MemoryAccessLogView::load() {
std::shared_ptr<MemoryAccessLogController> controllerPtr = m_controller.lock();
if (!controllerPtr) {
return;
}
m_ui.exportButton->setEnabled(false);
controllerPtr->setFile(m_ui.filename->text());
controllerPtr->load(m_ui.loadExisting->isChecked());
}
void MemoryAccessLogView::unload() {
std::shared_ptr<MemoryAccessLogController> controllerPtr = m_controller.lock();
if (!controllerPtr) {
return;
}
controllerPtr->unload();
}
void MemoryAccessLogView::selectFile() {
@ -110,12 +128,26 @@ void MemoryAccessLogView::handleStartStop(bool start) {
m_regionBoxes[region]->setChecked(true);
}
if (watchedRegions.contains(QString("cart0"))) {
m_ui.exportButton->setEnabled(start);
}
m_ui.start->setDisabled(start);
m_ui.stop->setEnabled(start);
m_ui.filename->setDisabled(start);
m_ui.browse->setDisabled(start);
m_ui.unload->setDisabled(start || !controllerPtr->isLoaded());
}
void MemoryAccessLogView::handleLoadUnload(bool load) {
std::shared_ptr<MemoryAccessLogController> controllerPtr = m_controller.lock();
if (!controllerPtr) {
return;
}
m_ui.filename->setText(controllerPtr->file());
if (load && controllerPtr->canExport()) {
m_ui.exportButton->setEnabled(true);
} else if (!load) {
m_ui.exportButton->setEnabled(false);
}
m_ui.load->setDisabled(load);
m_ui.unload->setEnabled(load);
m_ui.filename->setDisabled(load);
m_ui.browse->setDisabled(load);
}

View File

@ -34,9 +34,13 @@ private slots:
void start();
void stop();
void load();
void unload();
void exportFile();
void handleStartStop(bool start);
void handleLoadUnload(bool load);
private:
Ui::MemoryAccessLogView m_ui;

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>385</width>
<height>380</height>
<width>311</width>
<height>387</height>
</rect>
</property>
<property name="windowTitle">
@ -22,25 +22,25 @@
<property name="title">
<string>Log file</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="3,1,2">
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="filename"/>
</item>
<item row="0" column="1">
<item row="0" column="2">
<widget class="QPushButton" name="browse">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<item row="1" column="0" colspan="3">
<widget class="QCheckBox" name="logExtra">
<property name="text">
<string>Log additional information (uses 3× space)</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="2" column="0" colspan="3">
<widget class="QCheckBox" name="loadExisting">
<property name="text">
<string>Load existing file if present</string>
@ -50,6 +50,23 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="load">
<property name="text">
<string>Load</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QPushButton" name="unload">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Unload</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -124,9 +141,43 @@
</hint>
</hints>
</connection>
<connection>
<sender>load</sender>
<signal>clicked()</signal>
<receiver>QGBA::MemoryAccessLogView</receiver>
<slot>load()</slot>
<hints>
<hint type="sourcelabel">
<x>81</x>
<y>152</y>
</hint>
<hint type="destinationlabel">
<x>192</x>
<y>189</y>
</hint>
</hints>
</connection>
<connection>
<sender>unload</sender>
<signal>clicked()</signal>
<receiver>QGBA::MemoryAccessLogView</receiver>
<slot>unload()</slot>
<hints>
<hint type="sourcelabel">
<x>226</x>
<y>152</y>
</hint>
<hint type="destinationlabel">
<x>192</x>
<y>189</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>start()</slot>
<slot>stop()</slot>
<slot>load()</slot>
<slot>unload()</slot>
</slots>
</ui>