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;
|
currentlyDebugging = false;
|
||||||
|
currentlyTracing = false;
|
||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
|
|
||||||
if (currentlyEmulating) {
|
if (currentlyEmulating) {
|
||||||
cmdEsil("aeim-; aei-; wcr; .ar-");
|
cmdEsil("aeim-; aei-; wcr; .ar-; aets-");
|
||||||
currentlyEmulating = false;
|
currentlyEmulating = false;
|
||||||
} else if (currentlyAttachedToPID != -1) {
|
} else if (currentlyAttachedToPID != -1) {
|
||||||
// Use cmd because cmdRaw would not work with command concatenation
|
// Use cmd because cmdRaw would not work with command concatenation
|
||||||
@ -1926,7 +1927,33 @@ void CutterCore::continueDebug()
|
|||||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||||
debugTask.clear();
|
debugTask.clear();
|
||||||
syncAndSeekProgramCounter();
|
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 refreshCodeViews();
|
||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
});
|
});
|
||||||
@ -1954,8 +1981,6 @@ void CutterCore::continueUntilDebug(QString offset)
|
|||||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||||
debugTask.clear();
|
debugTask.clear();
|
||||||
syncAndSeekProgramCounter();
|
syncAndSeekProgramCounter();
|
||||||
emit registersChanged();
|
|
||||||
emit stackChanged();
|
|
||||||
emit refreshCodeViews();
|
emit refreshCodeViews();
|
||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
});
|
});
|
||||||
@ -1983,6 +2008,7 @@ void CutterCore::continueUntilCall()
|
|||||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||||
debugTask.clear();
|
debugTask.clear();
|
||||||
syncAndSeekProgramCounter();
|
syncAndSeekProgramCounter();
|
||||||
|
emit refreshCodeViews();
|
||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2009,6 +2035,7 @@ void CutterCore::continueUntilSyscall()
|
|||||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||||
debugTask.clear();
|
debugTask.clear();
|
||||||
syncAndSeekProgramCounter();
|
syncAndSeekProgramCounter();
|
||||||
|
emit refreshCodeViews();
|
||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2035,6 +2062,7 @@ void CutterCore::stepDebug()
|
|||||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||||
debugTask.clear();
|
debugTask.clear();
|
||||||
syncAndSeekProgramCounter();
|
syncAndSeekProgramCounter();
|
||||||
|
emit refreshCodeViews();
|
||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2061,6 +2089,7 @@ void CutterCore::stepOverDebug()
|
|||||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||||
debugTask.clear();
|
debugTask.clear();
|
||||||
syncAndSeekProgramCounter();
|
syncAndSeekProgramCounter();
|
||||||
|
emit refreshCodeViews();
|
||||||
emit debugTaskStateChanged();
|
emit debugTaskStateChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2081,6 +2110,34 @@ void CutterCore::stepOutDebug()
|
|||||||
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
connect(debugTask.data(), &RizinTask::finished, this, [this]() {
|
||||||
debugTask.clear();
|
debugTask.clear();
|
||||||
syncAndSeekProgramCounter();
|
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();
|
emit debugTaskStateChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2112,6 +2169,78 @@ void CutterCore::setDebugPlugin(QString plugin)
|
|||||||
setConfig("dbg.backend", 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)
|
void CutterCore::toggleBreakpoint(RVA addr)
|
||||||
{
|
{
|
||||||
cmdRaw(QString("dbs %1").arg(addr));
|
cmdRaw(QString("dbs %1").arg(addr));
|
||||||
|
@ -409,12 +409,17 @@ public:
|
|||||||
void suspendDebug();
|
void suspendDebug();
|
||||||
void syncAndSeekProgramCounter();
|
void syncAndSeekProgramCounter();
|
||||||
void continueDebug();
|
void continueDebug();
|
||||||
|
void continueBackDebug();
|
||||||
void continueUntilCall();
|
void continueUntilCall();
|
||||||
void continueUntilSyscall();
|
void continueUntilSyscall();
|
||||||
void continueUntilDebug(QString offset);
|
void continueUntilDebug(QString offset);
|
||||||
void stepDebug();
|
void stepDebug();
|
||||||
void stepOverDebug();
|
void stepOverDebug();
|
||||||
void stepOutDebug();
|
void stepOutDebug();
|
||||||
|
void stepBackDebug();
|
||||||
|
|
||||||
|
void startTraceSession();
|
||||||
|
void stopTraceSession();
|
||||||
|
|
||||||
void addBreakpoint(const BreakpointDescription &config);
|
void addBreakpoint(const BreakpointDescription &config);
|
||||||
void updateBreakpoint(int index, const BreakpointDescription &config);
|
void updateBreakpoint(int index, const BreakpointDescription &config);
|
||||||
@ -449,6 +454,7 @@ public:
|
|||||||
bool isRedirectableDebugee();
|
bool isRedirectableDebugee();
|
||||||
bool currentlyDebugging = false;
|
bool currentlyDebugging = false;
|
||||||
bool currentlyEmulating = false;
|
bool currentlyEmulating = false;
|
||||||
|
bool currentlyTracing = false;
|
||||||
int currentlyAttachedToPID = -1;
|
int currentlyAttachedToPID = -1;
|
||||||
QString currentlyOpenFile;
|
QString currentlyOpenFile;
|
||||||
|
|
||||||
|
@ -296,10 +296,14 @@ void MainWindow::initToolBar()
|
|||||||
ui->menuDebug->addAction(debugActions->actionStep);
|
ui->menuDebug->addAction(debugActions->actionStep);
|
||||||
ui->menuDebug->addAction(debugActions->actionStepOver);
|
ui->menuDebug->addAction(debugActions->actionStepOver);
|
||||||
ui->menuDebug->addAction(debugActions->actionStepOut);
|
ui->menuDebug->addAction(debugActions->actionStepOut);
|
||||||
|
ui->menuDebug->addAction(debugActions->actionStepBack);
|
||||||
ui->menuDebug->addSeparator();
|
ui->menuDebug->addSeparator();
|
||||||
ui->menuDebug->addAction(debugActions->actionContinue);
|
ui->menuDebug->addAction(debugActions->actionContinue);
|
||||||
ui->menuDebug->addAction(debugActions->actionContinueUntilCall);
|
ui->menuDebug->addAction(debugActions->actionContinueUntilCall);
|
||||||
ui->menuDebug->addAction(debugActions->actionContinueUntilSyscall);
|
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
|
// Sepparator between undo/redo and goto lineEdit
|
||||||
QWidget *spacer4 = new QWidget();
|
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/light/continue_until_call.svg</file>
|
||||||
<file>img/icons/continue_until_syscall.svg</file>
|
<file>img/icons/continue_until_syscall.svg</file>
|
||||||
<file>img/icons/light/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/detach_debugger.svg</file>
|
||||||
<file>img/icons/light/step_into.svg</file>
|
<file>img/icons/light/step_into.svg</file>
|
||||||
<file>img/icons/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_over.svg</file>
|
||||||
<file>img/icons/step_out.svg</file>
|
<file>img/icons/step_out.svg</file>
|
||||||
<file>img/icons/light/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/cloud.svg</file>
|
||||||
<file>img/icons/down.svg</file>
|
<file>img/icons/down.svg</file>
|
||||||
<file>img/icons/down_white.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 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 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");
|
stopIcon = QIcon(":/img/icons/media-stop_light.svg");
|
||||||
restartIcon = QIcon(":/img/icons/spin_light.svg");
|
restartIcon = QIcon(":/img/icons/spin_light.svg");
|
||||||
detachIcon = QIcon(":/img/icons/detach_debugger.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 continueUMLabel = tr("Continue until main");
|
||||||
QString continueUCLabel = tr("Continue until call");
|
QString continueUCLabel = tr("Continue until call");
|
||||||
QString continueUSLabel = tr("Continue until syscall");
|
QString continueUSLabel = tr("Continue until syscall");
|
||||||
|
QString continueBackLabel = tr("Continue backwards");
|
||||||
QString stepLabel = tr("Step");
|
QString stepLabel = tr("Step");
|
||||||
QString stepOverLabel = tr("Step over");
|
QString stepOverLabel = tr("Step over");
|
||||||
QString stepOutLabel = tr("Step out");
|
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");
|
suspendLabel = tr("Suspend the process");
|
||||||
continueLabel = tr("Continue");
|
continueLabel = tr("Continue");
|
||||||
restartDebugLabel = tr("Restart program");
|
restartDebugLabel = tr("Restart program");
|
||||||
@ -59,19 +67,23 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
|||||||
actionContinueUntilMain = new QAction(continueUMLabel, this);
|
actionContinueUntilMain = new QAction(continueUMLabel, this);
|
||||||
actionContinueUntilCall = new QAction(continueUCLabel, this);
|
actionContinueUntilCall = new QAction(continueUCLabel, this);
|
||||||
actionContinueUntilSyscall = new QAction(continueUSLabel, 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 = new QAction(stepLabel, this);
|
||||||
actionStep->setShortcut(QKeySequence(Qt::Key_F7));
|
actionStep->setShortcut(QKeySequence(Qt::Key_F7));
|
||||||
actionStepOver = new QAction(stepOverLabel, this);
|
actionStepOver = new QAction(stepOverLabel, this);
|
||||||
actionStepOver->setShortcut(QKeySequence(Qt::Key_F8));
|
actionStepOver->setShortcut(QKeySequence(Qt::Key_F8));
|
||||||
actionStepOut = new QAction(stepOutLabel, this);
|
actionStepOut = new QAction(stepOutLabel, this);
|
||||||
actionStepOut->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F8));
|
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;
|
QToolButton *startButton = new QToolButton;
|
||||||
startButton->setPopupMode(QToolButton::MenuButtonPopup);
|
startButton->setPopupMode(QToolButton::MenuButtonPopup);
|
||||||
connect(startButton, &QToolButton::triggered, startButton, &QToolButton::setDefaultAction);
|
connect(startButton, &QToolButton::triggered, startButton, &QToolButton::setDefaultAction);
|
||||||
QMenu *startMenu = new QMenu(startButton);
|
QMenu *startMenu = new QMenu(startButton);
|
||||||
|
|
||||||
// only emulation is currently allowed
|
|
||||||
startMenu->addAction(actionStart);
|
startMenu->addAction(actionStart);
|
||||||
startMenu->addAction(actionStartEmul);
|
startMenu->addAction(actionStartEmul);
|
||||||
startMenu->addAction(actionAttach);
|
startMenu->addAction(actionAttach);
|
||||||
@ -98,6 +110,9 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
|||||||
toolBar->addAction(actionStepOver);
|
toolBar->addAction(actionStepOver);
|
||||||
toolBar->addAction(actionStep);
|
toolBar->addAction(actionStep);
|
||||||
toolBar->addAction(actionStepOut);
|
toolBar->addAction(actionStepOut);
|
||||||
|
toolBar->addAction(actionStepBack);
|
||||||
|
toolBar->addAction(actionContinueBack);
|
||||||
|
toolBar->addAction(actionTrace);
|
||||||
|
|
||||||
allActions = { actionStop,
|
allActions = { actionStop,
|
||||||
actionAllContinues,
|
actionAllContinues,
|
||||||
@ -107,16 +122,25 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
|||||||
actionContinueUntilSyscall,
|
actionContinueUntilSyscall,
|
||||||
actionStep,
|
actionStep,
|
||||||
actionStepOut,
|
actionStepOut,
|
||||||
actionStepOver };
|
actionStepOver,
|
||||||
// hide allactions
|
actionContinueBack,
|
||||||
|
actionStepBack,
|
||||||
|
actionTrace };
|
||||||
|
|
||||||
|
// Hide all actions
|
||||||
setAllActionsVisible(false);
|
setAllActionsVisible(false);
|
||||||
|
|
||||||
// Toggle all buttons except restart, suspend(=continue) and stop since those are
|
// Toggle all buttons except reverse step/continue which are handled separately and
|
||||||
// necessary to avoid staying stuck
|
// restart, suspend(=continue) and stop since those are necessary to avoid freezing
|
||||||
toggleActions = { actionStepOver, actionStep,
|
toggleActions = { actionStepOver,
|
||||||
actionStepOut, actionContinueUntilMain,
|
actionStep,
|
||||||
actionContinueUntilCall, actionContinueUntilSyscall };
|
actionStepOut,
|
||||||
|
actionContinueUntilMain,
|
||||||
|
actionContinueUntilCall,
|
||||||
|
actionContinueUntilSyscall,
|
||||||
|
actionTrace };
|
||||||
toggleConnectionActions = { actionAttach, actionStartRemote };
|
toggleConnectionActions = { actionAttach, actionStartRemote };
|
||||||
|
reverseActions = { actionStepBack, actionContinueBack };
|
||||||
|
|
||||||
connect(Core(), &CutterCore::debugProcessFinished, this, [=](int pid) {
|
connect(Core(), &CutterCore::debugProcessFinished, this, [=](int pid) {
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
@ -138,6 +162,10 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
|||||||
actionContinue->setText(continueLabel);
|
actionContinue->setText(continueLabel);
|
||||||
actionContinue->setIcon(continueIcon);
|
actionContinue->setIcon(continueIcon);
|
||||||
}
|
}
|
||||||
|
for (QAction *a : reverseActions) {
|
||||||
|
a->setVisible(Core()->currentlyTracing);
|
||||||
|
a->setDisabled(disableToolbar);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (QAction *a : toggleConnectionActions) {
|
for (QAction *a : toggleConnectionActions) {
|
||||||
a->setDisabled(disableToolbar);
|
a->setDisabled(disableToolbar);
|
||||||
@ -160,7 +188,10 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
|||||||
continueUntilButton->setDefaultAction(actionContinueUntilMain);
|
continueUntilButton->setDefaultAction(actionContinueUntilMain);
|
||||||
setAllActionsVisible(false);
|
setAllActionsVisible(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(actionStep, &QAction::triggered, Core(), &CutterCore::stepDebug);
|
connect(actionStep, &QAction::triggered, Core(), &CutterCore::stepDebug);
|
||||||
|
connect(actionStepBack, &QAction::triggered, Core(), &CutterCore::stepBackDebug);
|
||||||
|
|
||||||
connect(actionStart, &QAction::triggered, this, &DebugActions::startDebug);
|
connect(actionStart, &QAction::triggered, this, &DebugActions::startDebug);
|
||||||
|
|
||||||
connect(actionAttach, &QAction::triggered, this, &DebugActions::attachProcessDialog);
|
connect(actionAttach, &QAction::triggered, this, &DebugActions::attachProcessDialog);
|
||||||
@ -178,6 +209,10 @@ DebugActions::DebugActions(QToolBar *toolBar, MainWindow *main) : QObject(main),
|
|||||||
actionStartEmul->setText(restartEmulLabel);
|
actionStartEmul->setText(restartEmulLabel);
|
||||||
actionStartEmul->setIcon(restartIcon);
|
actionStartEmul->setIcon(restartIcon);
|
||||||
actionStop->setText(stopEmulLabel);
|
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(actionStepOver, &QAction::triggered, Core(), &CutterCore::stepOverDebug);
|
||||||
connect(actionStepOut, &QAction::triggered, Core(), &CutterCore::stepOutDebug);
|
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(actionContinueUntilCall, &QAction::triggered, Core(), &CutterCore::continueUntilCall);
|
||||||
connect(actionContinueUntilSyscall, &QAction::triggered, Core(),
|
connect(actionContinueUntilSyscall, &QAction::triggered, Core(),
|
||||||
&CutterCore::continueUntilSyscall);
|
&CutterCore::continueUntilSyscall);
|
||||||
|
connect(actionContinueBack, &QAction::triggered, Core(), &CutterCore::continueBackDebug);
|
||||||
connect(actionContinue, &QAction::triggered, Core(), [=]() {
|
connect(actionContinue, &QAction::triggered, Core(), [=]() {
|
||||||
// Switch between continue and suspend depending on the debugger's state
|
// Switch between continue and suspend depending on the debugger's state
|
||||||
if (Core()->isDebugTaskInProgress()) {
|
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);
|
connect(Config(), &Configuration::interfaceThemeChanged, this, &DebugActions::chooseThemeIcons);
|
||||||
chooseThemeIcons();
|
chooseThemeIcons();
|
||||||
}
|
}
|
||||||
@ -352,6 +401,13 @@ void DebugActions::startDebug()
|
|||||||
actionStart->setIcon(restartIcon);
|
actionStart->setIcon(restartIcon);
|
||||||
setButtonVisibleIfMainExists();
|
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();
|
Core()->startDebug();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,21 +26,28 @@ public:
|
|||||||
QAction *actionContinueUntilMain;
|
QAction *actionContinueUntilMain;
|
||||||
QAction *actionContinueUntilCall;
|
QAction *actionContinueUntilCall;
|
||||||
QAction *actionContinueUntilSyscall;
|
QAction *actionContinueUntilSyscall;
|
||||||
|
QAction *actionContinueBack;
|
||||||
QAction *actionStep;
|
QAction *actionStep;
|
||||||
QAction *actionStepOver;
|
QAction *actionStepOver;
|
||||||
QAction *actionStepOut;
|
QAction *actionStepOut;
|
||||||
|
QAction *actionStepBack;
|
||||||
QAction *actionStop;
|
QAction *actionStop;
|
||||||
QAction *actionAllContinues;
|
QAction *actionAllContinues;
|
||||||
|
QAction *actionTrace;
|
||||||
|
|
||||||
// Continue/suspend and start/restart interchange during runtime
|
// Continue/suspend and start/restart interchange during runtime
|
||||||
QIcon continueIcon;
|
QIcon continueIcon;
|
||||||
QIcon suspendIcon;
|
QIcon suspendIcon;
|
||||||
QIcon restartIcon;
|
QIcon restartIcon;
|
||||||
QIcon startDebugIcon;
|
QIcon startDebugIcon;
|
||||||
QString suspendLabel;
|
QIcon startTraceIcon;
|
||||||
|
QIcon stopTraceIcon;
|
||||||
QString continueLabel;
|
QString continueLabel;
|
||||||
|
QString suspendLabel;
|
||||||
QString restartDebugLabel;
|
QString restartDebugLabel;
|
||||||
QString startDebugLabel;
|
QString startDebugLabel;
|
||||||
|
QString startTraceLabel;
|
||||||
|
QString stopTraceLabel;
|
||||||
|
|
||||||
// Stop and Detach interchange during runtime
|
// Stop and Detach interchange during runtime
|
||||||
QIcon detachIcon;
|
QIcon detachIcon;
|
||||||
@ -52,6 +59,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
QList<QAction *> toggleActions;
|
QList<QAction *> toggleActions;
|
||||||
QList<QAction *> toggleConnectionActions;
|
QList<QAction *> toggleConnectionActions;
|
||||||
|
QList<QAction *> reverseActions;
|
||||||
QList<QAction *> allActions;
|
QList<QAction *> allActions;
|
||||||
QToolButton *continueUntilButton;
|
QToolButton *continueUntilButton;
|
||||||
RemoteDebugDialog *remoteDialog = nullptr;
|
RemoteDebugDialog *remoteDialog = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user