mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +00:00
Add initial reverse debugging support
This commit is contained in:
parent
ac8c0e4175
commit
89a5b03484
@ -1902,6 +1902,35 @@ void CutterCore::continueDebug()
|
||||
debugTask->startTask();
|
||||
}
|
||||
|
||||
void CutterCore::continueBackDebug()
|
||||
{
|
||||
if (!currentlyDebugging) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentlyEmulating) {
|
||||
if (!asyncCmdEsil("aecb", debugTask)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!asyncCmd("dcb", debugTask)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit debugTaskStateChanged();
|
||||
|
||||
connect(debugTask.data(), &R2Task::finished, this, [this] () {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit registersChanged();
|
||||
emit stackChanged();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
debugTask->startTask();
|
||||
}
|
||||
|
||||
void CutterCore::continueUntilDebug(QString offset)
|
||||
{
|
||||
if (!currentlyDebugging) {
|
||||
@ -2055,6 +2084,32 @@ void CutterCore::stepOutDebug()
|
||||
debugTask->startTask();
|
||||
}
|
||||
|
||||
void CutterCore::stepBackDebug()
|
||||
{
|
||||
if (!currentlyDebugging) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentlyEmulating) {
|
||||
if (!asyncCmdEsil("aesb", debugTask)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!asyncCmd("dsb", debugTask)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit debugTaskStateChanged();
|
||||
|
||||
connect(debugTask.data(), &R2Task::finished, this, [this] () {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
debugTask->startTask();
|
||||
}
|
||||
|
||||
QStringList CutterCore::getDebugPlugins()
|
||||
{
|
||||
QStringList plugins;
|
||||
@ -2080,6 +2135,41 @@ void CutterCore::setDebugPlugin(QString plugin)
|
||||
setConfig("dbg.backend", plugin);
|
||||
}
|
||||
|
||||
void CutterCore::addTraceSession()
|
||||
{
|
||||
if (!currentlyDebugging) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentlyEmulating) {
|
||||
if (!asyncCmdEsil("aets+", debugTask)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!asyncCmd("dts+", debugTask)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit debugTaskStateChanged();
|
||||
|
||||
connect(debugTask.data(), &R2Task::finished, this, [this] () {
|
||||
if (debugTaskDialog) {
|
||||
delete debugTaskDialog;
|
||||
}
|
||||
debugTask.clear();
|
||||
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
debugTaskDialog = new R2TaskDialog(debugTask);
|
||||
debugTaskDialog->setBreakOnClose(true);
|
||||
debugTaskDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
debugTaskDialog->setDesc(tr("Creating debug tracepoint..."));
|
||||
debugTaskDialog->show();
|
||||
|
||||
debugTask->startTask();
|
||||
}
|
||||
|
||||
void CutterCore::toggleBreakpoint(RVA addr)
|
||||
{
|
||||
cmdRaw(QString("dbs %1").arg(addr));
|
||||
|
@ -394,12 +394,15 @@ public:
|
||||
void suspendDebug();
|
||||
void syncAndSeekProgramCounter();
|
||||
void continueDebug();
|
||||
void continueBackDebug();
|
||||
void continueUntilCall();
|
||||
void continueUntilSyscall();
|
||||
void continueUntilDebug(QString offset);
|
||||
void stepDebug();
|
||||
void stepOverDebug();
|
||||
void stepOutDebug();
|
||||
void stepBackDebug();
|
||||
void addTraceSession();
|
||||
|
||||
void addBreakpoint(const BreakpointDescription &config);
|
||||
void updateBreakpoint(int index, const BreakpointDescription &config);
|
||||
|
@ -294,10 +294,14 @@ void MainWindow::initToolBar()
|
||||
ui->menuDebug->addAction(debugActions->actionStep);
|
||||
ui->menuDebug->addAction(debugActions->actionStepOver);
|
||||
ui->menuDebug->addAction(debugActions->actionStepOut);
|
||||
ui->menuDebug->addAction(debugActions->actionStepBack);
|
||||
ui->menuDebug->addSeparator();
|
||||
ui->menuDebug->addAction(debugActions->actionContinue);
|
||||
ui->menuDebug->addAction(debugActions->actionContinueUntilCall);
|
||||
ui->menuDebug->addAction(debugActions->actionContinueUntilSyscall);
|
||||
ui->menuDebug->addAction(debugActions->actionContinueBack);
|
||||
ui->menuDebug->addSeparator();
|
||||
ui->menuDebug->addAction(debugActions->actionAddTraceSession);
|
||||
|
||||
// Sepparator between undo/redo and goto lineEdit
|
||||
QWidget *spacer4 = new QWidget();
|
||||
|
@ -33,6 +33,7 @@
|
||||
<file>img/icons/light/continue_until_call.svg</file>
|
||||
<file>img/icons/continue_until_syscall.svg</file>
|
||||
<file>img/icons/light/continue_until_syscall.svg</file>
|
||||
<file>img/icons/reverse_continue.svg</file>
|
||||
<file>img/icons/detach_debugger.svg</file>
|
||||
<file>img/icons/light/step_into.svg</file>
|
||||
<file>img/icons/step_into.svg</file>
|
||||
@ -40,6 +41,8 @@
|
||||
<file>img/icons/step_over.svg</file>
|
||||
<file>img/icons/step_out.svg</file>
|
||||
<file>img/icons/light/step_out.svg</file>
|
||||
<file>img/icons/reverse_step.svg</file>
|
||||
<file>img/icons/record_trace.svg</file>
|
||||
<file>img/icons/cloud.svg</file>
|
||||
<file>img/icons/down.svg</file>
|
||||
<file>img/icons/down_white.svg</file>
|
||||
|
@ -24,6 +24,9 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
||||
QIcon startEmulIcon = QIcon(":/img/icons/play_light_emul.svg");
|
||||
QIcon startAttachIcon = QIcon(":/img/icons/play_light_attach.svg");
|
||||
QIcon startRemoteIcon = QIcon(":/img/icons/play_light_remote.svg");
|
||||
QIcon continueBackIcon = QIcon(":/img/icons/reverse_continue.svg");
|
||||
QIcon stepBackIcon = QIcon(":/img/icons/reverse_step.svg");
|
||||
QIcon addTraceSessionIcon = QIcon(":/img/icons/record_trace.svg");
|
||||
stopIcon = QIcon(":/img/icons/media-stop_light.svg");
|
||||
restartIcon = QIcon(":/img/icons/spin_light.svg");
|
||||
detachIcon = QIcon(":/img/icons/detach_debugger.svg");
|
||||
@ -41,9 +44,12 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
||||
QString continueUMLabel = tr("Continue until main");
|
||||
QString continueUCLabel = tr("Continue until call");
|
||||
QString continueUSLabel = tr("Continue until syscall");
|
||||
QString continueBackLabel = tr("Continue backwards");
|
||||
QString stepLabel = tr("Step");
|
||||
QString stepOverLabel = tr("Step over");
|
||||
QString stepOutLabel = tr("Step out");
|
||||
QString stepBackLabel = tr("Step backwards");
|
||||
QString addTraceSessionLabel = tr("Add trace session");
|
||||
suspendLabel = tr("Suspend the process");
|
||||
continueLabel = tr("Continue");
|
||||
restartDebugLabel = tr("Restart program");
|
||||
@ -61,12 +67,17 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
||||
actionContinueUntilMain = new QAction(continueUMLabel, this);
|
||||
actionContinueUntilCall = new QAction(continueUCLabel, this);
|
||||
actionContinueUntilSyscall = new QAction(continueUSLabel, this);
|
||||
actionContinueBack = new QAction(continueBackIcon, continueBackLabel, this);
|
||||
actionContinueBack->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F5));
|
||||
actionStep = new QAction(stepLabel, this);
|
||||
actionStep->setShortcut(QKeySequence(Qt::Key_F7));
|
||||
actionStepOver = new QAction(stepOverLabel, this);
|
||||
actionStepOver->setShortcut(QKeySequence(Qt::Key_F8));
|
||||
actionStepOut = new QAction(stepOutLabel, this);
|
||||
actionStepOut->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F8));
|
||||
actionStepBack = new QAction(stepBackIcon, stepBackLabel, this);
|
||||
actionStepBack->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F7));
|
||||
actionAddTraceSession = new QAction(addTraceSessionIcon, addTraceSessionLabel, this);
|
||||
|
||||
QToolButton *startButton = new QToolButton;
|
||||
startButton->setPopupMode(QToolButton::MenuButtonPopup);
|
||||
@ -100,16 +111,22 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) :
|
||||
toolBar->addAction(actionStepOver);
|
||||
toolBar->addAction(actionStep);
|
||||
toolBar->addAction(actionStepOut);
|
||||
toolBar->addAction(actionStepBack);
|
||||
toolBar->addAction(actionContinueBack);
|
||||
toolBar->addAction(actionAddTraceSession);
|
||||
|
||||
allActions = {actionStop, actionAllContinues, actionContinue, actionContinueUntilCall, actionContinueUntilMain, actionContinueUntilSyscall, actionStep, actionStepOut, actionStepOver};
|
||||
// hide allactions
|
||||
allActions = {actionStop, actionAllContinues, actionContinue, actionContinueUntilCall,
|
||||
actionContinueUntilMain, actionContinueUntilSyscall, actionStep, actionStepOut,
|
||||
actionStepOver, actionContinueBack, actionStepBack, actionAddTraceSession};
|
||||
|
||||
// Hide all actions
|
||||
setAllActionsVisible(false);
|
||||
|
||||
// Toggle all buttons except restart, suspend(=continue) and stop since those are
|
||||
// necessary to avoid staying stuck
|
||||
toggleActions = {actionStepOver, actionStep, actionStepOut, actionContinueUntilMain,
|
||||
actionContinueUntilCall, actionContinueUntilSyscall
|
||||
};
|
||||
actionContinueUntilCall, actionContinueUntilSyscall, actionStepBack,
|
||||
actionContinueBack, actionAddTraceSession};
|
||||
toggleConnectionActions = {actionAttach, actionStartRemote};
|
||||
|
||||
connect(Core(), &CutterCore::debugProcessFinished, this, [ = ](int pid) {
|
||||
|
@ -26,11 +26,14 @@ public:
|
||||
QAction *actionContinueUntilMain;
|
||||
QAction *actionContinueUntilCall;
|
||||
QAction *actionContinueUntilSyscall;
|
||||
QAction *actionContinueBack;
|
||||
QAction *actionStep;
|
||||
QAction *actionStepOver;
|
||||
QAction *actionStepOut;
|
||||
QAction *actionStepBack;
|
||||
QAction *actionStop;
|
||||
QAction *actionAllContinues;
|
||||
QAction *actionAddTraceSession;
|
||||
|
||||
// Continue/suspend and start/restart interchange during runtime
|
||||
QIcon continueIcon;
|
||||
|
Loading…
Reference in New Issue
Block a user