diff --git a/CHANGELOG.md b/CHANGELOG.md index d01498d..a8f193b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Remove whitespace from C/C++ lines in the Assembly tab. * Allow assembly code to have its own font format. See Config->Editor->AssemblyText. * Add Nexti and Stepi toolbar buttons if Assembly tab is shown. +* Add PC, SP, FLAGS status bar to Assembly tab. ## [1.13] - 2022-12-02 diff --git a/src/SeerEditorManagerWidget.cpp b/src/SeerEditorManagerWidget.cpp index c546bd7..a60614c 100644 --- a/src/SeerEditorManagerWidget.cpp +++ b/src/SeerEditorManagerWidget.cpp @@ -151,6 +151,7 @@ void SeerEditorManagerWidget::showAssembly () { } assemblyWidgetTab()->assemblyArea()->setAddress("$pc"); + assemblyWidgetTab()->reloadRegisters(); } SeerEditorWidgetAssembly* SeerEditorManagerWidget::assemblyWidgetTab () { @@ -445,6 +446,7 @@ void SeerEditorManagerWidget::handleText (const QString& text) { if (assemblyWidget) { assemblyWidget->assemblyArea()->handleText(text); + assemblyWidget->handleText(text); } // Handle certain reasons uniquely. @@ -584,6 +586,7 @@ void SeerEditorManagerWidget::handleText (const QString& text) { if (assemblyWidget) { assemblyWidget->assemblyArea()->handleText(text); + assemblyWidget->handleText(text); } }else if (text.startsWith("^done,asm_insns=")) { @@ -593,6 +596,7 @@ void SeerEditorManagerWidget::handleText (const QString& text) { if (assemblyWidget) { assemblyWidget->assemblyArea()->handleText(text); + assemblyWidget->handleText(text); } }else if (text.startsWith("^error,msg=\"No registers.\"")) { @@ -619,6 +623,13 @@ void SeerEditorManagerWidget::handleText (const QString& text) { static_cast(w)->sourceArea()->handleText(text); } + SeerEditorWidgetAssembly* assemblyWidget = assemblyWidgetTab(); + + if (assemblyWidget) { + assemblyWidget->assemblyArea()->handleText(text); + assemblyWidget->handleText(text); + } + }else if (text.contains(QRegExp("^([0-9]+)\\^error,msg="))) { // 12^error,msg="No symbol \"return\" in current context." @@ -940,6 +951,7 @@ SeerEditorWidgetAssembly* SeerEditorManagerWidget::createAssemblyWidgetTab () { QObject::connect(assemblyWidget->assemblyArea(), &SeerEditorWidgetAssemblyArea::addMemoryVisualize, this, &SeerEditorManagerWidget::handleAddMemoryVisualizer); QObject::connect(assemblyWidget->assemblyArea(), &SeerEditorWidgetAssemblyArea::addArrayVisualize, this, &SeerEditorManagerWidget::handleAddArrayVisualizer); QObject::connect(assemblyWidget->assemblyArea(), &SeerEditorWidgetAssemblyArea::addStructVisualize, this, &SeerEditorManagerWidget::handleAddStructVisualizer); + QObject::connect(assemblyWidget, &SeerEditorWidgetAssembly::evaluateVariableExpression, this, &SeerEditorManagerWidget::handleEvaluateVariableExpression); // Load the file. assemblyWidget->assemblyArea()->setPlainText(""); diff --git a/src/SeerEditorWidgetAssembly.cpp b/src/SeerEditorWidgetAssembly.cpp index 089d1b9..363f0d9 100644 --- a/src/SeerEditorWidgetAssembly.cpp +++ b/src/SeerEditorWidgetAssembly.cpp @@ -1,4 +1,5 @@ #include "SeerEditorWidgetAssembly.h" +#include "SeerUtl.h" #include #include #include @@ -35,6 +36,15 @@ SeerEditorWidgetAssembly::SeerEditorWidgetAssembly(QWidget* parent) : QWidget(pa setKeySettings(SeerKeySettings::populate()); + _pcId = Seer::createID(); + _spId = Seer::createID(); + _flagsId = Seer::createID(); + + // Clear PC, SP, and FLAGS. + pcLineEdit->clear(); + spLineEdit->clear(); + flagsLineEdit->clear(); + // Connect things. QObject::connect(searchTextLineEdit, &QLineEdit::returnPressed, this, &SeerEditorWidgetAssembly::handleSearchTextLineEdit); QObject::connect(matchCaseCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleSearchTextLineEdit); @@ -43,6 +53,7 @@ SeerEditorWidgetAssembly::SeerEditorWidgetAssembly(QWidget* parent) : QWidget(pa QObject::connect(searchLineNumberLineEdit, &QLineEdit::returnPressed, this, &SeerEditorWidgetAssembly::handleSearchLineNumberLineEdit); QObject::connect(searchCloseToolButton, &QToolButton::clicked, this, &SeerEditorWidgetAssembly::handleSearchCloseToolButton); QObject::connect(refreshToolButton, &QToolButton::clicked, this, &SeerEditorWidgetAssembly::reloadAssembly); + QObject::connect(refreshToolButton, &QToolButton::clicked, this, &SeerEditorWidgetAssembly::reloadRegisters); QObject::connect(showAddressCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleShowAddressColumn); QObject::connect(showOffsetCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleShowOffsetColumn); QObject::connect(showOpcodeCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleShowOpcodeColumn); @@ -125,6 +136,19 @@ void SeerEditorWidgetAssembly::reloadAssembly () { QString addr = assemblyArea()->address(); assemblyArea()->setAddress(addr, true); + + // Get the PC, SP, and FLAGS + emit evaluateVariableExpression(_pcId, "$pc"); + emit evaluateVariableExpression(_spId, "$sp"); + emit evaluateVariableExpression(_flagsId, "$ps"); +} + +void SeerEditorWidgetAssembly::reloadRegisters () { + + // Get the PC, SP, and FLAGS + emit evaluateVariableExpression(_pcId, "$pc"); + emit evaluateVariableExpression(_spId, "$sp"); + emit evaluateVariableExpression(_flagsId, "$ps"); } void SeerEditorWidgetAssembly::showSearchBar (bool flag) { @@ -170,6 +194,95 @@ void SeerEditorWidgetAssembly::setShowSourceLines (bool flag) { handleShowSourceLines(); } +void SeerEditorWidgetAssembly::handleText (const QString& text) { + + if (text.startsWith("*stopped")) { + + //qDebug() << text; + + // *stopped, + // + // reason="end-stepping-range", + // + // frame={addr="0x0000000000400b45", + // func="main", + // args=[{name="argc",value="1"},{name="argv",value="0x7fffffffd5b8"}], + // file="helloworld.cpp", + // fullname="/home/erniep/Development/Peak/src/Seer/helloworld/helloworld.cpp", + // line="7", + // arch="i386:x86-64"}, + // + // thread-id="1", + // stopped-threads="all", + // core="6" + + QString newtext = Seer::filterEscapes(text); // Filter escaped characters. + + QString frame_text = Seer::parseFirst(newtext, "frame=", '{', '}', false); + + if (frame_text == "") { + return; + } + + // Get the PC, SP, and FLAGS + emit evaluateVariableExpression(_pcId, "$pc"); + emit evaluateVariableExpression(_spId, "$sp"); + emit evaluateVariableExpression(_flagsId, "$ps"); + + return; + + }else if (text.contains(QRegExp("^([0-9]+)\\^done,value="))) { + + QString id_text = text.section('^', 0,0); + QString value_text = Seer::parseFirst(text, "value=", '"', '"', false); + + if (id_text == QString::number(_pcId)) { + pcLineEdit->setText(Seer::filterEscapes(value_text)); + return; + } + + if (id_text == QString::number(_spId)) { + spLineEdit->setText(Seer::filterEscapes(value_text)); + return; + } + + if (id_text == QString::number(_flagsId)) { + flagsLineEdit->setText(Seer::filterEscapes(value_text)); + return; + } + + }else if (text.contains(QRegExp("^([0-9]+)\\^error,msg="))) { + + QString id_text = text.section('^', 0,0); + QString msg_text = Seer::parseFirst(text, "value=", '"', '"', false); + + if (id_text == QString::number(_pcId)) { + pcLineEdit->setText(Seer::filterEscapes(msg_text)); + return; + } + + if (id_text == QString::number(_spId)) { + spLineEdit->setText(Seer::filterEscapes(msg_text)); + return; + } + + if (id_text == QString::number(_flagsId)) { + flagsLineEdit->setText(Seer::filterEscapes(msg_text)); + return; + } + + }else if (text.startsWith("^error,msg=\"No registers.\"")) { + + // Clear PC, SP, and FLAGS. + pcLineEdit->clear(); + spLineEdit->clear(); + flagsLineEdit->clear(); + + }else{ + // Ignore others. + } +} + void SeerEditorWidgetAssembly::handleSearchLineNumberLineEdit () { QString address = searchLineNumberLineEdit->text(); diff --git a/src/SeerEditorWidgetAssembly.h b/src/SeerEditorWidgetAssembly.h index de2936b..d6fe92e 100644 --- a/src/SeerEditorWidgetAssembly.h +++ b/src/SeerEditorWidgetAssembly.h @@ -297,12 +297,14 @@ class SeerEditorWidgetAssembly : public QWidget, protected Ui::SeerEditorWidgetA public slots: void reloadAssembly (); + void reloadRegisters (); void showSearchBar (bool flag); void setSearchMatchCase (bool flag); void setShowAddressColumn (bool flag); void setShowOffsetColumn (bool flag); void setShowOpcodeColumn (bool flag); void setShowSourceLines (bool flag); + void handleText (const QString& text); private slots: void handleSearchLineNumberLineEdit (); @@ -317,7 +319,12 @@ class SeerEditorWidgetAssembly : public QWidget, protected Ui::SeerEditorWidgetA void handleShowSourceLines (); signals: + void evaluateVariableExpression (int expressionid, QString expression); + private: + int _pcId; + int _spId; + int _flagsId; SeerKeySettings _keySettings; QShortcut* _textSearchShortcut; QShortcut* _textSearchNextShortcut; diff --git a/src/SeerEditorWidgetAssembly.ui b/src/SeerEditorWidgetAssembly.ui index 830d3cd..59d414f 100644 --- a/src/SeerEditorWidgetAssembly.ui +++ b/src/SeerEditorWidgetAssembly.ui @@ -7,7 +7,7 @@ 0 0 833 - 555 + 668 @@ -24,6 +24,88 @@ + + + + + + PC + + + + + + + + 40 + 0 + + + + Program counter + + + true + + + Program counter + + + + + + + FLAGS + + + + + + + + 20 + 0 + + + + Processor flags + + + true + + + Processor flags + + + + + + + SP + + + + + + + + 20 + 0 + + + + Stack pointer + + + true + + + Stack pointer + + + + + diff --git a/src/SeerVariableLoggerBrowserWidget.cpp b/src/SeerVariableLoggerBrowserWidget.cpp index 8496ec9..74900cd 100644 --- a/src/SeerVariableLoggerBrowserWidget.cpp +++ b/src/SeerVariableLoggerBrowserWidget.cpp @@ -20,7 +20,7 @@ SeerVariableLoggerBrowserWidget::SeerVariableLoggerBrowserWidget (QWidget* paren variablesTreeWidget->resizeColumnToContents(1); // timestamp variablesTreeWidget->resizeColumnToContents(2); // name variablesTreeWidget->resizeColumnToContents(3); // value - variablesTreeWidget->setColumnHidden(0, true); // Hide the 'number' column. + variablesTreeWidget->setColumnHidden(0, true); // Hide the 'number' column. variablesTreeWidget->clear(); // Connect things. @@ -47,10 +47,13 @@ void SeerVariableLoggerBrowserWidget::handleText (const QString& text) { QString id_text = text.section('^', 0,0); QString value_text = Seer::parseFirst(text, "value=", '"', '"', false); - QList matches = variablesTreeWidget->findItems(id_text, Qt::MatchExactly, 0); + if (_ids.contains(id_text.toInt()) == true) { - if (matches.size() > 0) { - matches.first()->setText(3, Seer::filterEscapes(value_text)); + QList matches = variablesTreeWidget->findItems(id_text, Qt::MatchExactly, 0); + + if (matches.size() > 0) { + matches.first()->setText(3, Seer::filterEscapes(value_text)); + } } }else if (text.contains(QRegExp("^([0-9]+)\\^error,msg="))) { @@ -62,13 +65,17 @@ void SeerVariableLoggerBrowserWidget::handleText (const QString& text) { QString id_text = text.section('^', 0,0); QString msg_text = Seer::parseFirst(text, "msg=", '"', '"', false); - QList matches = variablesTreeWidget->findItems(id_text, Qt::MatchExactly, 0); + if (_ids.contains(id_text.toInt()) == true) { - if (matches.size() > 0) { - matches.first()->setText(3, Seer::filterEscapes(msg_text)); + QList matches = variablesTreeWidget->findItems(id_text, Qt::MatchExactly, 0); + + if (matches.size() > 0) { + matches.first()->setText(3, Seer::filterEscapes(msg_text)); + } } }else if (text.startsWith("^error,msg=\"No registers.\"")) { + variablesTreeWidget->clear(); }else{ @@ -95,6 +102,10 @@ void SeerVariableLoggerBrowserWidget::handleEvaluateVariableExpression (int expr QString id_text = QString::number(expressionid); + if (_ids.contains(id_text.toInt()) == false) { + return; + } + QList matches = variablesTreeWidget->findItems(id_text, Qt::MatchExactly, 0); // Reuse existing item. @@ -145,6 +156,8 @@ void SeerVariableLoggerBrowserWidget::handleAddLineEdit () { int id = Seer::createID(); + _ids.insert(id); // Keep track of which ones are entered. + emit evaluateVariableExpression(id, variable); } } diff --git a/src/SeerVariableLoggerBrowserWidget.h b/src/SeerVariableLoggerBrowserWidget.h index 81434d2..270d814 100644 --- a/src/SeerVariableLoggerBrowserWidget.h +++ b/src/SeerVariableLoggerBrowserWidget.h @@ -2,6 +2,7 @@ #include #include +#include #include "ui_SeerVariableLoggerBrowserWidget.h" class SeerVariableLoggerBrowserWidget : public QWidget, protected Ui::SeerVariableLoggerBrowserWidgetForm { @@ -28,6 +29,7 @@ class SeerVariableLoggerBrowserWidget : public QWidget, protected Ui::SeerVariab protected: private: + QSet _ids; };