Add initial reverse debugging support

This commit is contained in:
yossizap 2019-12-12 19:53:10 +00:00
parent ac8c0e4175
commit 89a5b03484
6 changed files with 124 additions and 4 deletions

View File

@ -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));

View File

@ -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);

View File

@ -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();

View File

@ -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>

View 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) {

View File

@ -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;