mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 03:16:10 +00:00
gdbserver and windbg remote debugging support (#1874)
* Added remote debugging
This commit is contained in:
parent
c85e1db3b3
commit
49d58b3624
@ -267,6 +267,7 @@ SOURCES += \
|
|||||||
dialogs/EditInstructionDialog.cpp \
|
dialogs/EditInstructionDialog.cpp \
|
||||||
dialogs/FlagDialog.cpp \
|
dialogs/FlagDialog.cpp \
|
||||||
dialogs/RenameDialog.cpp \
|
dialogs/RenameDialog.cpp \
|
||||||
|
dialogs/RemoteDebugDialog.cpp \
|
||||||
dialogs/XrefsDialog.cpp \
|
dialogs/XrefsDialog.cpp \
|
||||||
core/MainWindow.cpp \
|
core/MainWindow.cpp \
|
||||||
common/Helpers.cpp \
|
common/Helpers.cpp \
|
||||||
@ -335,6 +336,7 @@ SOURCES += \
|
|||||||
common/CommandTask.cpp \
|
common/CommandTask.cpp \
|
||||||
common/ProgressIndicator.cpp \
|
common/ProgressIndicator.cpp \
|
||||||
common/R2Task.cpp \
|
common/R2Task.cpp \
|
||||||
|
dialogs/R2TaskDialog.cpp \
|
||||||
widgets/DebugActions.cpp \
|
widgets/DebugActions.cpp \
|
||||||
widgets/MemoryMapWidget.cpp \
|
widgets/MemoryMapWidget.cpp \
|
||||||
dialogs/preferences/DebugOptionsWidget.cpp \
|
dialogs/preferences/DebugOptionsWidget.cpp \
|
||||||
@ -398,6 +400,7 @@ HEADERS += \
|
|||||||
dialogs/EditInstructionDialog.h \
|
dialogs/EditInstructionDialog.h \
|
||||||
dialogs/FlagDialog.h \
|
dialogs/FlagDialog.h \
|
||||||
dialogs/RenameDialog.h \
|
dialogs/RenameDialog.h \
|
||||||
|
dialogs/RemoteDebugDialog.h \
|
||||||
dialogs/XrefsDialog.h \
|
dialogs/XrefsDialog.h \
|
||||||
common/Helpers.h \
|
common/Helpers.h \
|
||||||
common/HexAsciiHighlighter.h \
|
common/HexAsciiHighlighter.h \
|
||||||
@ -469,6 +472,7 @@ HEADERS += \
|
|||||||
common/ProgressIndicator.h \
|
common/ProgressIndicator.h \
|
||||||
plugins/CutterPlugin.h \
|
plugins/CutterPlugin.h \
|
||||||
common/R2Task.h \
|
common/R2Task.h \
|
||||||
|
dialogs/R2TaskDialog.h \
|
||||||
widgets/DebugActions.h \
|
widgets/DebugActions.h \
|
||||||
widgets/MemoryMapWidget.h \
|
widgets/MemoryMapWidget.h \
|
||||||
dialogs/preferences/DebugOptionsWidget.h \
|
dialogs/preferences/DebugOptionsWidget.h \
|
||||||
@ -527,6 +531,7 @@ FORMS += \
|
|||||||
dialogs/EditInstructionDialog.ui \
|
dialogs/EditInstructionDialog.ui \
|
||||||
dialogs/FlagDialog.ui \
|
dialogs/FlagDialog.ui \
|
||||||
dialogs/RenameDialog.ui \
|
dialogs/RenameDialog.ui \
|
||||||
|
dialogs/RemoteDebugDialog.ui \
|
||||||
dialogs/XrefsDialog.ui \
|
dialogs/XrefsDialog.ui \
|
||||||
dialogs/NewfileDialog.ui \
|
dialogs/NewfileDialog.ui \
|
||||||
dialogs/InitialOptionsDialog.ui \
|
dialogs/InitialOptionsDialog.ui \
|
||||||
@ -552,6 +557,7 @@ FORMS += \
|
|||||||
dialogs/VersionInfoDialog.ui \
|
dialogs/VersionInfoDialog.ui \
|
||||||
widgets/ZignaturesWidget.ui \
|
widgets/ZignaturesWidget.ui \
|
||||||
dialogs/AsyncTaskDialog.ui \
|
dialogs/AsyncTaskDialog.ui \
|
||||||
|
dialogs/R2TaskDialog.ui \
|
||||||
widgets/StackWidget.ui \
|
widgets/StackWidget.ui \
|
||||||
widgets/RegistersWidget.ui \
|
widgets/RegistersWidget.ui \
|
||||||
widgets/ThreadsWidget.ui \
|
widgets/ThreadsWidget.ui \
|
||||||
|
@ -15,6 +15,8 @@ private:
|
|||||||
void taskFinished();
|
void taskFinished();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Ptr = QSharedPointer<R2Task>;
|
||||||
|
|
||||||
explicit R2Task(const QString &cmd, bool transient = true);
|
explicit R2Task(const QString &cmd, bool transient = true);
|
||||||
~R2Task();
|
~R2Task();
|
||||||
|
|
||||||
@ -30,4 +32,4 @@ signals:
|
|||||||
void finished();
|
void finished();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // R2TASK_H
|
#endif // R2TASK_H
|
||||||
|
@ -1228,6 +1228,59 @@ void CutterCore::startEmulation()
|
|||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CutterCore::attachRemote(const QString &uri)
|
||||||
|
{
|
||||||
|
if (!currentlyDebugging) {
|
||||||
|
offsetPriorDebugging = getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect to a debugger with the given plugin
|
||||||
|
asyncCmd("o-*; e cfg.debug = true; o+ " + uri, debugTask);
|
||||||
|
emit debugTaskStateChanged();
|
||||||
|
|
||||||
|
connect(debugTask.data(), &R2Task::finished, this, [this, uri] () {
|
||||||
|
if (debugTaskDialog) {
|
||||||
|
delete debugTaskDialog;
|
||||||
|
}
|
||||||
|
debugTask.clear();
|
||||||
|
// Check if we actually connected
|
||||||
|
bool connected = false;
|
||||||
|
QJsonArray openFilesArray = getOpenedFiles();
|
||||||
|
for (QJsonValue value : openFilesArray) {
|
||||||
|
QJsonObject openFile = value.toObject();
|
||||||
|
QString fileUri= openFile["uri"].toString();
|
||||||
|
if (!fileUri.compare(uri)) {
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
|
seekAndShow(programCounterValue);
|
||||||
|
if (!connected) {
|
||||||
|
emit attachedRemote(false);
|
||||||
|
emit debugTaskStateChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit registersChanged();
|
||||||
|
if (!currentlyDebugging || !currentlyEmulating) {
|
||||||
|
// prevent register flags from appearing during debug/emul
|
||||||
|
setConfig("asm.flags", false);
|
||||||
|
currentlyDebugging = true;
|
||||||
|
emit flagsChanged();
|
||||||
|
emit changeDebugView();
|
||||||
|
}
|
||||||
|
|
||||||
|
emit attachedRemote(true);
|
||||||
|
emit debugTaskStateChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
debugTaskDialog = new R2TaskDialog(debugTask);
|
||||||
|
debugTaskDialog->setBreakOnClose(true);
|
||||||
|
debugTaskDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
debugTaskDialog->setDesc("Connecting to: " + uri);
|
||||||
|
debugTaskDialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
void CutterCore::attachDebug(int pid)
|
void CutterCore::attachDebug(int pid)
|
||||||
{
|
{
|
||||||
if (!currentlyDebugging) {
|
if (!currentlyDebugging) {
|
||||||
|
@ -19,10 +19,12 @@ class BasicInstructionHighlighter;
|
|||||||
class CutterCore;
|
class CutterCore;
|
||||||
class Decompiler;
|
class Decompiler;
|
||||||
class R2Task;
|
class R2Task;
|
||||||
|
class R2TaskDialog;
|
||||||
|
|
||||||
#include "plugins/CutterPlugin.h"
|
#include "plugins/CutterPlugin.h"
|
||||||
#include "common/BasicBlockHighlighter.h"
|
#include "common/BasicBlockHighlighter.h"
|
||||||
#include "common/R2Task.h"
|
#include "common/R2Task.h"
|
||||||
|
#include "dialogs/R2TaskDialog.h"
|
||||||
|
|
||||||
#define Core() (CutterCore::instance())
|
#define Core() (CutterCore::instance())
|
||||||
|
|
||||||
@ -267,6 +269,12 @@ public:
|
|||||||
QJsonDocument getBacktrace();
|
QJsonDocument getBacktrace();
|
||||||
void startDebug();
|
void startDebug();
|
||||||
void startEmulation();
|
void startEmulation();
|
||||||
|
/**
|
||||||
|
* @brief attach to a remote debugger
|
||||||
|
* @param uri remote debugger uri
|
||||||
|
* @note attachedRemote(bool) signals the result
|
||||||
|
*/
|
||||||
|
void attachRemote(const QString &uri);
|
||||||
void attachDebug(int pid);
|
void attachDebug(int pid);
|
||||||
void stopDebug();
|
void stopDebug();
|
||||||
void suspendDebug();
|
void suspendDebug();
|
||||||
@ -473,6 +481,8 @@ signals:
|
|||||||
void classRenamed(const QString &oldName, const QString &newName);
|
void classRenamed(const QString &oldName, const QString &newName);
|
||||||
void classAttrsChanged(const QString &cls);
|
void classAttrsChanged(const QString &cls);
|
||||||
|
|
||||||
|
void attachedRemote(bool successfully);
|
||||||
|
|
||||||
void projectSaved(bool successfully, const QString &name);
|
void projectSaved(bool successfully, const QString &name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -527,6 +537,7 @@ private:
|
|||||||
BasicInstructionHighlighter biHighlighter;
|
BasicInstructionHighlighter biHighlighter;
|
||||||
|
|
||||||
QSharedPointer<R2Task> debugTask;
|
QSharedPointer<R2Task> debugTask;
|
||||||
|
R2TaskDialog *debugTaskDialog;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RCoreLocked
|
class RCoreLocked
|
||||||
|
72
src/dialogs/R2TaskDialog.cpp
Normal file
72
src/dialogs/R2TaskDialog.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "R2TaskDialog.h"
|
||||||
|
#include "common/R2Task.h"
|
||||||
|
|
||||||
|
#include <QCloseEvent>
|
||||||
|
|
||||||
|
#include "ui_R2TaskDialog.h"
|
||||||
|
|
||||||
|
R2TaskDialog::R2TaskDialog(R2Task::Ptr task, QWidget *parent)
|
||||||
|
: QDialog(parent),
|
||||||
|
ui(new Ui::R2TaskDialog),
|
||||||
|
task(task)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
connect(task.data(), &R2Task::finished, this, [this]() {
|
||||||
|
close();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&timer, SIGNAL(timeout()), this, SLOT(updateProgressTimer()));
|
||||||
|
timer.setInterval(1000);
|
||||||
|
timer.setSingleShot(false);
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
elapsedTimer.start();
|
||||||
|
updateProgressTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
R2TaskDialog::~R2TaskDialog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void R2TaskDialog::updateProgressTimer()
|
||||||
|
{
|
||||||
|
int secondsElapsed = elapsedTimer.elapsed() / 1000;
|
||||||
|
int minutesElapsed = secondsElapsed / 60;
|
||||||
|
int hoursElapsed = minutesElapsed / 60;
|
||||||
|
|
||||||
|
QString label = tr("Running for") + " ";
|
||||||
|
if (hoursElapsed) {
|
||||||
|
label += tr("%n hour", "%n hours", hoursElapsed);
|
||||||
|
label += " ";
|
||||||
|
}
|
||||||
|
if (minutesElapsed) {
|
||||||
|
label += tr("%n minute", "%n minutes", minutesElapsed % 60);
|
||||||
|
label += " ";
|
||||||
|
}
|
||||||
|
label += tr("%n seconds", "%n second", secondsElapsed % 60);
|
||||||
|
ui->timeLabel->setText(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R2TaskDialog::setDesc(const QString &label)
|
||||||
|
{
|
||||||
|
ui->descLabel->setText(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R2TaskDialog::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
if (breakOnClose) {
|
||||||
|
task->breakTask();
|
||||||
|
setDesc("Attempting to stop the task...");
|
||||||
|
event->ignore();
|
||||||
|
} else {
|
||||||
|
QWidget::closeEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void R2TaskDialog::reject()
|
||||||
|
{
|
||||||
|
task->breakTask();
|
||||||
|
setDesc("Attempting to stop the task...");
|
||||||
|
|
||||||
|
}
|
49
src/dialogs/R2TaskDialog.h
Normal file
49
src/dialogs/R2TaskDialog.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef R2TASKDIALOG_H
|
||||||
|
#define R2TASKDIALOG_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
#include "common/R2Task.h"
|
||||||
|
|
||||||
|
class R2Task;
|
||||||
|
namespace Ui {
|
||||||
|
class R2TaskDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class R2TaskDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Ptr = QSharedPointer<R2Task>;
|
||||||
|
R2TaskDialog(Ptr task, QWidget *parent = nullptr);
|
||||||
|
~R2TaskDialog();
|
||||||
|
|
||||||
|
void setBreakOnClose(bool v) { breakOnClose = v; }
|
||||||
|
bool getBreakOnClose() { return breakOnClose; }
|
||||||
|
void setDesc(const QString &label);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void reject() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateProgressTimer();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::R2TaskDialog> ui;
|
||||||
|
QSharedPointer<R2Task> task;
|
||||||
|
|
||||||
|
QTimer timer;
|
||||||
|
QElapsedTimer elapsedTimer;
|
||||||
|
|
||||||
|
bool breakOnClose = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //R2TASKDIALOG_H
|
91
src/dialogs/R2TaskDialog.ui
Normal file
91
src/dialogs/R2TaskDialog.ui
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>R2TaskDialog</class>
|
||||||
|
<widget class="QDialog" name="R2TaskDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>87</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>R2 Task</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="descLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>R2 task in progress..</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="timeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Time</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="textVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>R2TaskDialog</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>R2TaskDialog</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>
|
188
src/dialogs/RemoteDebugDialog.cpp
Normal file
188
src/dialogs/RemoteDebugDialog.cpp
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
#include "RemoteDebugDialog.h"
|
||||||
|
#include "ui_RemoteDebugDialog.h"
|
||||||
|
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#define GDBSERVER "GDB"
|
||||||
|
#define WINDBGPIPE "WinDbg - Pipe"
|
||||||
|
#define WINDBG_URI_PREFIX "windbg"
|
||||||
|
#define GDB_URI_PREFIX "gdb"
|
||||||
|
#define DEFAULT_INDEX (GDBSERVER)
|
||||||
|
|
||||||
|
RemoteDebugDialog::RemoteDebugDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::RemoteDebugDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
|
||||||
|
// Set a default selection
|
||||||
|
ui->debuggerCombo->setCurrentIndex(ui->debuggerCombo->findText(DEFAULT_INDEX));
|
||||||
|
onIndexChange();
|
||||||
|
|
||||||
|
connect(ui->debuggerCombo,
|
||||||
|
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||||
|
this, &RemoteDebugDialog::onIndexChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteDebugDialog::~RemoteDebugDialog() {}
|
||||||
|
|
||||||
|
bool RemoteDebugDialog::validate()
|
||||||
|
{
|
||||||
|
QString debugger = getDebugger();
|
||||||
|
|
||||||
|
if (debugger == GDBSERVER) {
|
||||||
|
if (!validateIp()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!validatePort()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (debugger == WINDBGPIPE) {
|
||||||
|
if (!validatePath()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText(tr("Invalid debugger"));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteDebugDialog::validateIp()
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
|
||||||
|
QString ip = getIp();
|
||||||
|
if (QHostAddress(ip).isNull()) {
|
||||||
|
msgBox.setText(tr("Invalid IP address"));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteDebugDialog::validatePath()
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
|
||||||
|
QString path = getPath();
|
||||||
|
if (!QFileInfo(path).exists()) {
|
||||||
|
msgBox.setText(tr("Path does not exist"));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoteDebugDialog::validatePort()
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
|
||||||
|
int port = getPort();
|
||||||
|
if (port < 1 || port > 65535) {
|
||||||
|
msgBox.setText(tr("Invalid port"));
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::onIndexChange()
|
||||||
|
{
|
||||||
|
QString debugger = getDebugger();
|
||||||
|
if (debugger == GDBSERVER) {
|
||||||
|
activateGdb();
|
||||||
|
} else if (debugger == WINDBGPIPE) {
|
||||||
|
activateWinDbgPipe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::activateGdb()
|
||||||
|
{
|
||||||
|
ui->ipEdit->setVisible(true);
|
||||||
|
ui->portEdit->setVisible(true);
|
||||||
|
ui->ipText->setVisible(true);
|
||||||
|
ui->portText->setVisible(true);
|
||||||
|
ui->pathEdit->setVisible(false);
|
||||||
|
ui->pathText->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::activateWinDbgPipe()
|
||||||
|
{
|
||||||
|
ui->ipEdit->setVisible(false);
|
||||||
|
ui->portEdit->setVisible(false);
|
||||||
|
ui->ipText->setVisible(false);
|
||||||
|
ui->portText->setVisible(false);
|
||||||
|
ui->pathEdit->setVisible(true);
|
||||||
|
ui->pathText->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::on_buttonBox_accepted()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::on_buttonBox_rejected()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::setIp(QString ip)
|
||||||
|
{
|
||||||
|
ui->ipEdit->setText(ip);
|
||||||
|
ui->ipEdit->selectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::setPath(QString path)
|
||||||
|
{
|
||||||
|
ui->pathEdit->setText(path);
|
||||||
|
ui->pathEdit->selectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::setPort(QString port)
|
||||||
|
{
|
||||||
|
ui->portEdit->setText(port);
|
||||||
|
ui->portEdit->selectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteDebugDialog::setDebugger(QString debugger)
|
||||||
|
{
|
||||||
|
ui->debuggerCombo->setCurrentIndex(ui->debuggerCombo->findText(debugger));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RemoteDebugDialog::getUri() const
|
||||||
|
{
|
||||||
|
QString debugger = getDebugger();
|
||||||
|
if (debugger == WINDBGPIPE) {
|
||||||
|
return QString("%1://%2").arg(WINDBG_URI_PREFIX, getPath());
|
||||||
|
} else if (debugger == GDBSERVER) {
|
||||||
|
return QString("%1://%2:%3").arg(GDB_URI_PREFIX, getIp(), QString::number(getPort()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RemoteDebugDialog::getIp() const
|
||||||
|
{
|
||||||
|
return ui->ipEdit->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RemoteDebugDialog::getPath() const
|
||||||
|
{
|
||||||
|
return ui->pathEdit->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RemoteDebugDialog::getPort() const
|
||||||
|
{
|
||||||
|
return ui->portEdit->text().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RemoteDebugDialog::getDebugger() const
|
||||||
|
{
|
||||||
|
return ui->debuggerCombo->currentText();
|
||||||
|
}
|
48
src/dialogs/RemoteDebugDialog.h
Normal file
48
src/dialogs/RemoteDebugDialog.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef REMOTEDEBUGDIALOG_H
|
||||||
|
#define REMOTEDEBUGDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RemoteDebugDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dialog for connecting to remote debuggers
|
||||||
|
*/
|
||||||
|
class RemoteDebugDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RemoteDebugDialog(QWidget *parent = nullptr);
|
||||||
|
~RemoteDebugDialog();
|
||||||
|
|
||||||
|
void setIp(QString ip);
|
||||||
|
void setPort(QString port);
|
||||||
|
void setPath(QString path);
|
||||||
|
void setDebugger(QString debugger);
|
||||||
|
QString getUri() const;
|
||||||
|
QString getIp() const;
|
||||||
|
int getPort() const;
|
||||||
|
QString getPath() const;
|
||||||
|
QString getDebugger() const;
|
||||||
|
bool validate();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
void on_buttonBox_rejected();
|
||||||
|
void onIndexChange();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void activateGdb();
|
||||||
|
void activateWinDbgPipe();
|
||||||
|
bool validateIp();
|
||||||
|
bool validatePort();
|
||||||
|
bool validatePath();
|
||||||
|
|
||||||
|
std::unique_ptr<Ui::RemoteDebugDialog> ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REMOTE_DEBUG_DIALOG
|
197
src/dialogs/RemoteDebugDialog.ui
Normal file
197
src/dialogs/RemoteDebugDialog.ui
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>RemoteDebugDialog</class>
|
||||||
|
<widget class="QDialog" name="RemoteDebugDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::NonModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>320</width>
|
||||||
|
<height>170</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Remote debugging configuration</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="gridLayoutWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>300</width>
|
||||||
|
<height>110</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="debugText">
|
||||||
|
<property name="text">
|
||||||
|
<string>Debugger:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="debuggerCombo">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>GDB</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>WinDbg - Pipe</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="ipText">
|
||||||
|
<property name="text">
|
||||||
|
<string>IP:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="ipEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="portText">
|
||||||
|
<property name="text">
|
||||||
|
<string>Port:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="portEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="pathText">
|
||||||
|
<property name="text">
|
||||||
|
<string>Path:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="pathEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="verticalLayoutWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>130</y>
|
||||||
|
<width>301</width>
|
||||||
|
<height>35</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<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>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>RemoteDebugDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>234</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>RemoteDebugDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>240</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
5
src/img/icons/play_light_remote.svg
Normal file
5
src/img/icons/play_light_remote.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="#78de82"/>
|
||||||
|
<text x="15" y="10" font-family="Helvetica, Arial, sans-serif" font-size="13" stroke-width="2" stroke="#aaacaf" fill="#aaacaf" >R</text>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 526 B |
@ -24,6 +24,7 @@
|
|||||||
<file>img/icons/play_light_debug.svg</file>
|
<file>img/icons/play_light_debug.svg</file>
|
||||||
<file>img/icons/play_light_emul.svg</file>
|
<file>img/icons/play_light_emul.svg</file>
|
||||||
<file>img/icons/play_light_attach.svg</file>
|
<file>img/icons/play_light_attach.svg</file>
|
||||||
|
<file>img/icons/play_light_remote.svg</file>
|
||||||
<file>img/icons/media-stop_light.svg</file>
|
<file>img/icons/media-stop_light.svg</file>
|
||||||
<file>img/icons/media-suspend_light.svg</file>
|
<file>img/icons/media-suspend_light.svg</file>
|
||||||
<file>img/icons/media-skip-forward_light.svg</file>
|
<file>img/icons/media-skip-forward_light.svg</file>
|
||||||
|
@ -20,6 +20,7 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
QIcon startDebugIcon = QIcon(":/img/icons/play_light_debug.svg");
|
QIcon startDebugIcon = QIcon(":/img/icons/play_light_debug.svg");
|
||||||
QIcon startEmulIcon = QIcon(":/img/icons/play_light_emul.svg");
|
QIcon startEmulIcon = QIcon(":/img/icons/play_light_emul.svg");
|
||||||
QIcon startAttachIcon = QIcon(":/img/icons/play_light_attach.svg");
|
QIcon startAttachIcon = QIcon(":/img/icons/play_light_attach.svg");
|
||||||
|
QIcon startRemoteIcon = QIcon(":/img/icons/play_light_remote.svg");
|
||||||
QIcon stopIcon = QIcon(":/img/icons/media-stop_light.svg");
|
QIcon stopIcon = QIcon(":/img/icons/media-stop_light.svg");
|
||||||
QIcon continueUntilMainIcon = QIcon(":/img/icons/continue_until_main.svg");
|
QIcon continueUntilMainIcon = QIcon(":/img/icons/continue_until_main.svg");
|
||||||
QIcon continueUntilCallIcon = QIcon(":/img/icons/continue_until_call.svg");
|
QIcon continueUntilCallIcon = QIcon(":/img/icons/continue_until_call.svg");
|
||||||
@ -35,6 +36,7 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
QString startDebugLabel = tr("Start debug");
|
QString startDebugLabel = tr("Start debug");
|
||||||
QString startEmulLabel = tr("Start emulation");
|
QString startEmulLabel = tr("Start emulation");
|
||||||
QString startAttachLabel = tr("Attach to process");
|
QString startAttachLabel = tr("Attach to process");
|
||||||
|
QString startRemoteLabel = tr("Connect to a remote debugger");
|
||||||
QString stopDebugLabel = tr("Stop debug");
|
QString stopDebugLabel = tr("Stop debug");
|
||||||
QString stopEmulLabel = tr("Stop emulation");
|
QString stopEmulLabel = tr("Stop emulation");
|
||||||
QString restartDebugLabel = tr("Restart program");
|
QString restartDebugLabel = tr("Restart program");
|
||||||
@ -53,6 +55,7 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
actionStart->setShortcut(QKeySequence(Qt::Key_F9));
|
actionStart->setShortcut(QKeySequence(Qt::Key_F9));
|
||||||
actionStartEmul = new QAction(startEmulIcon, startEmulLabel, this);
|
actionStartEmul = new QAction(startEmulIcon, startEmulLabel, this);
|
||||||
actionAttach = new QAction(startAttachIcon, startAttachLabel, this);
|
actionAttach = new QAction(startAttachIcon, startAttachLabel, this);
|
||||||
|
actionStartRemote = new QAction(startRemoteIcon, startRemoteLabel, this);
|
||||||
actionStop = new QAction(stopIcon, stopDebugLabel, this);
|
actionStop = new QAction(stopIcon, stopDebugLabel, this);
|
||||||
actionContinue = new QAction(continueIcon, continueLabel, this);
|
actionContinue = new QAction(continueIcon, continueLabel, this);
|
||||||
actionContinue->setShortcut(QKeySequence(Qt::Key_F5));
|
actionContinue->setShortcut(QKeySequence(Qt::Key_F5));
|
||||||
@ -75,8 +78,8 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
startMenu->addAction(actionStart);
|
startMenu->addAction(actionStart);
|
||||||
startMenu->addAction(actionStartEmul);
|
startMenu->addAction(actionStartEmul);
|
||||||
startMenu->addAction(actionAttach);
|
startMenu->addAction(actionAttach);
|
||||||
|
startMenu->addAction(actionStartRemote);
|
||||||
startButton->setDefaultAction(actionStart);
|
startButton->setDefaultAction(actionStart);
|
||||||
// startButton->setDefaultAction(actionStartEmul);
|
|
||||||
startButton->setMenu(startMenu);
|
startButton->setMenu(startMenu);
|
||||||
|
|
||||||
continueUntilButton = new QToolButton;
|
continueUntilButton = new QToolButton;
|
||||||
@ -105,21 +108,28 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
|
|
||||||
// Toggle all buttons except restart, suspend(=continue) and stop since those are
|
// Toggle all buttons except restart, suspend(=continue) and stop since those are
|
||||||
// necessary to avoid staying stuck
|
// necessary to avoid staying stuck
|
||||||
toggleActions = { actionStep, actionStepOver, actionStepOut, actionContinueUntilMain,
|
toggleActions = {actionStep, actionStepOver, actionStepOut, actionContinueUntilMain,
|
||||||
actionContinueUntilCall, actionContinueUntilSyscall};
|
actionContinueUntilCall, actionContinueUntilSyscall};
|
||||||
|
toggleConnectionActions = {actionAttach, actionStart, actionStartRemote, actionStartEmul};
|
||||||
|
|
||||||
connect(Core(), &CutterCore::debugTaskStateChanged, this, [ = ]() {
|
connect(Core(), &CutterCore::debugTaskStateChanged, this, [ = ]() {
|
||||||
bool disableToolbar = Core()->isDebugTaskInProgress() || !Core()->currentlyDebugging;
|
bool disableToolbar = Core()->isDebugTaskInProgress();
|
||||||
for (QAction *a : toggleActions) {
|
if (Core()->currentlyDebugging) {
|
||||||
a->setDisabled(disableToolbar);
|
for (QAction *a : toggleActions) {
|
||||||
}
|
a->setDisabled(disableToolbar);
|
||||||
// Suspend should only be available when other icons are disabled
|
}
|
||||||
if (disableToolbar) {
|
// Suspend should only be available when other icons are disabled
|
||||||
actionContinue->setText(suspendLabel);
|
if (disableToolbar) {
|
||||||
actionContinue->setIcon(suspendIcon);
|
actionContinue->setText(suspendLabel);
|
||||||
|
actionContinue->setIcon(suspendIcon);
|
||||||
|
} else {
|
||||||
|
actionContinue->setText(continueLabel);
|
||||||
|
actionContinue->setIcon(continueIcon);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
actionContinue->setText(continueLabel);
|
for (QAction *a : toggleConnectionActions) {
|
||||||
actionContinue->setIcon(continueIcon);
|
a->setDisabled(disableToolbar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -128,6 +138,7 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
actionStart->setVisible(true);
|
actionStart->setVisible(true);
|
||||||
actionStartEmul->setVisible(true);
|
actionStartEmul->setVisible(true);
|
||||||
actionAttach->setVisible(true);
|
actionAttach->setVisible(true);
|
||||||
|
actionStartRemote->setVisible(true);
|
||||||
actionStop->setText(stopDebugLabel);
|
actionStop->setText(stopDebugLabel);
|
||||||
actionStart->setText(startDebugLabel);
|
actionStart->setText(startDebugLabel);
|
||||||
actionStart->setIcon(startDebugIcon);
|
actionStart->setIcon(startDebugIcon);
|
||||||
@ -149,6 +160,7 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
}
|
}
|
||||||
setAllActionsVisible(true);
|
setAllActionsVisible(true);
|
||||||
actionAttach->setVisible(false);
|
actionAttach->setVisible(false);
|
||||||
|
actionStartRemote->setVisible(false);
|
||||||
actionStartEmul->setVisible(false);
|
actionStartEmul->setVisible(false);
|
||||||
actionStart->setText(restartDebugLabel);
|
actionStart->setText(restartDebugLabel);
|
||||||
actionStart->setIcon(restartIcon);
|
actionStart->setIcon(restartIcon);
|
||||||
@ -157,11 +169,14 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(actionAttach, &QAction::triggered, this, &DebugActions::attachProcessDialog);
|
connect(actionAttach, &QAction::triggered, this, &DebugActions::attachProcessDialog);
|
||||||
|
connect(actionStartRemote, &QAction::triggered, this, &DebugActions::attachRemoteDialog);
|
||||||
|
connect(Core(), &CutterCore::attachedRemote, this, &DebugActions::onAttachedRemoteDebugger);
|
||||||
connect(actionStartEmul, &QAction::triggered, Core(), &CutterCore::startEmulation);
|
connect(actionStartEmul, &QAction::triggered, Core(), &CutterCore::startEmulation);
|
||||||
connect(actionStartEmul, &QAction::triggered, [ = ]() {
|
connect(actionStartEmul, &QAction::triggered, [ = ]() {
|
||||||
setAllActionsVisible(true);
|
setAllActionsVisible(true);
|
||||||
actionStart->setVisible(false);
|
actionStart->setVisible(false);
|
||||||
actionAttach->setVisible(false);
|
actionAttach->setVisible(false);
|
||||||
|
actionStartRemote->setVisible(false);
|
||||||
actionContinueUntilMain->setVisible(false);
|
actionContinueUntilMain->setVisible(false);
|
||||||
actionStepOut->setVisible(false);
|
actionStepOut->setVisible(false);
|
||||||
continueUntilButton->setDefaultAction(actionContinueUntilSyscall);
|
continueUntilButton->setDefaultAction(actionContinueUntilSyscall);
|
||||||
@ -200,6 +215,49 @@ void DebugActions::continueUntilMain()
|
|||||||
Core()->continueUntilDebug(mainAddr);
|
Core()->continueUntilDebug(mainAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugActions::attachRemoteDebugger()
|
||||||
|
{
|
||||||
|
QString stopAttachLabel = tr("Detach from process");
|
||||||
|
// Hide unwanted buttons
|
||||||
|
setAllActionsVisible(true);
|
||||||
|
actionStart->setVisible(false);
|
||||||
|
actionStartRemote->setVisible(false);
|
||||||
|
actionStartEmul->setVisible(false);
|
||||||
|
actionStop->setText(stopAttachLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugActions::onAttachedRemoteDebugger(bool successfully) {
|
||||||
|
if (!successfully) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText(tr("Error connecting."));
|
||||||
|
msgBox.exec();
|
||||||
|
attachRemoteDialog();
|
||||||
|
} else {
|
||||||
|
delete remoteDialog;
|
||||||
|
attachRemoteDebugger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugActions::attachRemoteDialog()
|
||||||
|
{
|
||||||
|
if (!remoteDialog) {
|
||||||
|
remoteDialog = new RemoteDebugDialog(main);
|
||||||
|
}
|
||||||
|
QMessageBox msgBox;
|
||||||
|
bool success = false;
|
||||||
|
while (!success) {
|
||||||
|
success = true;
|
||||||
|
if (remoteDialog->exec()) {
|
||||||
|
if (!remoteDialog->validate()) {
|
||||||
|
success = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core()->attachRemote(remoteDialog->getUri());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DebugActions::attachProcessDialog()
|
void DebugActions::attachProcessDialog()
|
||||||
{
|
{
|
||||||
AttachProcDialog dialog(main);
|
AttachProcDialog dialog(main);
|
||||||
@ -226,6 +284,7 @@ void DebugActions::attachProcess(int pid)
|
|||||||
// hide unwanted buttons
|
// hide unwanted buttons
|
||||||
setAllActionsVisible(true);
|
setAllActionsVisible(true);
|
||||||
actionStart->setVisible(false);
|
actionStart->setVisible(false);
|
||||||
|
actionStartRemote->setVisible(false);
|
||||||
actionStartEmul->setVisible(false);
|
actionStartEmul->setVisible(false);
|
||||||
actionStop->setText(stopAttachLabel);
|
actionStop->setText(stopAttachLabel);
|
||||||
// attach
|
// attach
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/Cutter.h"
|
#include "core/Cutter.h"
|
||||||
|
#include "dialogs/RemoteDebugDialog.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ public:
|
|||||||
void addToToolBar(QToolBar *toolBar);
|
void addToToolBar(QToolBar *toolBar);
|
||||||
|
|
||||||
QAction *actionStart;
|
QAction *actionStart;
|
||||||
|
QAction *actionStartRemote;
|
||||||
QAction *actionStartEmul;
|
QAction *actionStartEmul;
|
||||||
QAction *actionAttach;
|
QAction *actionAttach;
|
||||||
QAction *actionContinue;
|
QAction *actionContinue;
|
||||||
@ -29,7 +31,7 @@ public:
|
|||||||
QAction *actionStepOut;
|
QAction *actionStepOut;
|
||||||
QAction *actionStop;
|
QAction *actionStop;
|
||||||
QAction *actionAllContinues;
|
QAction *actionAllContinues;
|
||||||
|
|
||||||
// Continue and suspend interchange during runtime
|
// Continue and suspend interchange during runtime
|
||||||
QIcon continueIcon;
|
QIcon continueIcon;
|
||||||
QIcon suspendIcon;
|
QIcon suspendIcon;
|
||||||
@ -41,14 +43,19 @@ private:
|
|||||||
* @brief buttons that will be disabled/enabled on (disable/enable)DebugToolbar
|
* @brief buttons that will be disabled/enabled on (disable/enable)DebugToolbar
|
||||||
*/
|
*/
|
||||||
QList<QAction *> toggleActions;
|
QList<QAction *> toggleActions;
|
||||||
MainWindow *main;
|
QList<QAction *> toggleConnectionActions;
|
||||||
QList<QAction *> allActions;
|
QList<QAction *> allActions;
|
||||||
QToolButton *continueUntilButton;
|
QToolButton *continueUntilButton;
|
||||||
|
RemoteDebugDialog *remoteDialog = nullptr;
|
||||||
|
MainWindow *main;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void continueUntilMain();
|
void continueUntilMain();
|
||||||
void attachProcessDialog();
|
void attachProcessDialog();
|
||||||
void attachProcess(int pid);
|
void attachProcess(int pid);
|
||||||
|
void attachRemoteDialog();
|
||||||
|
void attachRemoteDebugger();
|
||||||
|
void onAttachedRemoteDebugger(bool successfully);
|
||||||
void setAllActionsVisible(bool visible);
|
void setAllActionsVisible(bool visible);
|
||||||
void setButtonVisibleIfMainExists();
|
void setButtonVisibleIfMainExists();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user