Add basic Pseudocode tab (Fixes #142) (#184)

* Add basic Pseudocode tab (Fixes #142)
* Add missing include to fix Windows build
* PseudocodeWidget: Move refreshPseudocode to slots to silence warning
This commit is contained in:
Thomas (nezza-_-) Roth 2017-12-07 00:19:14 +01:00 committed by xarkes
parent 3f05e55bbe
commit 8bc7213b8c
8 changed files with 188 additions and 5 deletions

View File

@ -99,6 +99,7 @@ MainWindow::MainWindow(QWidget *parent) :
relocsDock(nullptr),
commentsDock(nullptr),
stringsDock(nullptr),
pseudocodeDock(nullptr),
flagsDock(nullptr),
dashboardDock(nullptr),
gotoEntry(nullptr),
@ -191,6 +192,9 @@ void MainWindow::initUI()
hexdumpDock = new HexdumpWidget(tr("Hexdump"), this);
dockWidgets.push_back(hexdumpDock);
pseudocodeDock = new PseudocodeWidget(tr("Pseudocode"), this);
dockWidgets.push_back(pseudocodeDock);
// Add graph view as dockable
graphDock = new QDockWidget(tr("Graph"), this);
graphDock->setObjectName("Graph");
@ -659,6 +663,7 @@ void MainWindow::restoreDocks()
tabifyDockWidget(dashboardDock, disassemblyDock);
tabifyDockWidget(dashboardDock, graphDock);
tabifyDockWidget(dashboardDock, hexdumpDock);
tabifyDockWidget(dashboardDock, pseudocodeDock);
tabifyDockWidget(dashboardDock, entrypointDock);
tabifyDockWidget(dashboardDock, flagsDock);
tabifyDockWidget(dashboardDock, stringsDock);
@ -695,6 +700,7 @@ void MainWindow::showDefaultDocks()
disassemblyDock,
sidebarDock,
hexdumpDock,
pseudocodeDock,
dashboardDock
};

View File

@ -8,6 +8,7 @@
#include "widgets/DisassemblerGraphView.h"
#include "widgets/SidebarWidget.h"
#include "widgets/HexdumpWidget.h"
#include "widgets/PseudocodeWidget.h"
#include "utils/Configuration.h"
#include <QMainWindow>
@ -169,6 +170,7 @@ private:
DisassemblyWidget *disassemblyDock;
SidebarWidget *sidebarDock;
HexdumpWidget *hexdumpDock;
PseudocodeWidget *pseudocodeDock;
QDockWidget *graphDock;
DisassemblerGraphView *graphView;
QDockWidget *asmDock;

View File

@ -721,6 +721,11 @@ RVA CutterCore::getOffsetJump(RVA addr)
return value;
}
QString CutterCore::getDecompiledCode(RVA addr)
{
return cmd("pdc @ " + QString::number(addr));
}
QString CutterCore::getDecompiledCode(QString addr)
{
return cmd("pdc @ " + addr);

View File

@ -225,8 +225,8 @@ public:
RVA prevOpAddr(RVA startAddr, int count);
RVA nextOpAddr(RVA startAddr, int count);
// Disassembly/Graph/Hexdump view priority
enum class MemoryWidgetType { Disassembly, Graph, Hexdump };
// Disassembly/Graph/Hexdump/Pseudocode view priority
enum class MemoryWidgetType { Disassembly, Graph, Hexdump, Pseudocode };
MemoryWidgetType getMemoryWidgetPriority() const { return memoryWidgetPriority; }
void setMemoryWidgetPriority(MemoryWidgetType type) { memoryWidgetPriority = type; }
void triggerRaisePrioritizedMemoryWidget() { emit raisePrioritizedMemoryWidget(memoryWidgetPriority); }
@ -262,6 +262,7 @@ public:
QList<QList<QString>> get_exec_sections();
QString getOffsetInfo(QString addr);
RVA getOffsetJump(RVA addr);
QString getDecompiledCode(RVA addr);
QString getDecompiledCode(QString addr);
QString getFileInfo();
QStringList getStats();

View File

@ -79,7 +79,8 @@ SOURCES += \
utils/Colors.cpp \
dialogs/SaveProjectDialog.cpp \
utils/TempConfig.cpp \
utils/SvgIconEngine.cpp
utils/SvgIconEngine.cpp \
widgets/PseudocodeWidget.cpp
HEADERS += \
cutter.h \
@ -129,7 +130,8 @@ HEADERS += \
utils/Colors.h \
dialogs/SaveProjectDialog.h \
utils/TempConfig.h \
utils/SvgIconEngine.h
utils/SvgIconEngine.h \
widgets/PseudocodeWidget.h
FORMS += \
dialogs/AboutDialog.ui \
@ -159,7 +161,8 @@ FORMS += \
widgets/SymbolsWidget.ui \
widgets/SidebarWidget.ui \
widgets/HexdumpWidget.ui \
dialogs/SaveProjectDialog.ui
dialogs/SaveProjectDialog.ui \
widgets/PseudocodeWidget.ui
RESOURCES += \
resources.qrc

View File

@ -0,0 +1,103 @@
#include "PseudocodeWidget.h"
#include "ui_PseudocodeWidget.h"
#include "utils/Configuration.h"
#include "utils/Helpers.h"
#include "utils/TempConfig.h"
PseudocodeWidget::PseudocodeWidget(QWidget *parent, Qt::WindowFlags flags) :
QDockWidget(parent, flags),
ui(new Ui::PseudocodeWidget)
{
ui->setupUi(this);
setupFonts();
colorsUpdatedSlot();
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
connect(Core(), SIGNAL(commentsChanged()), this, SLOT(refreshPseudocode()));
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(refreshPseudocode()));
connect(Core(), SIGNAL(functionRenamed(QString, QString)), this, SLOT(refreshPseudocode()));
connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshPseudocode()));
connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshPseudocode()));
connect(Core(), &CutterCore::instructionChanged, this, [this](RVA offset) {
refreshPseudocode();
});
connect(Core(), SIGNAL(seekChanged(RVA)), this, SLOT(on_seekChanged(RVA)));
connect(Core(), SIGNAL(raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType)), this, SLOT(raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType)));
connect(this, &QDockWidget::visibilityChanged, this, [](bool visibility) {
if (visibility)
{
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Pseudocode);
}
});
// Get alerted when there's a refresh
connect(Core(), &CutterCore::refreshAll, this, [this]() {
refresh(Core()->getOffset());
});
refresh(Core()->getOffset());
}
PseudocodeWidget::PseudocodeWidget(const QString &title, QWidget *parent, Qt::WindowFlags flags)
: PseudocodeWidget(parent, flags)
{
setWindowTitle(title);
}
PseudocodeWidget::~PseudocodeWidget() {}
void PseudocodeWidget::on_seekChanged(RVA addr)
{
refresh(addr);
}
void PseudocodeWidget::refresh(RVA addr)
{
QString decompiledCode = Core()->getDecompiledCode(addr);
if (decompiledCode.length() == 0)
{
decompiledCode = tr("Cannot decompile at") + " " + RAddressString(addr) + " " + tr("(Not a function?)");
}
ui->pseudocodeTextBrowser->setText(decompiledCode);
}
void PseudocodeWidget::refreshPseudocode()
{
refresh(Core()->getOffset());
}
void PseudocodeWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type)
{
if (type == CutterCore::MemoryWidgetType::Pseudocode)
{
raise();
}
}
void PseudocodeWidget::setupFonts()
{
QFont font = Config()->getFont();
ui->pseudocodeTextBrowser->setFont(font);
}
void PseudocodeWidget::fontsUpdated()
{
setupFonts();
}
void PseudocodeWidget::colorsUpdatedSlot()
{
QString styleSheet = QString("QTextBrowser { background-color: %1; color: %2; }")
.arg(ConfigColor("gui.background").name())
.arg(ConfigColor("btext").name());
ui->pseudocodeTextBrowser->setStyleSheet(styleSheet);
}

