mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 19:36:11 +00:00
Add reverse debugging (#1918)
* Add initial reverse debugging support * Add reverse debug icons * Added an option to stop the debug session and enabled continue and step back * Added a new icon for stop trace and recolored start trace * Toggle reverse debug actions when not tracing * Stop existing trace sessions in stopDebug * Ported to Rizin * Set reverse icons to invisible when not in a trace session instead of disabled * Updated rizin submodule * Cleaned up step and continue events * Apply clang format
This commit is contained in:
parent
3b8f98ca42
commit
8f89d1641b
2
rizin
2
rizin
@ -1 +1 @@
|
||||
Subproject commit 74ca7ff0d1a95d3604b1900311e18741af097ec4
|
||||
Subproject commit 380372dce7cc7bf6244f135d10c73a426a098167
|
@ -1865,10 +1865,11 @@ void CutterCore::stopDebug()
|
||||
}
|
||||
|
||||
currentlyDebugging = false;
|
||||
currentlyTracing = false;
|
||||
emit debugTaskStateChanged();
|
||||
|
||||
if (currentlyEmulating) {
|
||||
cmdEsil("aeim-; aei-; wcr; .ar-");
|
||||
cmdEsil("aeim-; aei-; wcr; .ar-; aets-");
|
||||
currentlyEmulating = false;
|
||||
} else if (currentlyAttachedToPID != -1) {
|
||||
// Use cmd because cmdRaw would not work with command concatenation
|
||||
@ -1926,7 +1927,33 @@ void CutterCore::continueDebug()
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit registersChanged();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
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(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
@ -1954,8 +1981,6 @@ void CutterCore::continueUntilDebug(QString offset)
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit registersChanged();
|
||||
emit stackChanged();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
@ -1983,6 +2008,7 @@ void CutterCore::continueUntilCall()
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
@ -2009,6 +2035,7 @@ void CutterCore::continueUntilSyscall()
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
@ -2035,6 +2062,7 @@ void CutterCore::stepDebug()
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
@ -2061,6 +2089,7 @@ void CutterCore::stepOverDebug()
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
@ -2081,6 +2110,34 @@ void CutterCore::stepOutDebug()
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
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(), &RizinTask::finished, this, [this]() {
|
||||
debugTask.clear();
|
||||
syncAndSeekProgramCounter();
|
||||
emit refreshCodeViews();
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
@ -2112,6 +2169,78 @@ void CutterCore::setDebugPlugin(QString plugin)
|
||||
setConfig("dbg.backend", plugin);
|
||||
}
|
||||
|
||||
void CutterCore::startTraceSession()
|
||||
{
|
||||
if (!currentlyDebugging || currentlyTracing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentlyEmulating) {
|
||||
if (!asyncCmdEsil("aets+", debugTask)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!asyncCmd("dts+", debugTask)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit debugTaskStateChanged();
|
||||
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
if (debugTaskDialog) {
|
||||
delete debugTaskDialog;
|
||||
}
|
||||
debugTask.clear();
|
||||
|
||||
currentlyTracing = true;
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
debugTaskDialog = new RizinTaskDialog(debugTask);
|
||||
debugTaskDialog->setBreakOnClose(true);
|
||||
debugTaskDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
debugTaskDialog->setDesc(tr("Creating debug tracepoint..."));
|
||||
debugTaskDialog->show();
|
||||
|
||||
debugTask->startTask();
|
||||
}
|
||||
|
||||
void CutterCore::stopTraceSession()
|
||||
{
|
||||
if (!currentlyDebugging || !currentlyTracing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentlyEmulating) {
|
||||
if (!asyncCmdEsil("aets-", debugTask)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!asyncCmd("dts-", debugTask)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit debugTaskStateChanged();
|
||||
|
||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||
if (debugTaskDialog) {
|
||||
delete debugTaskDialog;
|
||||
}
|
||||
debugTask.clear();
|
||||
|
||||
currentlyTracing = false;
|
||||
emit debugTaskStateChanged();
|
||||
});
|
||||
|
||||
debugTaskDialog = new RizinTaskDialog(debugTask);
|
||||
debugTaskDialog->setBreakOnClose(true);
|
||||
debugTaskDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
debugTaskDialog->setDesc(tr("Stopping debug session..."));
|
||||
debugTaskDialog->show();
|
||||
|
||||
debugTask->startTask();
|
||||
}
|
||||
|
||||
void CutterCore::toggleBreakpoint(RVA addr)
|
||||
{
|
||||
cmdRaw(QString("dbs %1").arg(addr));
|
||||
|
@ -409,12 +409,17 @@ 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 startTraceSession();
|
||||
void stopTraceSession();
|
||||
|
||||
void addBreakpoint(const BreakpointDescription &config);
|
||||
void updateBreakpoint(int index, const BreakpointDescription &config);
|
||||
@ -449,6 +454,7 @@ public:
|
||||
bool isRedirectableDebugee();
|
||||
bool currentlyDebugging = false;
|
||||
bool currentlyEmulating = false;
|
||||
bool currentlyTracing = false;
|
||||
int currentlyAttachedToPID = -1;
|
||||
QString currentlyOpenFile;
|
||||
|
||||
|
@ -296,10 +296,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->actionTrace);
|
||||
|
||||
// Sepparator between undo/redo and goto lineEdit
|
||||
QWidget *spacer4 = new QWidget();
|
||||
|
8
src/img/icons/reverse_continue.svg
Normal file
8
src/img/icons/reverse_continue.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<metadata id="metadata5379">image/svg+xml</metadata>
|
||||
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path clip-rule="evenodd" d="m15.833328,2.249998l-1.46,0l0,0.24001l0,11.75999l1.46,0l0,-12zm-3.406667,0.18094l0,11.81906l-8.76,-5.93782l8.76,-5.88124zm-6.146405,5.88124l4.686182,-3.06218l0,6.1809l-4.686182,-3.11872z" fill="#75beff" fill-rule="evenodd" id="svg_1"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 482 B |
6
src/img/icons/reverse_step.svg
Normal file
6
src/img/icons/reverse_step.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path clip-rule="evenodd" d="m1.731978,6.075001l0,-4l1.518314,0l0,2.5416c1.158979,-1.35857 2.94652,-2.20826 4.899932,-2.20826c3.214756,0 5.992004,2.30702 6.233608,5.39741l0.021054,0.26925l-1.519407,0l-0.022147,-0.2259c-0.215125,-2.19478 -2.229097,-3.94076 -4.713108,-3.94076c-1.757256,0 -3.283232,0.87591 -4.099072,2.16666l2.863448,0l0,1.5l-4.212925,0l-0.973239,-0.97507l0,-0.52493l0.003543,0zm6.326306,8.25c-1.118056,0 -2.024418,-0.8954 -2.024418,-2c0,-1.1046 0.906362,-2 2.024418,-2c1.118056,0 2.024418,0.8954 2.024418,2c0,1.1046 -0.906362,2 -2.024418,2z" fill="#75BEFF" fill-rule="evenodd" id="svg_4"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 768 B |
62
src/img/icons/start_trace.svg
Normal file
62
src/img/icons/start_trace.svg
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="500px"
|
||||
height="500px"
|
||||
viewBox="0 0 500 500"
|
||||
enable-background="new 0 0 500 500"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="stop_trace.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata13"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs11" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview9"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.944"
|
||||
inkscape:cx="49.481017"
|
||||
inkscape:cy="170.83775"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<g
|
||||
id="g4"
|
||||
style="fill:#78de82;fill-opacity:1">
|
||||
<path
|
||||
enable-background="new "
|
||||
d="M366.566,249.441c0.229,64.494-51.64,116.898-115.929,117.123 c-64.571,0.227-117.042-51.708-117.203-116.005c-0.162-64.701,51.523-116.88,116.016-117.124 C314.081,133.191,366.336,184.951,366.566,249.441z"
|
||||
id="path2"
|
||||
fill="#78de82"
|
||||
opacity="0.75"
|
||||
style="fill:#78de82;fill-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
opacity="0.75"
|
||||
fill="#78de82"
|
||||
enable-background="new "
|
||||
d="M250,70.443c-99.165,0-179.557,80.392-179.557,179.557 S150.835,429.557,250,429.557S429.557,349.165,429.557,250S349.165,70.443,250,70.443z M250,399.837 c-83.303,0-150.82-67.518-150.82-150.82S166.697,98.196,250,98.196s150.82,67.528,150.82,150.82S333.303,399.837,250,399.837z"
|
||||
id="path6"
|
||||
style="fill:#78de82;fill-opacity:0.74901962" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
59
src/img/icons/stop_trace.svg
Normal file
59
src/img/icons/stop_trace.svg
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="500px"
|
||||
height="500px"
|
||||
viewBox="0 0 500 500"
|
||||
enable-background="new 0 0 500 500"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="stop_trace.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata13"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs11" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview9"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.472"
|
||||
inkscape:cx="250"
|
||||
inkscape:cy="250"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid17" /></sodipodi:namedview>
|
||||
|
||||
<path
|
||||
opacity="0.75"
|
||||
fill="#b15858"
|
||||
enable-background="new "
|
||||
d="M250,70.443c-99.165,0-179.557,80.392-179.557,179.557 S150.835,429.557,250,429.557S429.557,349.165,429.557,250S349.165,70.443,250,70.443z M250,399.837 c-83.303,0-150.82-67.518-150.82-150.82S166.697,98.196,250,98.196s150.82,67.528,150.82,150.82S333.303,399.837,250,399.837z"
|
||||
id="path6" />
|
||||
<rect
|
||||
id="rect15"
|
||||
width="179.15254"
|
||||
height="180.00002"
|
||||
x="160.84744"
|
||||
y="160"
|
||||
style="fill:#ff3d3d;fill-opacity:0.74901961;stroke-width:0.87863451" /></svg>
|
After Width: | Height: | Size: 2.0 KiB |
@ -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,9 @@
|
||||
<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/start_trace.svg</file>
|
||||
<file>img/icons/stop_trace.svg</file>
|
||||
<file>img/icons/cloud.svg</file>
|
||||
<file>img/icons/down.svg</file>
|
||||
<file>img/icons/down_white.svg</file>
|
||||
|
@ -22,6 +22,10 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(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");
|
||||
startTraceIcon = QIcon(":/img/icons/start_trace.svg");
|
||||
stopTraceIcon = QIcon(":/img/icons/stop_trace.svg");
|
||||
stopIcon = QIcon(":/img/icons/media-stop_light.svg");
|
||||
restartIcon = QIcon(":/img/icons/spin_light.svg");
|
||||
detachIcon = QIcon(":/img/icons/detach_debugger.svg");
|
||||
@ -39,9 +43,13 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(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");
|
||||
startTraceLabel = tr("Start trace session");
|
||||
stopTraceLabel = tr("Stop trace session");
|
||||
suspendLabel = tr("Suspend the process");
|
||||
continueLabel = tr("Continue");
|
||||
restartDebugLabel = tr("Restart program");
|
||||
@ -59,19 +67,23 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(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));
|
||||
actionTrace = new QAction(startTraceIcon, startTraceLabel, this);
|
||||
|
||||
QToolButton *startButton = new QToolButton;
|
||||
startButton->setPopupMode(QToolButton::MenuButtonPopup);
|
||||
connect(startButton, &QToolButton::triggered, startButton, &QToolButton::setDefaultAction);
|
||||
QMenu *startMenu = new QMenu(startButton);
|
||||
|
||||
// only emulation is currently allowed
|
||||
startMenu->addAction(actionStart);
|
||||
startMenu->addAction(actionStartEmul);
|
||||
startMenu->addAction(actionAttach);
|
||||
@ -98,6 +110,9 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
||||
toolBar->addAction(actionStepOver);
|
||||
toolBar->addAction(actionStep);
|
||||
toolBar->addAction(actionStepOut);
|
||||
toolBar->addAction(actionStepBack);
|
||||
toolBar->addAction(actionContinueBack);
|
||||
toolBar->addAction(actionTrace);
|
||||
|
||||
allActions = { actionStop,
|
||||
actionAllContinues,
|
||||
@ -107,16 +122,25 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
||||
actionContinueUntilSyscall,
|
||||
actionStep,
|
||||
actionStepOut,
|
||||
actionStepOver };
|
||||
// hide allactions
|
||||
actionStepOver,
|
||||
actionContinueBack,
|
||||
actionStepBack,
|
||||
actionTrace };
|
||||
|
||||
// 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 };
|
||||
// Toggle all buttons except reverse step/continue which are handled separately and
|
||||
// restart, suspend(=continue) and stop since those are necessary to avoid freezing
|
||||
toggleActions = { actionStepOver,
|
||||
actionStep,
|
||||
actionStepOut,
|
||||
actionContinueUntilMain,
|
||||
actionContinueUntilCall,
|
||||
actionContinueUntilSyscall,
|
||||
actionTrace };
|
||||
toggleConnectionActions = { actionAttach, actionStartRemote };
|
||||
reverseActions = { actionStepBack, actionContinueBack };
|
||||
|
||||
connect(Core(), &CutterCore::debugProcessFinished, this, [=](int pid) {
|
||||
QMessageBox msgBox;
|
||||
@ -138,6 +162,10 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
||||
actionContinue->setText(continueLabel);
|
||||
actionContinue->setIcon(continueIcon);
|
||||
}
|
||||
for (QAction *a : reverseActions) {
|
||||
a->setVisible(Core()->currentlyTracing);
|
||||
a->setDisabled(disableToolbar);
|
||||
}
|
||||
} else {
|
||||
for (QAction *a : toggleConnectionActions) {
|
||||
a->setDisabled(disableToolbar);
|
||||
@ -160,7 +188,10 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
||||
continueUntilButton->setDefaultAction(actionContinueUntilMain);
|
||||
setAllActionsVisible(false);
|
||||
});
|
||||
|
||||
connect(actionStep, &QAction::triggered, Core(), &CutterCore::stepDebug);
|
||||
connect(actionStepBack, &QAction::triggered, Core(), &CutterCore::stepBackDebug);
|
||||
|
||||
connect(actionStart, &QAction::triggered, this, &DebugActions::startDebug);
|
||||
|
||||
connect(actionAttach, &QAction::triggered, this, &DebugActions::attachProcessDialog);
|
||||
@ -178,6 +209,10 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
||||
actionStartEmul->setText(restartEmulLabel);
|
||||
actionStartEmul->setIcon(restartIcon);
|
||||
actionStop->setText(stopEmulLabel);
|
||||
// Reverse debug actions aren't visible until we start tracing
|
||||
for (QAction *a : reverseActions) {
|
||||
a->setVisible(false);
|
||||
}
|
||||
});
|
||||
connect(actionStepOver, &QAction::triggered, Core(), &CutterCore::stepOverDebug);
|
||||
connect(actionStepOut, &QAction::triggered, Core(), &CutterCore::stepOutDebug);
|
||||
@ -185,6 +220,7 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
||||
connect(actionContinueUntilCall, &QAction::triggered, Core(), &CutterCore::continueUntilCall);
|
||||
connect(actionContinueUntilSyscall, &QAction::triggered, Core(),
|
||||
&CutterCore::continueUntilSyscall);
|
||||
connect(actionContinueBack, &QAction::triggered, Core(), &CutterCore::continueBackDebug);
|
||||
connect(actionContinue, &QAction::triggered, Core(), [=]() {
|
||||
// Switch between continue and suspend depending on the debugger's state
|
||||
if (Core()->isDebugTaskInProgress()) {
|
||||
@ -194,6 +230,19 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
||||
}
|
||||
});
|
||||
|
||||
connect(actionTrace, &QAction::triggered, Core(), [=]() {
|
||||
// Check if a debug session was created to switch between start and stop
|
||||
if (!Core()->currentlyTracing) {
|
||||
Core()->startTraceSession();
|
||||
actionTrace->setText(stopTraceLabel);
|
||||
actionTrace->setIcon(stopTraceIcon);
|
||||
} else {
|
||||
Core()->stopTraceSession();
|
||||
actionTrace->setText(startTraceLabel);
|
||||
actionTrace->setIcon(startTraceIcon);
|
||||
}
|
||||
});
|
||||
|
||||
connect(Config(), &Configuration::interfaceThemeChanged, this, &DebugActions::chooseThemeIcons);
|
||||
chooseThemeIcons();
|
||||
}
|
||||
@ -352,6 +401,13 @@ void DebugActions::startDebug()
|
||||
actionStart->setIcon(restartIcon);
|
||||
setButtonVisibleIfMainExists();
|
||||
|
||||
// Reverse debug actions aren't visible until we start tracing
|
||||
for (QAction *a : reverseActions) {
|
||||
a->setVisible(false);
|
||||
}
|
||||
actionTrace->setText(startTraceLabel);
|
||||
actionTrace->setIcon(startTraceIcon);
|
||||
|
||||
Core()->startDebug();
|
||||
}
|
||||
|
||||
|
@ -26,21 +26,28 @@ public:
|
||||
QAction *actionContinueUntilMain;
|
||||
QAction *actionContinueUntilCall;
|
||||
QAction *actionContinueUntilSyscall;
|
||||
QAction *actionContinueBack;
|
||||
QAction *actionStep;
|
||||
QAction *actionStepOver;
|
||||
QAction *actionStepOut;
|
||||
QAction *actionStepBack;
|
||||
QAction *actionStop;
|
||||
QAction *actionAllContinues;
|
||||
QAction *actionTrace;
|
||||
|
||||
// Continue/suspend and start/restart interchange during runtime
|
||||
QIcon continueIcon;
|
||||
QIcon suspendIcon;
|
||||
QIcon restartIcon;
|
||||
QIcon startDebugIcon;
|
||||
QString suspendLabel;
|
||||
QIcon startTraceIcon;
|
||||
QIcon stopTraceIcon;
|
||||
QString continueLabel;
|
||||
QString suspendLabel;
|
||||
QString restartDebugLabel;
|
||||
QString startDebugLabel;
|
||||
QString startTraceLabel;
|
||||
QString stopTraceLabel;
|
||||
|
||||
// Stop and Detach interchange during runtime
|
||||
QIcon detachIcon;
|
||||
@ -52,6 +59,7 @@ private:
|
||||
*/
|
||||
QList<QAction *> toggleActions;
|
||||
QList<QAction *> toggleConnectionActions;
|
||||
QList<QAction *> reverseActions;
|
||||
QList<QAction *> allActions;
|
||||
QToolButton *continueUntilButton;
|
||||
RemoteDebugDialog *remoteDialog = nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user