mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-21 12:26:11 +00:00
highlight PC line while debugging (#541)
* highlight PC line while debugging * highlight PC correctly
This commit is contained in:
parent
1f49440c02
commit
837ffef20f
@ -751,6 +751,18 @@ QString CutterCore::getRegisterName(QString registerRole)
|
|||||||
return cmd("drn " + registerRole).trimmed();
|
return cmd("drn " + registerRole).trimmed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RVA CutterCore::getProgramCounterValue()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
if (currentlyDebugging) {
|
||||||
|
RVA addr = cmd("dr?`drn PC`").toULongLong(&ok, 16);
|
||||||
|
if (ok) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RVA_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
void CutterCore::setRegister(QString regName, QString regValue)
|
void CutterCore::setRegister(QString regName, QString regValue)
|
||||||
{
|
{
|
||||||
cmd("dr " + regName + "=" + regValue);
|
cmd("dr " + regName + "=" + regValue);
|
||||||
@ -774,10 +786,12 @@ void CutterCore::stopDebug()
|
|||||||
{
|
{
|
||||||
// @TODO should first obtain correct signal to send.
|
// @TODO should first obtain correct signal to send.
|
||||||
// Also, we do a ds since otherwise the process does not die.
|
// Also, we do a ds since otherwise the process does not die.
|
||||||
|
if (currentlyDebugging) {
|
||||||
cmd("dk 9; ds; e cfg.debug = false; oo");
|
cmd("dk 9; ds; e cfg.debug = false; oo");
|
||||||
seek(offsetPriorDebugging);
|
seek(offsetPriorDebugging);
|
||||||
emit changeDefinedView();
|
emit changeDefinedView();
|
||||||
currentlyDebugging = false;
|
currentlyDebugging = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::continueDebug()
|
void CutterCore::continueDebug()
|
||||||
@ -795,7 +809,7 @@ void CutterCore::continueUntilDebug(QString offset)
|
|||||||
void CutterCore::continueUntilCall()
|
void CutterCore::continueUntilCall()
|
||||||
{
|
{
|
||||||
cmd("dcc");
|
cmd("dcc");
|
||||||
QString programCounterValue = cmd("dr?`drn pc`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seek(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
@ -803,7 +817,7 @@ void CutterCore::continueUntilCall()
|
|||||||
void CutterCore::continueUntilSyscall()
|
void CutterCore::continueUntilSyscall()
|
||||||
{
|
{
|
||||||
cmd("dcs");
|
cmd("dcs");
|
||||||
QString programCounterValue = cmd("dr?`drn pc`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seek(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
@ -811,7 +825,7 @@ void CutterCore::continueUntilSyscall()
|
|||||||
void CutterCore::stepDebug()
|
void CutterCore::stepDebug()
|
||||||
{
|
{
|
||||||
cmd("ds");
|
cmd("ds");
|
||||||
QString programCounterValue = cmd("dr?`drn pc`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seek(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
@ -819,7 +833,7 @@ void CutterCore::stepDebug()
|
|||||||
void CutterCore::stepOverDebug()
|
void CutterCore::stepOverDebug()
|
||||||
{
|
{
|
||||||
cmd("dso");
|
cmd("dso");
|
||||||
QString programCounterValue = cmd("dr?`drn pc`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seek(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
|
@ -475,6 +475,7 @@ public:
|
|||||||
QJsonDocument getRegistersInfo();
|
QJsonDocument getRegistersInfo();
|
||||||
QJsonDocument getRegisterValues();
|
QJsonDocument getRegisterValues();
|
||||||
QString getRegisterName(QString registerRole);
|
QString getRegisterName(QString registerRole);
|
||||||
|
RVA getProgramCounterValue();
|
||||||
void setRegister(QString regName, QString regValue);
|
void setRegister(QString regName, QString regValue);
|
||||||
QJsonDocument getStack(int size = 0x40);
|
QJsonDocument getStack(int size = 0x40);
|
||||||
QJsonDocument getBacktrace();
|
QJsonDocument getBacktrace();
|
||||||
@ -494,6 +495,7 @@ public:
|
|||||||
QString getActiveDebugPlugin();
|
QString getActiveDebugPlugin();
|
||||||
QStringList getDebugPlugins();
|
QStringList getDebugPlugins();
|
||||||
void setDebugPlugin(QString plugin);
|
void setDebugPlugin(QString plugin);
|
||||||
|
bool currentlyDebugging = false;
|
||||||
|
|
||||||
RVA getOffsetJump(RVA addr);
|
RVA getOffsetJump(RVA addr);
|
||||||
QString getDecompiledCode(RVA addr);
|
QString getDecompiledCode(RVA addr);
|
||||||
|
@ -422,12 +422,14 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
|||||||
tr("Do you really want to exit?\nSave your project before closing!"),
|
tr("Do you really want to exit?\nSave your project before closing!"),
|
||||||
(QMessageBox::StandardButtons)(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel));
|
(QMessageBox::StandardButtons)(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel));
|
||||||
if (ret == QMessageBox::Save) {
|
if (ret == QMessageBox::Save) {
|
||||||
if (saveProject(true)) {
|
if (saveProject(true) && !Core()->currentlyDebugging) {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
} else if (ret == QMessageBox::Discard) {
|
} else if (ret == QMessageBox::Discard) {
|
||||||
|
if (!Core()->currentlyDebugging) {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
}
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
} else {
|
} else {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
|
@ -119,6 +119,8 @@ void Configuration::loadDefaultTheme()
|
|||||||
setColor("gui.border", QColor(0, 0, 0));
|
setColor("gui.border", QColor(0, 0, 0));
|
||||||
setColor("highlight", QColor(210, 210, 255));
|
setColor("highlight", QColor(210, 210, 255));
|
||||||
setColor("highlightWord", QColor(210, 210, 255));
|
setColor("highlightWord", QColor(210, 210, 255));
|
||||||
|
// RIP line selection in debug
|
||||||
|
setColor("highlightPC", QColor(214, 255, 210));
|
||||||
// Windows background
|
// Windows background
|
||||||
setColor("gui.background", QColor(255, 255, 255));
|
setColor("gui.background", QColor(255, 255, 255));
|
||||||
setColor("gui.disass_selected", QColor(255, 255, 255));
|
setColor("gui.disass_selected", QColor(255, 255, 255));
|
||||||
@ -171,6 +173,8 @@ void Configuration::loadBaseDark()
|
|||||||
setColor("gui.navbar.str", QColor(69, 104, 229));
|
setColor("gui.navbar.str", QColor(69, 104, 229));
|
||||||
setColor("gui.navbar.sym", QColor(229, 150, 69));
|
setColor("gui.navbar.sym", QColor(229, 150, 69));
|
||||||
setColor("gui.navbar.empty", QColor(100, 100, 100));
|
setColor("gui.navbar.empty", QColor(100, 100, 100));
|
||||||
|
// RIP line selection in debug
|
||||||
|
setColor("highlightPC", QColor(87, 26, 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Configuration::loadDarkTheme()
|
void Configuration::loadDarkTheme()
|
||||||
|
@ -335,15 +335,20 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
// Render node
|
// Render node
|
||||||
DisassemblyBlock &db = disassembly_blocks[block.entry];
|
DisassemblyBlock &db = disassembly_blocks[block.entry];
|
||||||
bool block_selected = false;
|
bool block_selected = false;
|
||||||
|
bool PCInBlock = false;
|
||||||
RVA selected_instruction = RVA_INVALID;
|
RVA selected_instruction = RVA_INVALID;
|
||||||
|
|
||||||
// Figure out if the current block is selected
|
// Figure out if the current block is selected
|
||||||
for (const Instr &instr : db.instrs) {
|
|
||||||
RVA addr = seekable->getOffset();
|
RVA addr = seekable->getOffset();
|
||||||
|
RVA PCAddr = Core()->getProgramCounterValue();
|
||||||
|
for (const Instr &instr : db.instrs) {
|
||||||
if ((instr.addr <= addr) && (addr <= instr.addr + instr.size)) {
|
if ((instr.addr <= addr) && (addr <= instr.addr + instr.size)) {
|
||||||
block_selected = true;
|
block_selected = true;
|
||||||
selected_instruction = instr.addr;
|
selected_instruction = instr.addr;
|
||||||
}
|
}
|
||||||
|
if ((instr.addr <= PCAddr) && (PCAddr <= instr.addr + instr.size)) {
|
||||||
|
PCInBlock = true;
|
||||||
|
}
|
||||||
// TODO: L219
|
// TODO: L219
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,6 +375,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
block.width, block.height);
|
block.width, block.height);
|
||||||
|
|
||||||
// Draw different background for selected instruction
|
// Draw different background for selected instruction
|
||||||
|
bool paintedSelected = false;
|
||||||
if (selected_instruction != RVA_INVALID) {
|
if (selected_instruction != RVA_INVALID) {
|
||||||
int y = block.y + (2 * charWidth) + (db.header_text.lines.size() * charHeight);
|
int y = block.y + (2 * charWidth) + (db.header_text.lines.size() * charHeight);
|
||||||
for (Instr &instr : db.instrs) {
|
for (Instr &instr : db.instrs) {
|
||||||
@ -379,9 +385,11 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
if (selected && traceCount) {
|
if (selected && traceCount) {
|
||||||
p.fillRect(QRect(block.x + charWidth, y, block.width - (10 + 2 * charWidth),
|
p.fillRect(QRect(block.x + charWidth, y, block.width - (10 + 2 * charWidth),
|
||||||
int(instr.text.lines.size()) * charHeight), disassemblyTracedSelectionColor);
|
int(instr.text.lines.size()) * charHeight), disassemblyTracedSelectionColor);
|
||||||
|
paintedSelected = true;
|
||||||
} else if (selected) {
|
} else if (selected) {
|
||||||
p.fillRect(QRect(block.x + charWidth, y, block.width - (10 + 2 * charWidth),
|
p.fillRect(QRect(block.x + charWidth, y, block.width - (10 + 2 * charWidth),
|
||||||
int(instr.text.lines.size()) * charHeight), disassemblySelectionColor);
|
int(instr.text.lines.size()) * charHeight), disassemblySelectionColor);
|
||||||
|
paintedSelected = true;
|
||||||
} else if (traceCount) {
|
} else if (traceCount) {
|
||||||
// Color depending on how often a sequence of code is executed
|
// Color depending on how often a sequence of code is executed
|
||||||
int exponent = 1;
|
int exponent = 1;
|
||||||
@ -398,11 +406,28 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
QColor(disassemblyTracedColor.red(),
|
QColor(disassemblyTracedColor.red(),
|
||||||
disassemblyTracedColor.green(),
|
disassemblyTracedColor.green(),
|
||||||
std::max(0, std::min(256, disassemblyTracedColor.blue() + colorDiff))));
|
std::max(0, std::min(256, disassemblyTracedColor.blue() + colorDiff))));
|
||||||
|
paintedSelected = true;
|
||||||
|
}
|
||||||
|
if (paintedSelected) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
y += int(instr.text.lines.size()) * charHeight;
|
y += int(instr.text.lines.size()) * charHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// highlight program counter
|
||||||
|
if (PCInBlock) {
|
||||||
|
int y = block.y + (2 * charWidth) + (db.header_text.lines.size() * charHeight);
|
||||||
|
for (Instr &instr : db.instrs) {
|
||||||
|
auto PC = instr.addr == PCAddr;
|
||||||
|
if (PC) {
|
||||||
|
p.fillRect(QRect(block.x + charWidth, y, block.width - (10 + 2 * charWidth),
|
||||||
|
int(instr.text.lines.size()) * charHeight), PCSelectionColor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
y += int(instr.text.lines.size()) * charHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render node text
|
// Render node text
|
||||||
auto x = block.x + (2 * charWidth);
|
auto x = block.x + (2 * charWidth);
|
||||||
@ -504,6 +529,7 @@ void DisassemblerGraphView::colorsUpdatedSlot()
|
|||||||
graphNodeColor = ConfigColor("gui.border");
|
graphNodeColor = ConfigColor("gui.border");
|
||||||
backgroundColor = ConfigColor("gui.background");
|
backgroundColor = ConfigColor("gui.background");
|
||||||
disassemblySelectionColor = ConfigColor("highlight");
|
disassemblySelectionColor = ConfigColor("highlight");
|
||||||
|
PCSelectionColor = ConfigColor("highlightPC");
|
||||||
|
|
||||||
jmpColor = ConfigColor("graph.trufae");
|
jmpColor = ConfigColor("graph.trufae");
|
||||||
brtrueColor = ConfigColor("graph.true");
|
brtrueColor = ConfigColor("graph.true");
|
||||||
|
@ -201,6 +201,7 @@ private:
|
|||||||
QColor disassemblyBackgroundColor;
|
QColor disassemblyBackgroundColor;
|
||||||
QColor disassemblySelectedBackgroundColor;
|
QColor disassemblySelectedBackgroundColor;
|
||||||
QColor disassemblySelectionColor;
|
QColor disassemblySelectionColor;
|
||||||
|
QColor PCSelectionColor;
|
||||||
QColor disassemblyTracedColor;
|
QColor disassemblyTracedColor;
|
||||||
QColor disassemblyTracedSelectionColor;
|
QColor disassemblyTracedSelectionColor;
|
||||||
QColor jmpColor;
|
QColor jmpColor;
|
||||||
|
@ -310,6 +310,7 @@ void DisassemblyWidget::highlightCurrentLine()
|
|||||||
QList<QTextEdit::ExtraSelection> extraSelections;
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
||||||
|
|
||||||
QColor highlightColor = ConfigColor("highlight");
|
QColor highlightColor = ConfigColor("highlight");
|
||||||
|
QColor highlightPCColor = ConfigColor("highlightPC");
|
||||||
QColor highlightWordColor = ConfigColor("highlightWord");
|
QColor highlightWordColor = ConfigColor("highlightWord");
|
||||||
highlightWordColor.setAlpha(128);
|
highlightWordColor.setAlpha(128);
|
||||||
QColor highlightWordCurrentLineColor = ConfigColor("gui.background");
|
QColor highlightWordCurrentLineColor = ConfigColor("gui.background");
|
||||||
@ -357,6 +358,30 @@ void DisassemblyWidget::highlightCurrentLine()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// highlight PC line
|
||||||
|
RVA PCAddr = Core()->getProgramCounterValue();
|
||||||
|
highlightSelection.cursor = cursor;
|
||||||
|
highlightSelection.cursor.movePosition(QTextCursor::Start);
|
||||||
|
if (PCAddr != RVA_INVALID) {
|
||||||
|
while (true) {
|
||||||
|
RVA lineOffset = readDisassemblyOffset(highlightSelection.cursor);
|
||||||
|
if (lineOffset == PCAddr) {
|
||||||
|
highlightSelection.format.setBackground(highlightPCColor);
|
||||||
|
highlightSelection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||||
|
highlightSelection.cursor.clearSelection();
|
||||||
|
extraSelections.append(highlightSelection);
|
||||||
|
} else if (lineOffset != RVA_INVALID && lineOffset > PCAddr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
highlightSelection.cursor.movePosition(QTextCursor::EndOfLine);
|
||||||
|
if (highlightSelection.cursor.atEnd()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightSelection.cursor.movePosition(QTextCursor::Down);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mDisasTextEdit->setExtraSelections(extraSelections);
|
mDisasTextEdit->setExtraSelections(extraSelections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user