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

View File

@ -49,6 +49,7 @@ public:
QString file() const { return m_path; } QString file() const { return m_path; }
bool active() const { return m_active; } bool active() const { return m_active; }
bool isLoaded() const { return m_loaded; }
public slots: public slots:
void updateRegion(const QString& internalName, bool enable); void updateRegion(const QString& internalName, bool enable);
@ -57,9 +58,13 @@ public slots:
void start(bool loadExisting, bool logExtra); void start(bool loadExisting, bool logExtra);
void stop(); void stop();
void load(bool loadExisting);
void unload();
void exportFile(const QString& filename); void exportFile(const QString& filename);
signals: signals:
void loaded(bool loaded);
void loggingChanged(bool active); void loggingChanged(bool active);
void regionMappingChanged(const QString& internalName, bool active); void regionMappingChanged(const QString& internalName, bool active);
@ -71,6 +76,7 @@ private:
QHash<QString, int> m_regionMapping; QHash<QString, int> m_regionMapping;
QVector<Region> m_regions; QVector<Region> m_regions;
struct mDebuggerAccessLogger m_logger{}; struct mDebuggerAccessLogger m_logger{};
bool m_loaded = false;
bool m_active = false; bool m_active = false;
mDebuggerAccessLogRegion* m_cachedRegion = nullptr; 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(m_ui.exportButton, &QAbstractButton::clicked, this, &MemoryAccessLogView::exportFile);
connect(controllerPtr.get(), &MemoryAccessLogController::regionMappingChanged, this, &MemoryAccessLogView::updateRegion); connect(controllerPtr.get(), &MemoryAccessLogController::regionMappingChanged, this, &MemoryAccessLogView::updateRegion);
connect(controllerPtr.get(), &MemoryAccessLogController::loggingChanged, this, &MemoryAccessLogView::handleStartStop); connect(controllerPtr.get(), &MemoryAccessLogController::loggingChanged, this, &MemoryAccessLogView::handleStartStop);
connect(controllerPtr.get(), &MemoryAccessLogController::loaded, this, &MemoryAccessLogView::handleLoadUnload);
bool active = controllerPtr->active(); bool active = controllerPtr->active();
bool loaded = controllerPtr->isLoaded();
auto watchedRegions = controllerPtr->watchedRegions(); auto watchedRegions = controllerPtr->watchedRegions();
QVBoxLayout* regionBox = static_cast<QVBoxLayout*>(m_ui.regionBox->layout()); QVBoxLayout* regionBox = static_cast<QVBoxLayout*>(m_ui.regionBox->layout());
@ -46,12 +48,15 @@ MemoryAccessLogView::MemoryAccessLogView(std::weak_ptr<MemoryAccessLogController
}); });
} }
handleLoadUnload(loaded);
handleStartStop(active); handleStartStop(active);
} }
void MemoryAccessLogView::updateRegion(const QString& internalName, bool) { void MemoryAccessLogView::updateRegion(const QString& internalName, bool checked) {
if (checked) {
m_regionBoxes[internalName]->setEnabled(false); m_regionBoxes[internalName]->setEnabled(false);
} }
}
void MemoryAccessLogView::start() { void MemoryAccessLogView::start() {
std::shared_ptr<MemoryAccessLogController> controllerPtr = m_controller.lock(); std::shared_ptr<MemoryAccessLogController> controllerPtr = m_controller.lock();
@ -68,10 +73,23 @@ void MemoryAccessLogView::stop() {
return; return;
} }
controllerPtr->stop(); controllerPtr->stop();
for (const auto& region : controllerPtr->watchedRegions()) {
m_regionBoxes[region]->setEnabled(true);
} }
m_ui.exportButton->setEnabled(false);
void MemoryAccessLogView::load() {
std::shared_ptr<MemoryAccessLogController> controllerPtr = m_controller.lock();
if (!controllerPtr) {
return;
}
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() { void MemoryAccessLogView::selectFile() {
@ -110,12 +128,26 @@ void MemoryAccessLogView::handleStartStop(bool start) {
m_regionBoxes[region]->setChecked(true); m_regionBoxes[region]->setChecked(true);
} }
if (watchedRegions.contains(QString("cart0"))) {
m_ui.exportButton->setEnabled(start);
}
m_ui.start->setDisabled(start); m_ui.start->setDisabled(start);
m_ui.stop->setEnabled(start); m_ui.stop->setEnabled(start);
m_ui.filename->setDisabled(start); m_ui.unload->setDisabled(start || !controllerPtr->isLoaded());
m_ui.browse->setDisabled(start); }
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 start();
void stop(); void stop();
void load();
void unload();
void exportFile(); void exportFile();
void handleStartStop(bool start); void handleStartStop(bool start);
void handleLoadUnload(bool load);
private: private:
Ui::MemoryAccessLogView m_ui; Ui::MemoryAccessLogView m_ui;

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>385</width> <width>311</width>
<height>380</height> <height>387</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -22,25 +22,25 @@
<property name="title"> <property name="title">
<string>Log file</string> <string>Log file</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2" columnstretch="3,1,2">
<item row="0" column="0"> <item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="filename"/> <widget class="QLineEdit" name="filename"/>
</item> </item>
<item row="0" column="1"> <item row="0" column="2">
<widget class="QPushButton" name="browse"> <widget class="QPushButton" name="browse">
<property name="text"> <property name="text">
<string>Browse</string> <string>Browse</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0" colspan="2"> <item row="1" column="0" colspan="3">
<widget class="QCheckBox" name="logExtra"> <widget class="QCheckBox" name="logExtra">
<property name="text"> <property name="text">
<string>Log additional information (uses 3× space)</string> <string>Log additional information (uses 3× space)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="3">
<widget class="QCheckBox" name="loadExisting"> <widget class="QCheckBox" name="loadExisting">
<property name="text"> <property name="text">
<string>Load existing file if present</string> <string>Load existing file if present</string>
@ -50,6 +50,23 @@
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
</item> </item>
@ -124,9 +141,43 @@
</hint> </hint>
</hints> </hints>
</connection> </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> </connections>
<slots> <slots>
<slot>start()</slot> <slot>start()</slot>
<slot>stop()</slot> <slot>stop()</slot>
<slot>load()</slot>
<slot>unload()</slot>
</slots> </slots>
</ui> </ui>