mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 11:26:11 +00:00
Highlight Breakpoints and PC in decompiler (#1948)
This commit is contained in:
parent
58b44893f9
commit
4e84d1b502
@ -35,13 +35,32 @@ QList<QTextEdit::ExtraSelection> createSameWordsSelections(QPlainTextEdit *textE
|
||||
return selections;
|
||||
}
|
||||
|
||||
QTextEdit::ExtraSelection createLineHighlightSelection(const QTextCursor &cursor)
|
||||
|
||||
QTextEdit::ExtraSelection createLineHighlight(const QTextCursor &cursor, QColor highlightColor)
|
||||
{
|
||||
QColor highlightColor = ConfigColor("lineHighlight");
|
||||
QTextEdit::ExtraSelection highlightSelection;
|
||||
highlightSelection.cursor = cursor;
|
||||
highlightSelection.format.setBackground(highlightColor);
|
||||
highlightSelection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||
highlightSelection.cursor.clearSelection();
|
||||
return highlightSelection;
|
||||
}
|
||||
|
||||
QTextEdit::ExtraSelection createLineHighlightSelection(const QTextCursor &cursor)
|
||||
{
|
||||
QColor highlightColor = ConfigColor("lineHighlight");
|
||||
return createLineHighlight(cursor, highlightColor);
|
||||
}
|
||||
|
||||
|
||||
QTextEdit::ExtraSelection createLineHighlightPC(const QTextCursor &cursor)
|
||||
{
|
||||
QColor highlightColor = ConfigColor("highlightPC");
|
||||
return createLineHighlight(cursor, highlightColor);
|
||||
}
|
||||
|
||||
QTextEdit::ExtraSelection createLineHighlightBP(const QTextCursor &cursor)
|
||||
{
|
||||
QColor highlightColor = ConfigColor("gui.breakpoint_background");
|
||||
return createLineHighlight(cursor, highlightColor);
|
||||
}
|
@ -6,7 +6,41 @@
|
||||
class QPlainTextEdit;
|
||||
class QString;
|
||||
|
||||
/**
|
||||
* @brief createSameWordsSelections se
|
||||
* @param textEdit
|
||||
* @param word
|
||||
* @return
|
||||
*/
|
||||
QList<QTextEdit::ExtraSelection> createSameWordsSelections(QPlainTextEdit *textEdit, const QString &word);
|
||||
|
||||
/**
|
||||
* @brief createLineHighlight
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @param highlightColor - the color to be used for highlighting. The color is decided by the callee for different usages (BP, PC, Current line, ...)
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlight(const QTextCursor &cursor, QColor highlightColor);
|
||||
|
||||
/**
|
||||
* @brief This function responsible to highlight the currently selected line
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlightSelection(const QTextCursor &cursor);
|
||||
|
||||
/**
|
||||
* @brief This function responsible to highlight the program counter line
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlightPC(const QTextCursor &cursor);
|
||||
|
||||
/**
|
||||
* @brief This function responsible to highlight a line with breakpoint
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlightBP(const QTextCursor &cursor);
|
||||
|
||||
#endif //CUTTER_SELECTIONHIGHLIGHT_H
|
||||
|
@ -1802,6 +1802,19 @@ QList<RVA> CutterCore::getBreakpointsAddresses()
|
||||
return bpAddresses;
|
||||
}
|
||||
|
||||
QList<RVA> CutterCore::getBreakpointsInFunction(RVA funcAddr)
|
||||
{
|
||||
QList<RVA> allBreakpoints = getBreakpointsAddresses();
|
||||
QList<RVA> functionBreakpoints;
|
||||
|
||||
// Use std manipulations to take only the breakpoints that belong to this function
|
||||
std::copy_if(allBreakpoints.begin(),
|
||||
allBreakpoints.end(),
|
||||
std::back_inserter(functionBreakpoints),
|
||||
[this, funcAddr](RVA BPadd) { return getFunctionStart(BPadd) == funcAddr; });
|
||||
return functionBreakpoints;
|
||||
}
|
||||
|
||||
bool CutterCore::isBreakpoint(const QList<RVA> &breakpoints, RVA addr)
|
||||
{
|
||||
return breakpoints.contains(addr);
|
||||
|
@ -327,6 +327,11 @@ public:
|
||||
void disableBreakpoint(RVA addr);
|
||||
bool isBreakpoint(const QList<RVA> &breakpoints, RVA addr);
|
||||
QList<RVA> getBreakpointsAddresses();
|
||||
|
||||
/**
|
||||
* @brief Get all breakpoinst that are belong to a functions at this address
|
||||
*/
|
||||
QList<RVA> getBreakpointsInFunction(RVA funcAddr);
|
||||
QString getActiveDebugPlugin();
|
||||
QStringList getDebugPlugins();
|
||||
void setDebugPlugin(QString plugin);
|
||||
|
@ -32,6 +32,7 @@ DecompilerWidget::DecompilerWidget(MainWindow *main, QAction *action) :
|
||||
|
||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
||||
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
||||
connect(Core(), SIGNAL(registersChanged()), this, SLOT(highlightPC()));
|
||||
|
||||
decompiledFunctionAddr = RVA_INVALID;
|
||||
decompilerWasBusy = false;
|
||||
@ -158,6 +159,8 @@ void DecompilerWidget::doRefresh(RVA addr)
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear all selections since we just refreshed
|
||||
ui->textEdit->setExtraSelections({});
|
||||
decompiledFunctionAddr = Core()->getFunctionStart(addr);
|
||||
dec->decompileAt(addr);
|
||||
if (dec->isRunning()) {
|
||||
@ -173,6 +176,18 @@ void DecompilerWidget::refreshDecompiler()
|
||||
doRefresh();
|
||||
}
|
||||
|
||||
QTextCursor DecompilerWidget::getCursorForAddress(RVA addr)
|
||||
{
|
||||
size_t pos = code.PositionForOffset(addr);
|
||||
if (pos == SIZE_MAX || pos == 0) {
|
||||
return QTextCursor();
|
||||
}
|
||||
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
cursor.setPosition(pos);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
void DecompilerWidget::decompilationFinished(AnnotatedCode code)
|
||||
{
|
||||
ui->progressLabel->setVisible(false);
|
||||
@ -188,6 +203,8 @@ void DecompilerWidget::decompilationFinished(AnnotatedCode code)
|
||||
ui->textEdit->setPlainText(code.code);
|
||||
connectCursorPositionChanged(false);
|
||||
updateCursorPosition();
|
||||
highlightPC();
|
||||
highlightBreakpoints();
|
||||
}
|
||||
|
||||
if (decompilerWasBusy) {
|
||||
@ -284,6 +301,8 @@ void DecompilerWidget::updateSelection()
|
||||
extraSelections.append(createSameWordsSelections(ui->textEdit, searchString));
|
||||
|
||||
ui->textEdit->setExtraSelections(extraSelections);
|
||||
// Highlight PC after updating the selected line
|
||||
highlightPC();
|
||||
mCtxMenu->setCurHighlightedWord(searchString);
|
||||
}
|
||||
|
||||
@ -327,3 +346,46 @@ bool DecompilerWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
|
||||
return MemoryDockWidget::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
|
||||
void DecompilerWidget::highlightPC()
|
||||
{
|
||||
RVA PCAddress = Core()->getProgramCounterValue();
|
||||
if (PCAddress == RVA_INVALID || (Core()->getFunctionStart(PCAddress) != decompiledFunctionAddr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTextCursor cursor = getCursorForAddress(PCAddress);
|
||||
if (!cursor.isNull()) {
|
||||
colorLine(createLineHighlightPC(cursor));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DecompilerWidget::highlightBreakpoints()
|
||||
{
|
||||
|
||||
QList<RVA> functionBreakpoints = Core()->getBreakpointsInFunction(decompiledFunctionAddr);
|
||||
QTextCursor cursor;
|
||||
foreach(auto &bp, functionBreakpoints) {
|
||||
if (bp == RVA_INVALID) {
|
||||
continue;;
|
||||
}
|
||||
|
||||
cursor = getCursorForAddress(bp);
|
||||
if (!cursor.isNull()) {
|
||||
// Use a Block formatting since these lines are not updated frequently as selections and PC
|
||||
QTextBlockFormat f;
|
||||
f.setBackground(ConfigColor("gui.breakpoint_background"));
|
||||
cursor.setBlockFormat(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DecompilerWidget::colorLine(QTextEdit::ExtraSelection extraSelection)
|
||||
{
|
||||
QList<QTextEdit::ExtraSelection> extraSelections = ui->textEdit->extraSelections();
|
||||
extraSelections.append(extraSelection);
|
||||
ui->textEdit->setExtraSelections(extraSelections);
|
||||
return true;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef DECOMPILERWIDGET_H
|
||||
#define DECOMPILERWIDGET_H
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <memory>
|
||||
|
||||
#include "core/Cutter.h"
|
||||
@ -29,6 +30,7 @@ public:
|
||||
public slots:
|
||||
void showDisasContextMenu(const QPoint &pt);
|
||||
|
||||
void highlightPC();
|
||||
private slots:
|
||||
void fontsUpdatedSlot();
|
||||
void colorsUpdatedSlot();
|
||||
@ -77,6 +79,26 @@ private:
|
||||
* referenced from the address under cursor
|
||||
*/
|
||||
void seekToReference();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Cursor for a location as close as possible to the given address
|
||||
* @param addr - an address in the decompiled function
|
||||
* @return a Cursor object for the given address
|
||||
*/
|
||||
QTextCursor getCursorForAddress(RVA addr);
|
||||
|
||||
/**
|
||||
* @brief Append a highlighted line to the TextEdit
|
||||
* @param extraSelection - an ExtraSelection object colored with the appropriate color
|
||||
* @return True on success, otherwise False
|
||||
*/
|
||||
bool colorLine(QTextEdit::ExtraSelection extraSelection);
|
||||
|
||||
/**
|
||||
* @brief This function responsible to highlight all the breakpoints in the decompiler view.
|
||||
* It will also run when a breakpoint is added, removed or modified.
|
||||
*/
|
||||
void highlightBreakpoints();
|
||||
};
|
||||
|
||||
#endif // DECOMPILERWIDGET_H
|
||||
|
Loading…
Reference in New Issue
Block a user