View File

@ -0,0 +1,40 @@
#ifndef PSEUDOCODEWIDGET_H
#define PSEUDOCODEWIDGET_H
#include <QDockWidget>
#include <memory>
#include "ui_PseudocodeWidget.h"
#include "cutter.h"
namespace Ui
{
class PseudocodeWidget;
}
class PseudocodeWidget : public QDockWidget
{
Q_OBJECT
public:
explicit PseudocodeWidget(const QString &title, QWidget *parent = nullptr, Qt::WindowFlags flags = 0);
explicit PseudocodeWidget(QWidget *parent = nullptr, Qt::WindowFlags flags = 0);
~PseudocodeWidget();
private:
std::unique_ptr<Ui::PseudocodeWidget> ui;
void refresh(RVA addr);
void setupFonts();
signals:
public slots:
private slots:
void on_seekChanged(RVA addr);
void raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type);
void fontsUpdated();
void colorsUpdatedSlot();
void refreshPseudocode();
};
#endif // PSEUDOCODEWIDGET_H

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PseudocodeWidget</class>
<widget class="QDockWidget" name="PseudocodeWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>686</width>
<height>646</height>
</rect>
</property>
<property name="toolTipDuration">
<number>0</number>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QTextBrowser" name="pseudocodeTextBrowser"/>
</widget>
<resources/>
<connections/>
</ui>