mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-31 16:47:26 +00:00
Added emulation support (#553)
* emulation start button * add emul continue until syscall * reopen file after stopping debug * show debug context menu only when debugging * updated r2 * Attach to running process * fix bps issue in debug and attach mode * renamed signal and added attach icon
This commit is contained in:
parent
975e4c4a3d
commit
342fe77886
143
src/Cutter.cpp
143
src/Cutter.cpp
@ -777,65 +777,137 @@ void CutterCore::startDebug()
|
|||||||
cmd("ood");
|
cmd("ood");
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
if (!currentlyDebugging) {
|
if (!currentlyDebugging) {
|
||||||
|
setConfig("asm.flags", false);
|
||||||
emit changeDebugView();
|
emit changeDebugView();
|
||||||
|
emit flagsChanged();
|
||||||
|
emit refreshCodeViews();
|
||||||
|
currentlyDebugging = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::startEmulation()
|
||||||
|
{
|
||||||
|
if (!currentlyDebugging) {
|
||||||
|
offsetPriorDebugging = getOffset();
|
||||||
|
}
|
||||||
|
// clear registers, init esil state, stack, progcounter at current seek
|
||||||
|
cmd("ar0; aei; aeim; aeip");
|
||||||
|
emit registersChanged();
|
||||||
|
if (!currentlyDebugging || !currentlyEmulating) {
|
||||||
|
// prevent register flags from appearing during debug/emul
|
||||||
|
setConfig("asm.flags", false);
|
||||||
|
// allows to view self-modifying code changes or other binary changes
|
||||||
|
setConfig("io.cache", true);
|
||||||
|
emit changeDebugView();
|
||||||
|
emit flagsChanged();
|
||||||
|
emit refreshCodeViews();
|
||||||
|
currentlyDebugging = true;
|
||||||
|
currentlyEmulating = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::attachDebug(int pid)
|
||||||
|
{
|
||||||
|
if (!currentlyDebugging) {
|
||||||
|
offsetPriorDebugging = getOffset();
|
||||||
|
}
|
||||||
|
// attach to process with dbg plugin
|
||||||
|
cmd("o-*; e cfg.debug = true; o+ dbg://" + QString::number(pid));
|
||||||
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
|
seek(programCounterValue);
|
||||||
|
emit registersChanged();
|
||||||
|
if (!currentlyDebugging || !currentlyEmulating) {
|
||||||
|
// prevent register flags from appearing during debug/emul
|
||||||
|
setConfig("asm.flags", false);
|
||||||
|
emit changeDebugView();
|
||||||
|
emit flagsChanged();
|
||||||
currentlyDebugging = true;
|
currentlyDebugging = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::stopDebug()
|
void CutterCore::stopDebug()
|
||||||
{
|
{
|
||||||
// @TODO should first obtain correct signal to send.
|
|
||||||
// Also, we do a ds since otherwise the process does not die.
|
|
||||||
if (currentlyDebugging) {
|
if (currentlyDebugging) {
|
||||||
cmd("dk 9; ds; e cfg.debug = false; oo");
|
if (currentlyEmulating) {
|
||||||
|
cmd("aeim-; aei-; wcr; .ar-");
|
||||||
|
currentlyEmulating = false;
|
||||||
|
} else {
|
||||||
|
// we do a ds since otherwise the process does not die.
|
||||||
|
cmd("dk 9; ds; oo; .ar-");
|
||||||
|
}
|
||||||
seek(offsetPriorDebugging);
|
seek(offsetPriorDebugging);
|
||||||
emit changeDefinedView();
|
setConfig("asm.flags", true);
|
||||||
|
setConfig("io.cache", false);
|
||||||
currentlyDebugging = false;
|
currentlyDebugging = false;
|
||||||
|
emit changeDefinedView();
|
||||||
|
emit flagsChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::continueDebug()
|
void CutterCore::continueDebug()
|
||||||
{
|
{
|
||||||
cmd("dc");
|
if (currentlyDebugging) {
|
||||||
emit registersChanged();
|
cmd("dc");
|
||||||
|
emit registersChanged();
|
||||||
|
emit refreshCodeViews();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::continueUntilDebug(QString offset)
|
void CutterCore::continueUntilDebug(QString offset)
|
||||||
{
|
{
|
||||||
cmd("dcu " + offset);
|
if (currentlyDebugging) {
|
||||||
emit registersChanged();
|
if (!currentlyEmulating) {
|
||||||
|
cmd("dcu " + offset);
|
||||||
|
} else {
|
||||||
|
cmd("aecu " + offset);
|
||||||
|
}
|
||||||
|
emit registersChanged();
|
||||||
|
emit refreshCodeViews();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::continueUntilCall()
|
void CutterCore::continueUntilCall()
|
||||||
{
|
{
|
||||||
cmd("dcc");
|
if (currentlyDebugging) {
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
cmd("dcc");
|
||||||
seek(programCounterValue);
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
emit registersChanged();
|
seek(programCounterValue);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::continueUntilSyscall()
|
void CutterCore::continueUntilSyscall()
|
||||||
{
|
{
|
||||||
cmd("dcs");
|
if (currentlyDebugging) {
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
if (currentlyEmulating) {
|
||||||
seek(programCounterValue);
|
cmd("aecs");
|
||||||
emit registersChanged();
|
} else {
|
||||||
|
cmd("dcs");
|
||||||
|
}
|
||||||
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
|
seek(programCounterValue);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::stepDebug()
|
void CutterCore::stepDebug()
|
||||||
{
|
{
|
||||||
cmd("ds");
|
if (currentlyDebugging) {
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
cmd("ds");
|
||||||
seek(programCounterValue);
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
emit registersChanged();
|
seek(programCounterValue);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::stepOverDebug()
|
void CutterCore::stepOverDebug()
|
||||||
{
|
{
|
||||||
cmd("dso");
|
if (currentlyDebugging) {
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
cmd("dso");
|
||||||
seek(programCounterValue);
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
emit registersChanged();
|
seek(programCounterValue);
|
||||||
|
emit registersChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CutterCore::getDebugPlugins()
|
QStringList CutterCore::getDebugPlugins()
|
||||||
@ -885,7 +957,7 @@ void CutterCore::delBreakpoint(RVA addr)
|
|||||||
void CutterCore::delAllBreakpoints()
|
void CutterCore::delAllBreakpoints()
|
||||||
{
|
{
|
||||||
cmd("db-*");
|
cmd("db-*");
|
||||||
emit deletedAllBreakpoints();
|
emit refreshCodeViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::enableBreakpoint(RVA addr)
|
void CutterCore::enableBreakpoint(RVA addr)
|
||||||
@ -930,6 +1002,27 @@ QJsonDocument CutterCore::getBacktrace()
|
|||||||
return cmdj("dbtj");
|
return cmdj("dbtj");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<ProcessDescription> CutterCore::getAllProcesses()
|
||||||
|
{
|
||||||
|
QList<ProcessDescription> ret;
|
||||||
|
QJsonArray ProcessArray = cmdj("dplj").array();
|
||||||
|
|
||||||
|
for (QJsonValue value : ProcessArray) {
|
||||||
|
QJsonObject procObject = value.toObject();
|
||||||
|
|
||||||
|
ProcessDescription proc;
|
||||||
|
|
||||||
|
proc.pid = procObject["pid"].toVariant().toInt();
|
||||||
|
proc.uid = procObject["uid"].toVariant().toInt();
|
||||||
|
proc.status = procObject["status"].toString();
|
||||||
|
proc.path = procObject["path"].toString();
|
||||||
|
|
||||||
|
ret << proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
QList<MemoryMapDescription> CutterCore::getMemoryMap()
|
QList<MemoryMapDescription> CutterCore::getMemoryMap()
|
||||||
{
|
{
|
||||||
QList<MemoryMapDescription> ret;
|
QList<MemoryMapDescription> ret;
|
||||||
|
14
src/Cutter.h
14
src/Cutter.h
@ -312,6 +312,13 @@ struct BreakpointDescription {
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ProcessDescription {
|
||||||
|
int pid;
|
||||||
|
int uid;
|
||||||
|
QString status;
|
||||||
|
QString path;
|
||||||
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FunctionDescription)
|
Q_DECLARE_METATYPE(FunctionDescription)
|
||||||
Q_DECLARE_METATYPE(ImportDescription)
|
Q_DECLARE_METATYPE(ImportDescription)
|
||||||
Q_DECLARE_METATYPE(ExportDescription)
|
Q_DECLARE_METATYPE(ExportDescription)
|
||||||
@ -342,6 +349,7 @@ Q_DECLARE_METATYPE(SearchDescription)
|
|||||||
Q_DECLARE_METATYPE(SectionDescription)
|
Q_DECLARE_METATYPE(SectionDescription)
|
||||||
Q_DECLARE_METATYPE(MemoryMapDescription)
|
Q_DECLARE_METATYPE(MemoryMapDescription)
|
||||||
Q_DECLARE_METATYPE(BreakpointDescription)
|
Q_DECLARE_METATYPE(BreakpointDescription)
|
||||||
|
Q_DECLARE_METATYPE(ProcessDescription)
|
||||||
|
|
||||||
class CutterCore: public QObject
|
class CutterCore: public QObject
|
||||||
{
|
{
|
||||||
@ -480,6 +488,8 @@ public:
|
|||||||
QJsonDocument getStack(int size = 0x40);
|
QJsonDocument getStack(int size = 0x40);
|
||||||
QJsonDocument getBacktrace();
|
QJsonDocument getBacktrace();
|
||||||
void startDebug();
|
void startDebug();
|
||||||
|
void startEmulation();
|
||||||
|
void attachDebug(int pid);
|
||||||
void stopDebug();
|
void stopDebug();
|
||||||
void continueDebug();
|
void continueDebug();
|
||||||
void continueUntilCall();
|
void continueUntilCall();
|
||||||
@ -497,6 +507,7 @@ public:
|
|||||||
QStringList getDebugPlugins();
|
QStringList getDebugPlugins();
|
||||||
void setDebugPlugin(QString plugin);
|
void setDebugPlugin(QString plugin);
|
||||||
bool currentlyDebugging = false;
|
bool currentlyDebugging = false;
|
||||||
|
bool currentlyEmulating = false;
|
||||||
|
|
||||||
RVA getOffsetJump(RVA addr);
|
RVA getOffsetJump(RVA addr);
|
||||||
QString getDecompiledCode(RVA addr);
|
QString getDecompiledCode(RVA addr);
|
||||||
@ -554,6 +565,7 @@ public:
|
|||||||
QList<SearchDescription> getAllSearch(QString search_for, QString space);
|
QList<SearchDescription> getAllSearch(QString search_for, QString space);
|
||||||
BlockStatistics getBlockStatistics(unsigned int blocksCount);
|
BlockStatistics getBlockStatistics(unsigned int blocksCount);
|
||||||
QList<BreakpointDescription> getBreakpoints();
|
QList<BreakpointDescription> getBreakpoints();
|
||||||
|
QList<ProcessDescription> getAllProcesses();
|
||||||
|
|
||||||
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
|
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
|
||||||
const QString &filterType = QString::null);
|
const QString &filterType = QString::null);
|
||||||
@ -584,7 +596,7 @@ signals:
|
|||||||
void registersChanged();
|
void registersChanged();
|
||||||
void instructionChanged(RVA offset);
|
void instructionChanged(RVA offset);
|
||||||
void breakpointsChanged();
|
void breakpointsChanged();
|
||||||
void deletedAllBreakpoints();
|
void refreshCodeViews();
|
||||||
|
|
||||||
void notesChanged(const QString ¬es);
|
void notesChanged(const QString ¬es);
|
||||||
void projectSaved(const QString &name);
|
void projectSaved(const QString &name);
|
||||||
|
@ -180,7 +180,8 @@ SOURCES += \
|
|||||||
widgets/MemoryMapWidget.cpp \
|
widgets/MemoryMapWidget.cpp \
|
||||||
dialogs/preferences/DebugOptionsWidget.cpp \
|
dialogs/preferences/DebugOptionsWidget.cpp \
|
||||||
widgets/BreakpointWidget.cpp \
|
widgets/BreakpointWidget.cpp \
|
||||||
dialogs/BreakpointsDialog.cpp
|
dialogs/BreakpointsDialog.cpp \
|
||||||
|
dialogs/AttachProcDialog.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Cutter.h \
|
Cutter.h \
|
||||||
@ -272,7 +273,8 @@ HEADERS += \
|
|||||||
widgets/MemoryMapWidget.h \
|
widgets/MemoryMapWidget.h \
|
||||||
dialogs/preferences/DebugOptionsWidget.h \
|
dialogs/preferences/DebugOptionsWidget.h \
|
||||||
widgets/BreakpointWidget.h \
|
widgets/BreakpointWidget.h \
|
||||||
dialogs/BreakpointsDialog.h
|
dialogs/BreakpointsDialog.h \
|
||||||
|
dialogs/AttachProcDialog.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialogs/AboutDialog.ui \
|
dialogs/AboutDialog.ui \
|
||||||
@ -325,7 +327,8 @@ FORMS += \
|
|||||||
widgets/MemoryMapWidget.ui \
|
widgets/MemoryMapWidget.ui \
|
||||||
dialogs/preferences/DebugOptionsWidget.ui \
|
dialogs/preferences/DebugOptionsWidget.ui \
|
||||||
widgets/BreakpointWidget.ui \
|
widgets/BreakpointWidget.ui \
|
||||||
dialogs/BreakpointsDialog.ui
|
dialogs/BreakpointsDialog.ui \
|
||||||
|
dialogs/AttachProcDialog.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc \
|
resources.qrc \
|
||||||
|
178
src/dialogs/AttachProcDialog.cpp
Normal file
178
src/dialogs/AttachProcDialog.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include "MainWindow.h"
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include "AttachProcDialog.h"
|
||||||
|
#include "ui_AttachProcDialog.h"
|
||||||
|
|
||||||
|
#include "utils/Helpers.h"
|
||||||
|
|
||||||
|
ProcessModel::ProcessModel(QList<ProcessDescription> *processes, QObject *parent)
|
||||||
|
: QAbstractListModel(parent),
|
||||||
|
processes(processes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProcessModel::rowCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return processes->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProcessModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return ProcessModel::ColumnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ProcessModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (index.row() >= processes->count())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
const ProcessDescription &proc = processes->at(index.row());
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case PidColumn:
|
||||||
|
return proc.pid;
|
||||||
|
case UidColumn:
|
||||||
|
return proc.uid;
|
||||||
|
case StatusColumn:
|
||||||
|
return proc.status;
|
||||||
|
case PathColumn:
|
||||||
|
return proc.path;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case ProcDescriptionRole:
|
||||||
|
return QVariant::fromValue(proc);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ProcessModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (section) {
|
||||||
|
case PidColumn:
|
||||||
|
return tr("PID");
|
||||||
|
case UidColumn:
|
||||||
|
return tr("UID");
|
||||||
|
case StatusColumn:
|
||||||
|
return tr("Status");
|
||||||
|
case PathColumn:
|
||||||
|
return tr("Path");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessModel::beginReloadProcess()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessModel::endReloadProcess()
|
||||||
|
{
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessProxyModel::ProcessProxyModel(ProcessModel *sourceModel, QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSourceModel(sourceModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||||
|
ProcessDescription item = index.data(ProcessModel::ProcDescriptionRole).value<ProcessDescription>();
|
||||||
|
return item.path.contains(filterRegExp());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
{
|
||||||
|
ProcessDescription leftProc = left.data(ProcessModel::ProcDescriptionRole).value<ProcessDescription>();
|
||||||
|
ProcessDescription rightProc = right.data(ProcessModel::ProcDescriptionRole).value<ProcessDescription>();
|
||||||
|
|
||||||
|
switch (left.column()) {
|
||||||
|
case ProcessModel::PidColumn:
|
||||||
|
return leftProc.pid < rightProc.pid;
|
||||||
|
case ProcessModel::UidColumn:
|
||||||
|
return leftProc.uid < rightProc.uid;
|
||||||
|
case ProcessModel::StatusColumn:
|
||||||
|
return leftProc.status < rightProc.status;
|
||||||
|
case ProcessModel::PathColumn:
|
||||||
|
return leftProc.path < rightProc.path;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftProc.pid < rightProc.pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
AttachProcDialog::AttachProcDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::AttachProcDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
|
||||||
|
processes = Core()->getAllProcesses();
|
||||||
|
processModel = new ProcessModel(&processes, this);
|
||||||
|
processProxyModel = new ProcessProxyModel(processModel, this);
|
||||||
|
ui->procTreeView->setModel(processProxyModel);
|
||||||
|
ui->procTreeView->sortByColumn(ProcessModel::PidColumn, Qt::AscendingOrder);
|
||||||
|
connect(ui->filterLineEdit, SIGNAL(textChanged(const QString &)), processProxyModel,
|
||||||
|
SLOT(setFilterWildcard(const QString &)));
|
||||||
|
qhelpers::setVerticalScrollMode(ui->procTreeView);
|
||||||
|
|
||||||
|
// focus on filter line
|
||||||
|
ui->filterLineEdit->setFocus();
|
||||||
|
// Event filter for capturing Ctrl/Cmd+Return
|
||||||
|
ui->filterLineEdit->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
AttachProcDialog::~AttachProcDialog() {}
|
||||||
|
|
||||||
|
void AttachProcDialog::on_buttonBox_accepted()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachProcDialog::on_buttonBox_rejected()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AttachProcDialog::getPID()
|
||||||
|
{
|
||||||
|
ProcessDescription proc = ui->procTreeView->selectionModel()->currentIndex().data(
|
||||||
|
ProcessModel::ProcDescriptionRole).value<ProcessDescription>();
|
||||||
|
return proc.pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AttachProcDialog::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(obj);
|
||||||
|
if (event -> type() == QEvent::KeyPress) {
|
||||||
|
QKeyEvent *keyEvent = static_cast <QKeyEvent *> (event);
|
||||||
|
|
||||||
|
// Confirm comment by pressing Ctrl/Cmd+Return
|
||||||
|
if ((keyEvent -> modifiers() & Qt::ControlModifier) &&
|
||||||
|
((keyEvent -> key() == Qt::Key_Enter) || (keyEvent -> key() == Qt::Key_Return))) {
|
||||||
|
this->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachProcDialog::on_procTreeView_doubleClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
ProcessDescription proc = index.data(ProcessModel::ProcDescriptionRole).value<ProcessDescription>();
|
||||||
|
accept();
|
||||||
|
}
|
82
src/dialogs/AttachProcDialog.h
Normal file
82
src/dialogs/AttachProcDialog.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include <QDialog>
|
||||||
|
#include <memory>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class AttachProcDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidget;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessModel: public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<ProcessDescription> *processes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Column { PidColumn = 0, UidColumn, StatusColumn, PathColumn, ColumnCount };
|
||||||
|
enum Role { ProcDescriptionRole = Qt::UserRole };
|
||||||
|
|
||||||
|
ProcessModel(QList<ProcessDescription> *processes, QObject *parent = 0);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
void beginReloadProcess();
|
||||||
|
void endReloadProcess();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProcessProxyModel(ProcessModel *sourceModel, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int row, const QModelIndex &parent) const override;
|
||||||
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AttachProcDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AttachProcDialog(QWidget *parent = nullptr);
|
||||||
|
~AttachProcDialog();
|
||||||
|
|
||||||
|
int getPID();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
void on_buttonBox_rejected();
|
||||||
|
void on_procTreeView_doubleClicked(const QModelIndex &index);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void attachProcess(int pid);
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::AttachProcDialog> ui;
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
|
||||||
|
ProcessModel *processModel;
|
||||||
|
ProcessProxyModel *processProxyModel;
|
||||||
|
QList<ProcessDescription> processes;
|
||||||
|
|
||||||
|
};
|
116
src/dialogs/AttachProcDialog.ui
Normal file
116
src/dialogs/AttachProcDialog.ui
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>AttachProcDialog</class>
|
||||||
|
<widget class="QDialog" name="AttachProcDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>600</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Select process to attach...</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="procTreeView">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QTreeView::item
|
||||||
|
{
|
||||||
|
padding-top: 1px;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="indentation">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="filterLineEdit">
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Quick Filter</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>AttachProcDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>AttachProcDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
5
src/img/icons/play_light_attach.svg
Normal file
5
src/img/icons/play_light_attach.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||||
|
<svg style="enable-background:new 0 0 24 32" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="32px" width="24px" version="1.1" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 32">
|
||||||
|
<polygon points="0 0 24 16 0 32" fill="#aaacaf"/>
|
||||||
|
<text x="15" y="10" font-family="Helvetica, Arial, sans-serif" font-size="13" stroke-width="2" stroke="#aaacaf" fill="#aaacaf" >A</text>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 521 B |
5
src/img/icons/play_light_debug.svg
Normal file
5
src/img/icons/play_light_debug.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||||
|
<svg style="enable-background:new 0 0 24 32" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="32px" width="24px" version="1.1" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 32">
|
||||||
|
<polygon points="0 0 24 16 0 32" fill="#aaacaf"/>
|
||||||
|
<text x="15" y="10" font-family="Helvetica, Arial, sans-serif" font-size="13" stroke-width="2" stroke="#aaacaf" fill="#aaacaf" >D</text>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 521 B |
5
src/img/icons/play_light_emul.svg
Normal file
5
src/img/icons/play_light_emul.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||||
|
<svg style="enable-background:new 0 0 24 32" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="32px" width="24px" version="1.1" y="0px" x="0px" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 32">
|
||||||
|
<polygon points="0 0 24 16 0 32" fill="#aaacaf"/>
|
||||||
|
<text x="15" y="10" font-family="Helvetica, Arial, sans-serif" font-size="13" stroke-width="2" stroke="#aaacaf" fill="#aaacaf" >E</text>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 521 B |
@ -237,10 +237,12 @@ void DisassemblyContextMenu::aboutToShowSlot()
|
|||||||
// decide to show Reverse jmp option
|
// decide to show Reverse jmp option
|
||||||
showReverseJmpQuery();
|
showReverseJmpQuery();
|
||||||
|
|
||||||
// show debug options
|
// only show debug options if we are currently debugging
|
||||||
// @TODO determine if we are being debugged and only show the menu in those cases
|
debugMenuAction->setVisible(Core()->currentlyDebugging);
|
||||||
// maybe using dpt command
|
// currently there are is no breakpoint support in ESIL so
|
||||||
debugMenuAction->setVisible(true);
|
// we dont show the option in case we are emulating
|
||||||
|
actionAddBreakpoint.setVisible(!Core()->currentlyEmulating);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence DisassemblyContextMenu::getCopySequence() const
|
QKeySequence DisassemblyContextMenu::getCopySequence() const
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
<file>img/icons/spin.svg</file>
|
<file>img/icons/spin.svg</file>
|
||||||
<file>img/icons/plus.svg</file>
|
<file>img/icons/plus.svg</file>
|
||||||
<file>img/icons/play.svg</file>
|
<file>img/icons/play.svg</file>
|
||||||
<file>img/icons/play_light.svg</file>
|
<file>img/icons/play_light_debug.svg</file>
|
||||||
|
<file>img/icons/play_light_emul.svg</file>
|
||||||
|
<file>img/icons/play_light_attach.svg</file>
|
||||||
<file>img/icons/media-stop_light.svg</file>
|
<file>img/icons/media-stop_light.svg</file>
|
||||||
<file>img/icons/media-skip-forward_light.svg</file>
|
<file>img/icons/media-skip-forward_light.svg</file>
|
||||||
<file>img/icons/continue_until_main.svg</file>
|
<file>img/icons/continue_until_main.svg</file>
|
||||||
|
@ -136,7 +136,7 @@ BreakpointWidget::BreakpointWidget(MainWindow *main, QAction *action) :
|
|||||||
connect(actionToggleBreakpoint, &QAction::triggered, this, &BreakpointWidget::toggleBreakpoint);
|
connect(actionToggleBreakpoint, &QAction::triggered, this, &BreakpointWidget::toggleBreakpoint);
|
||||||
connect(Core(), &CutterCore::refreshAll, this, &BreakpointWidget::refreshBreakpoint);
|
connect(Core(), &CutterCore::refreshAll, this, &BreakpointWidget::refreshBreakpoint);
|
||||||
connect(Core(), &CutterCore::breakpointsChanged, this, &BreakpointWidget::refreshBreakpoint);
|
connect(Core(), &CutterCore::breakpointsChanged, this, &BreakpointWidget::refreshBreakpoint);
|
||||||
connect(Core(), &CutterCore::deletedAllBreakpoints, this, &BreakpointWidget::refreshBreakpoint);
|
connect(Core(), &CutterCore::refreshCodeViews, this, &BreakpointWidget::refreshBreakpoint);
|
||||||
connect(ui->addBreakpoint, &QAbstractButton::clicked, this, &BreakpointWidget::addBreakpointDialog);
|
connect(ui->addBreakpoint, &QAbstractButton::clicked, this, &BreakpointWidget::addBreakpointDialog);
|
||||||
connect(ui->delBreakpoint, &QAbstractButton::clicked, this, &BreakpointWidget::delBreakpoint);
|
connect(ui->delBreakpoint, &QAbstractButton::clicked, this, &BreakpointWidget::delBreakpoint);
|
||||||
connect(ui->delAllBreakpoints, &QAbstractButton::clicked, Core(), &CutterCore::delAllBreakpoints);
|
connect(ui->delAllBreakpoints, &QAbstractButton::clicked, Core(), &CutterCore::delAllBreakpoints);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "DebugToolbar.h"
|
#include "DebugToolbar.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
#include "dialogs/AttachProcDialog.cpp"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
@ -11,7 +12,9 @@ DebugToolbar::DebugToolbar(MainWindow *main, QWidget *parent) :
|
|||||||
main(main)
|
main(main)
|
||||||
{
|
{
|
||||||
setObjectName("debugToolbar");
|
setObjectName("debugToolbar");
|
||||||
QIcon startIcon = QIcon(":/img/icons/play_light.svg");
|
QIcon startDebugIcon = QIcon(":/img/icons/play_light_debug.svg");
|
||||||
|
QIcon startEmulIcon = QIcon(":/img/icons/play_light_emul.svg");
|
||||||
|
QIcon startAttachIcon = QIcon(":/img/icons/play_light_attach.svg");
|
||||||
QIcon stopIcon = QIcon(":/img/icons/media-stop_light.svg");
|
QIcon stopIcon = QIcon(":/img/icons/media-stop_light.svg");
|
||||||
QIcon continueIcon = QIcon(":/img/icons/media-skip-forward_light.svg");
|
QIcon continueIcon = QIcon(":/img/icons/media-skip-forward_light.svg");
|
||||||
QIcon continueUntilMainIcon = QIcon(":/img/icons/continue_until_main.svg");
|
QIcon continueUntilMainIcon = QIcon(":/img/icons/continue_until_main.svg");
|
||||||
@ -20,7 +23,9 @@ DebugToolbar::DebugToolbar(MainWindow *main, QWidget *parent) :
|
|||||||
QIcon stepIcon = QIcon(":/img/icons/step_light.svg");
|
QIcon stepIcon = QIcon(":/img/icons/step_light.svg");
|
||||||
QIcon stepOverIcon = QIcon(":/img/icons/step_over_light.svg");
|
QIcon stepOverIcon = QIcon(":/img/icons/step_over_light.svg");
|
||||||
|
|
||||||
QAction *actionStart = new QAction(startIcon, tr("Start debug"), parent);
|
actionStart = new QAction(startDebugIcon, tr("Start debug"), parent);
|
||||||
|
actionStartEmul = new QAction(startEmulIcon, tr("Start emulation"), parent);
|
||||||
|
QAction *actionAttach = new QAction(startAttachIcon, tr("Attach to process"), parent);
|
||||||
QAction *actionStop = new QAction(stopIcon, tr("Stop debug"), parent);
|
QAction *actionStop = new QAction(stopIcon, tr("Stop debug"), parent);
|
||||||
QAction *actionContinue = new QAction(continueIcon, tr("Continue"), parent);
|
QAction *actionContinue = new QAction(continueIcon, tr("Continue"), parent);
|
||||||
QAction *actionContinueUntilMain = new QAction(continueUntilMainIcon, tr("Continue until main"), parent);
|
QAction *actionContinueUntilMain = new QAction(continueUntilMainIcon, tr("Continue until main"), parent);
|
||||||
@ -29,10 +34,19 @@ DebugToolbar::DebugToolbar(MainWindow *main, QWidget *parent) :
|
|||||||
QAction *actionStep = new QAction(stepIcon, tr("Step"), parent);
|
QAction *actionStep = new QAction(stepIcon, tr("Step"), parent);
|
||||||
QAction *actionStepOver = new QAction(stepOverIcon, tr("Step over"), parent);
|
QAction *actionStepOver = new QAction(stepOverIcon, tr("Step over"), parent);
|
||||||
|
|
||||||
|
QToolButton *startButton = new QToolButton;
|
||||||
|
startButton->setPopupMode(QToolButton::MenuButtonPopup);
|
||||||
|
connect(startButton, &QToolButton::triggered, startButton, &QToolButton::setDefaultAction);
|
||||||
|
QMenu *startMenu = new QMenu;
|
||||||
|
startMenu->addAction(actionStart);
|
||||||
|
startMenu->addAction(actionStartEmul);
|
||||||
|
startMenu->addAction(actionAttach);
|
||||||
|
startButton->setDefaultAction(actionStart);
|
||||||
|
startButton->setMenu(startMenu);
|
||||||
|
|
||||||
QToolButton *continueUntilButton = new QToolButton;
|
QToolButton *continueUntilButton = new QToolButton;
|
||||||
continueUntilButton->setPopupMode(QToolButton::MenuButtonPopup);
|
continueUntilButton->setPopupMode(QToolButton::MenuButtonPopup);
|
||||||
connect(continueUntilButton, &QToolButton::triggered, continueUntilButton, &QToolButton::setDefaultAction);
|
connect(continueUntilButton, &QToolButton::triggered, continueUntilButton, &QToolButton::setDefaultAction);
|
||||||
|
|
||||||
QMenu *continueUntilMenu = new QMenu;
|
QMenu *continueUntilMenu = new QMenu;
|
||||||
continueUntilMenu->addAction(actionContinueUntilMain);
|
continueUntilMenu->addAction(actionContinueUntilMain);
|
||||||
continueUntilMenu->addAction(actionContinueUntilCall);
|
continueUntilMenu->addAction(actionContinueUntilCall);
|
||||||
@ -40,7 +54,7 @@ DebugToolbar::DebugToolbar(MainWindow *main, QWidget *parent) :
|
|||||||
continueUntilButton->setMenu(continueUntilMenu);
|
continueUntilButton->setMenu(continueUntilMenu);
|
||||||
continueUntilButton->setDefaultAction(actionContinueUntilMain);
|
continueUntilButton->setDefaultAction(actionContinueUntilMain);
|
||||||
|
|
||||||
addAction(actionStart);
|
addWidget(startButton);
|
||||||
addAction(actionStop);
|
addAction(actionStop);
|
||||||
addAction(actionContinue);
|
addAction(actionContinue);
|
||||||
addWidget(continueUntilButton);
|
addWidget(continueUntilButton);
|
||||||
@ -48,10 +62,33 @@ DebugToolbar::DebugToolbar(MainWindow *main, QWidget *parent) :
|
|||||||
addAction(actionStepOver);
|
addAction(actionStepOver);
|
||||||
|
|
||||||
connect(actionStop, &QAction::triggered, Core(), &CutterCore::stopDebug);
|
connect(actionStop, &QAction::triggered, Core(), &CutterCore::stopDebug);
|
||||||
connect(actionStop, &QAction::triggered, [=](){ this->colorToolbar(false); });
|
connect(actionStop, &QAction::triggered, [=](){
|
||||||
|
actionContinue->setVisible(true);
|
||||||
|
actionStart->setVisible(true);
|
||||||
|
actionStartEmul->setVisible(true);
|
||||||
|
actionAttach->setVisible(true);
|
||||||
|
actionContinueUntilMain->setVisible(true);
|
||||||
|
actionContinueUntilCall->setVisible(true);
|
||||||
|
this->colorToolbar(false);
|
||||||
|
});
|
||||||
connect(actionStep, &QAction::triggered, Core(), &CutterCore::stepDebug);
|
connect(actionStep, &QAction::triggered, Core(), &CutterCore::stepDebug);
|
||||||
connect(actionStart, &QAction::triggered, Core(), &CutterCore::startDebug);
|
connect(actionStart, &QAction::triggered, Core(), &CutterCore::startDebug);
|
||||||
connect(actionStart, &QAction::triggered, [=](){ this->colorToolbar(true); });
|
connect(actionStart, &QAction::triggered, [=](){
|
||||||
|
this->colorToolbar(true);
|
||||||
|
actionAttach->setVisible(false);
|
||||||
|
actionStartEmul->setVisible(false);
|
||||||
|
});
|
||||||
|
connect(actionAttach, &QAction::triggered, this, &DebugToolbar::attachProcessDialog);
|
||||||
|
connect(actionStartEmul, &QAction::triggered, Core(), &CutterCore::startEmulation);
|
||||||
|
connect(actionStartEmul, &QAction::triggered, [=](){
|
||||||
|
actionContinue->setVisible(false);
|
||||||
|
actionStart->setVisible(false);
|
||||||
|
actionAttach->setVisible(false);
|
||||||
|
actionContinueUntilMain->setVisible(false);
|
||||||
|
actionContinueUntilCall->setVisible(false);
|
||||||
|
continueUntilButton->setDefaultAction(actionContinueUntilSyscall);
|
||||||
|
this->colorToolbar(true);
|
||||||
|
});
|
||||||
connect(actionStepOver, &QAction::triggered, Core(), &CutterCore::stepOverDebug);
|
connect(actionStepOver, &QAction::triggered, Core(), &CutterCore::stepOverDebug);
|
||||||
connect(actionContinue, &QAction::triggered, Core(), &CutterCore::continueDebug);
|
connect(actionContinue, &QAction::triggered, Core(), &CutterCore::continueDebug);
|
||||||
connect(actionContinueUntilMain, &QAction::triggered, this, &DebugToolbar::continueUntilMain);
|
connect(actionContinueUntilMain, &QAction::triggered, this, &DebugToolbar::continueUntilMain);
|
||||||
@ -72,3 +109,23 @@ void DebugToolbar::colorToolbar(bool p)
|
|||||||
this->setStyleSheet("");
|
this->setStyleSheet("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugToolbar::attachProcessDialog()
|
||||||
|
{
|
||||||
|
AttachProcDialog *dialog = new AttachProcDialog(this);
|
||||||
|
|
||||||
|
if (dialog->exec()) {
|
||||||
|
int pid = dialog->getPID();
|
||||||
|
attachProcess(pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugToolbar::attachProcess(int pid)
|
||||||
|
{
|
||||||
|
// hide unwanted buttons
|
||||||
|
this->colorToolbar(true);
|
||||||
|
this->actionStart->setVisible(false);
|
||||||
|
this->actionStartEmul->setVisible(false);
|
||||||
|
// attach
|
||||||
|
Core()->attachDebug(pid);
|
||||||
|
}
|
@ -14,9 +14,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
MainWindow *main;
|
MainWindow *main;
|
||||||
|
QAction *actionStart;
|
||||||
|
QAction *actionStartEmul;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void continueUntilMain();
|
void continueUntilMain();
|
||||||
void colorToolbar(bool p);
|
void colorToolbar(bool p);
|
||||||
|
void attachProcessDialog();
|
||||||
|
void attachProcess(int pid);
|
||||||
};
|
};
|
@ -36,7 +36,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
|
|||||||
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(refreshView()));
|
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(refreshView()));
|
||||||
connect(Core(), SIGNAL(graphOptionsChanged()), this, SLOT(refreshView()));
|
connect(Core(), SIGNAL(graphOptionsChanged()), this, SLOT(refreshView()));
|
||||||
connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshView()));
|
connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshView()));
|
||||||
connect(Core(), SIGNAL(deletedAllBreakpoints()), this, SLOT(refreshView()));
|
connect(Core(), SIGNAL(refreshCodeViews()), this, SLOT(refreshView()));
|
||||||
|
|
||||||
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
||||||
|
@ -119,7 +119,7 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
|||||||
refreshDisasm();
|
refreshDisasm();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(Core(), SIGNAL(deletedAllBreakpoints()), this, SLOT(refreshDisasm()));
|
connect(Core(), SIGNAL(refreshCodeViews()), this, SLOT(refreshDisasm()));
|
||||||
|
|
||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
||||||
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
||||||
|
Loading…
Reference in New Issue
Block a user