From c869a34d99228e2aa334f5f4f7beddf3c65e0278 Mon Sep 17 00:00:00 2001 From: mandlebro Date: Wed, 25 Jul 2018 00:15:38 +0100 Subject: [PATCH] Added seeking, editing and colors to stack widget --- src/Cutter.cpp | 8 +++++ src/Cutter.h | 2 ++ src/widgets/StackWidget.cpp | 71 ++++++++++++++++++++++++++++++++++++- src/widgets/StackWidget.h | 6 ++++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/Cutter.cpp b/src/Cutter.cpp index d4353426..8dec4956 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -397,6 +397,12 @@ void CutterCore::editBytes(RVA addr, const QString &bytes) emit instructionChanged(addr); } +void CutterCore::editBytesEndian(RVA addr, const QString &bytes) +{ + cmd("wv " + bytes + " @ " + RAddressString(addr)); + emit stackChanged(); +} + void CutterCore::setComment(RVA addr, const QString &cmt) { cmd("CCu base64:" + cmt.toLocal8Bit().toBase64() + " @ " + QString::number(addr)); @@ -806,6 +812,7 @@ void CutterCore::startDebug() emit flagsChanged(); emit refreshCodeViews(); } + emit stackChanged(); } void CutterCore::startEmulation() @@ -826,6 +833,7 @@ void CutterCore::startEmulation() emit changeDebugView(); emit flagsChanged(); } + emit stackChanged(); emit refreshCodeViews(); } diff --git a/src/Cutter.h b/src/Cutter.h index dc950468..28a175d8 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -410,6 +410,7 @@ public: void nopInstruction(RVA addr); void jmpReverse(RVA addr); void editBytes(RVA addr, const QString &inst); + void editBytesEndian(RVA addr, const QString &bytes); /* Comments */ void setComment(RVA addr, const QString &cmt); @@ -605,6 +606,7 @@ signals: void instructionChanged(RVA offset); void breakpointsChanged(); void refreshCodeViews(); + void stackChanged(); void notesChanged(const QString ¬es); void projectSaved(const QString &name); diff --git a/src/widgets/StackWidget.cpp b/src/widgets/StackWidget.cpp index 2d7279d9..d7ef3927 100644 --- a/src/widgets/StackWidget.cpp +++ b/src/widgets/StackWidget.cpp @@ -2,9 +2,11 @@ #include "ui_StackWidget.h" #include "utils/JsonModel.h" #include "utils/Helpers.h" +#include "dialogs/EditInstructionDialog.h" #include "MainWindow.h" #include "QHeaderView" +#include "QMenu" StackWidget::StackWidget(MainWindow *main, QAction *action) : CutterDockWidget(main, action), @@ -23,9 +25,19 @@ StackWidget::StackWidget(MainWindow *main, QAction *action) : viewStack->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); ui->verticalLayout->addWidget(viewStack); + seekAction = new QAction(tr("Seek to this offset")); + editAction = new QAction(tr("Edit stack value...")); + viewStack->setContextMenuPolicy(Qt::CustomContextMenu); + connect(Core(), &CutterCore::refreshAll, this, &StackWidget::updateContents); connect(Core(), &CutterCore::seekChanged, this, &StackWidget::updateContents); + connect(Core(), &CutterCore::stackChanged, this, &StackWidget::updateContents); connect(Config(), &Configuration::fontsUpdated, this, &StackWidget::fontsUpdatedSlot); + connect(viewStack, SIGNAL(doubleClicked(const QModelIndex &)), this, + SLOT(onDoubleClicked(const QModelIndex &))); + connect(viewStack, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); + connect(seekAction, &QAction::triggered, this, &StackWidget::seekOffset); + connect(editAction, &QAction::triggered, this, &StackWidget::editStack); } StackWidget::~StackWidget() {} @@ -44,14 +56,27 @@ void StackWidget::setStackGrid() QString addr = RAddressString(stackItem["addr"].toVariant().toULongLong()); QString valueStack = RAddressString(stackItem["value"].toVariant().toULongLong()); QStandardItem *rowOffset = new QStandardItem(addr); + rowOffset->setEditable(false); QStandardItem *rowValue = new QStandardItem(valueStack); modelStack->setItem(i, 0, rowOffset); modelStack->setItem(i, 1, rowValue); QJsonValue refObject = stackItem["ref"]; if (!refObject.isUndefined()) { // check that the key exists QString ref = refObject.toString(); + if (ref.contains("ascii") && ref.count("-->") == 1) { + ref = Core()->cmd("psz @ [" + addr + "]"); + } QStandardItem *rowRef = new QStandardItem(ref); modelStack->setItem(i, 2, rowRef); + if (refObject.toString().contains("ascii") && refObject.toString().count("-->") == 1) { + modelStack->setData(modelStack->index(i, 2, QModelIndex()), QVariant(QColor(243, 156, 17)), Qt::ForegroundRole); // orange + } else if (ref.contains("program R X") && ref.count("-->") == 0) { + modelStack->setData(modelStack->index(i, 2, QModelIndex()), QVariant(QColor(Qt::red)), Qt::ForegroundRole); + } else if (ref.contains("stack") && ref.count("-->") == 0) { + modelStack->setData(modelStack->index(i, 2, QModelIndex()), QVariant(QColor(Qt::cyan)), Qt::ForegroundRole); + } else if (ref.contains("library") && ref.count("-->") == 0) { + modelStack->setData(modelStack->index(i, 2, QModelIndex()), QVariant(QColor(Qt::green)), Qt::ForegroundRole); + } } i++; } @@ -62,4 +87,48 @@ void StackWidget::setStackGrid() void StackWidget::fontsUpdatedSlot() { viewStack->setFont(Config()->getFont()); -} \ No newline at end of file +} + +void StackWidget::onDoubleClicked(const QModelIndex &index) +{ + if (!index.isValid()) + return; + // check if we are clicking on the offset or value columns and seek if it is the case + if (index.column() <= 1) { + QString item = index.data().toString(); + Core()->seek(item); + } +} + +void StackWidget::customMenuRequested(QPoint pos) +{ + QMenu *menu = new QMenu(this); + menu->addAction(seekAction); + menu->addAction(editAction); + menu->popup(viewStack->viewport()->mapToGlobal(pos)); +} + +void StackWidget::seekOffset() +{ + QString offset = viewStack->selectionModel()->currentIndex().data().toString(); + Core()->seek(offset); +} + +void StackWidget::editStack() +{ + bool ok; + int row = viewStack->selectionModel()->currentIndex().row(); + QString offset = viewStack->selectionModel()->currentIndex().sibling(row, 0).data().toString(); + EditInstructionDialog *e = new EditInstructionDialog(this); + e->setWindowTitle(tr("Edit stack at %1").arg(offset)); + + QString oldBytes = viewStack->selectionModel()->currentIndex().sibling(row, 1).data().toString(); + e->setInstruction(oldBytes); + + if (e->exec()) { + QString bytes = e->getInstruction(); + if (bytes != oldBytes) { + Core()->editBytesEndian((RVA)offset.toULongLong(&ok, 16), bytes); + } + } +} diff --git a/src/widgets/StackWidget.h b/src/widgets/StackWidget.h index d712cf7f..9ec2a48e 100644 --- a/src/widgets/StackWidget.h +++ b/src/widgets/StackWidget.h @@ -26,9 +26,15 @@ private slots: void updateContents(); void setStackGrid(); void fontsUpdatedSlot(); + void onDoubleClicked(const QModelIndex &index); + void customMenuRequested(QPoint pos); + void seekOffset(); + void editStack(); private: std::unique_ptr ui; QTableView *viewStack = new QTableView; QStandardItemModel *modelStack = new QStandardItemModel(1, 3, this); + QAction *seekAction; + QAction *editAction; }; \ No newline at end of file