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