mirror of
https://github.com/rizinorg/cutter.git
synced 2025-02-22 14:43:46 +00:00
UI Improvemetnts + graph.offset implementation (#612)
* Add getBreakpointsAddresses to list breakpoints offsets * Add breakpoint highligthing and improve of disassembly UIs * Improve dialogs and positions * Add graph,offset option to preference * Tiny text fix * Updated radare2 sumodule
This commit is contained in:
parent
4e3d857239
commit
bf07f2a002
2
radare2
2
radare2
@ -1 +1 @@
|
|||||||
Subproject commit c9ec8b54b9ba32ba6712f319825f8d032e573e68
|
Subproject commit 404e4a1b74df7941c3ff7511f5396e1e1736ce37
|
@ -1078,6 +1078,25 @@ QList<BreakpointDescription> CutterCore::getBreakpoints()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QList<RVA> CutterCore::getBreakpointsAddresses()
|
||||||
|
{
|
||||||
|
QList<BreakpointDescription> bps = getBreakpoints();
|
||||||
|
BreakpointDescription bp;
|
||||||
|
QList<RVA> bpAddresses;
|
||||||
|
foreach (bp, bps)
|
||||||
|
{
|
||||||
|
bpAddresses << bp.addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bpAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CutterCore::isBreakpoint(QList<RVA> breakpoints, RVA addr)
|
||||||
|
{
|
||||||
|
return breakpoints.contains(addr);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonDocument CutterCore::getBacktrace()
|
QJsonDocument CutterCore::getBacktrace()
|
||||||
{
|
{
|
||||||
return cmdj("dbtj");
|
return cmdj("dbtj");
|
||||||
|
@ -518,6 +518,8 @@ public:
|
|||||||
void delAllBreakpoints();
|
void delAllBreakpoints();
|
||||||
void enableBreakpoint(RVA addr);
|
void enableBreakpoint(RVA addr);
|
||||||
void disableBreakpoint(RVA addr);
|
void disableBreakpoint(RVA addr);
|
||||||
|
bool isBreakpoint(QList<RVA> breakpoints, RVA addr);
|
||||||
|
QList<RVA> getBreakpointsAddresses();
|
||||||
QString getActiveDebugPlugin();
|
QString getActiveDebugPlugin();
|
||||||
QStringList getDebugPlugins();
|
QStringList getDebugPlugins();
|
||||||
void setDebugPlugin(QString plugin);
|
void setDebugPlugin(QString plugin);
|
||||||
|
@ -206,8 +206,6 @@ border-top: 0px;
|
|||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionLock"/>
|
<addaction name="actionLock"/>
|
||||||
<addaction name="actionTabs_on_Top"/>
|
<addaction name="actionTabs_on_Top"/>
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="actionPreferences"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -222,6 +220,8 @@ border-top: 0px;
|
|||||||
<addaction name="actionSearch"/>
|
<addaction name="actionSearch"/>
|
||||||
<addaction name="actionUndoSeek"/>
|
<addaction name="actionUndoSeek"/>
|
||||||
<addaction name="actionRedoSeek"/>
|
<addaction name="actionRedoSeek"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionPreferences"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="addDebugWidgets">
|
<widget class="QMenu" name="addDebugWidgets">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>296</width>
|
<width>506</width>
|
||||||
<height>310</height>
|
<height>310</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>545</width>
|
<width>545</width>
|
||||||
<height>450</height>
|
<height>526</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -17,7 +17,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="asmOptionsTab">
|
<widget class="QTabWidget" name="asmOptionsTab">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="asmStyleTab">
|
<widget class="QWidget" name="asmStyleTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
@ -25,6 +25,7 @@ GraphOptionsWidget::~GraphOptionsWidget() {}
|
|||||||
|
|
||||||
void GraphOptionsWidget::updateOptionsFromVars()
|
void GraphOptionsWidget::updateOptionsFromVars()
|
||||||
{
|
{
|
||||||
|
qhelpers::setCheckedWithoutSignals(ui->graphOffsetCheckBox, Config()->getConfigBool("graph.offset"));
|
||||||
ui->maxColsSpinBox->blockSignals(true);
|
ui->maxColsSpinBox->blockSignals(true);
|
||||||
ui->maxColsSpinBox->setValue(Config()->getGraphBlockMaxChars());
|
ui->maxColsSpinBox->setValue(Config()->getGraphBlockMaxChars());
|
||||||
ui->maxColsSpinBox->blockSignals(false);
|
ui->maxColsSpinBox->blockSignals(false);
|
||||||
@ -44,3 +45,8 @@ void GraphOptionsWidget::on_maxColsSpinBox_valueChanged(int value)
|
|||||||
triggerOptionsChanged();
|
triggerOptionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphOptionsWidget::on_graphOffsetCheckBox_toggled(bool checked)
|
||||||
|
{
|
||||||
|
Config()->setConfig("graph.offset", checked);
|
||||||
|
triggerOptionsChanged();
|
||||||
|
}
|
||||||
|
@ -31,6 +31,7 @@ private slots:
|
|||||||
void updateOptionsFromVars();
|
void updateOptionsFromVars();
|
||||||
|
|
||||||
void on_maxColsSpinBox_valueChanged(int value);
|
void on_maxColsSpinBox_valueChanged(int value);
|
||||||
|
void on_graphOffsetCheckBox_toggled(bool checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,28 +13,51 @@
|
|||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Graph</string>
|
<string>Graph</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<widget class="QLabel" name="maxColsLabel">
|
||||||
<item row="0" column="0">
|
<property name="geometry">
|
||||||
<widget class="QLabel" name="maxColsLabel">
|
<rect>
|
||||||
<property name="text">
|
<x>30</x>
|
||||||
<string>Maximum Line Length:</string>
|
<y>10</y>
|
||||||
</property>
|
<width>141</width>
|
||||||
</widget>
|
<height>18</height>
|
||||||
</item>
|
</rect>
|
||||||
<item row="0" column="1">
|
</property>
|
||||||
<widget class="QSpinBox" name="maxColsSpinBox">
|
<property name="text">
|
||||||
<property name="minimum">
|
<string>Maximum Line Length:</string>
|
||||||
<number>10</number>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="maximum">
|
<widget class="QSpinBox" name="maxColsSpinBox">
|
||||||
<number>999999999</number>
|
<property name="geometry">
|
||||||
</property>
|
<rect>
|
||||||
<property name="singleStep">
|
<x>190</x>
|
||||||
<number>5</number>
|
<y>10</y>
|
||||||
</property>
|
<width>104</width>
|
||||||
</widget>
|
<height>23</height>
|
||||||
</item>
|
</rect>
|
||||||
</layout>
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="graphOffsetCheckBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>44</y>
|
||||||
|
<width>162</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Show offsets (graph.offset) </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
@ -22,7 +22,7 @@ static const QHash<QString, QVariant> asmOptions = {
|
|||||||
{ "asm.flags.offset", false },
|
{ "asm.flags.offset", false },
|
||||||
{ "asm.emu", false },
|
{ "asm.emu", false },
|
||||||
{ "asm.cmt.right", true },
|
{ "asm.cmt.right", true },
|
||||||
{ "asm.cmt.col", 70 },
|
{ "asm.cmt.col", 35 },
|
||||||
{ "asm.var.summary", false },
|
{ "asm.var.summary", false },
|
||||||
{ "asm.bytes", false },
|
{ "asm.bytes", false },
|
||||||
{ "asm.size", false },
|
{ "asm.size", false },
|
||||||
@ -37,7 +37,9 @@ static const QHash<QString, QVariant> asmOptions = {
|
|||||||
{ "asm.var.subonly", true },
|
{ "asm.var.subonly", true },
|
||||||
{ "asm.tabs", 5 },
|
{ "asm.tabs", 5 },
|
||||||
{ "asm.tabs.off", 5 },
|
{ "asm.tabs.off", 5 },
|
||||||
{ "esil.breakoninvalid", true }
|
{ "asm.marks", false },
|
||||||
|
{ "esil.breakoninvalid", true },
|
||||||
|
{ "graph.offset", false}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -118,7 +120,7 @@ void Configuration::loadDefaultTheme()
|
|||||||
setColor("gui.cflow", QColor(0, 0, 0));
|
setColor("gui.cflow", QColor(0, 0, 0));
|
||||||
setColor("gui.dataoffset", QColor(0, 0, 0));
|
setColor("gui.dataoffset", QColor(0, 0, 0));
|
||||||
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, 150));
|
||||||
setColor("highlightWord", QColor(210, 210, 255));
|
setColor("highlightWord", QColor(210, 210, 255));
|
||||||
// RIP line selection in debug
|
// RIP line selection in debug
|
||||||
setColor("highlightPC", QColor(214, 255, 210));
|
setColor("highlightPC", QColor(214, 255, 210));
|
||||||
@ -135,6 +137,7 @@ void Configuration::loadDefaultTheme()
|
|||||||
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));
|
||||||
|
setColor("gui.breakpoint_background", QColor(233, 143, 143));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Configuration::loadBaseDark()
|
void Configuration::loadBaseDark()
|
||||||
@ -176,6 +179,7 @@ void Configuration::loadBaseDark()
|
|||||||
setColor("gui.navbar.empty", QColor(100, 100, 100));
|
setColor("gui.navbar.empty", QColor(100, 100, 100));
|
||||||
// RIP line selection in debug
|
// RIP line selection in debug
|
||||||
setColor("highlightPC", QColor(87, 26, 7));
|
setColor("highlightPC", QColor(87, 26, 7));
|
||||||
|
setColor("gui.breakpoint_background", QColor(140, 76, 76));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Configuration::loadDarkTheme()
|
void Configuration::loadDarkTheme()
|
||||||
@ -187,15 +191,16 @@ void Configuration::loadDarkTheme()
|
|||||||
// Disassembly nodes background
|
// Disassembly nodes background
|
||||||
setColor("gui.alt_background", QColor(28, 31, 36));
|
setColor("gui.alt_background", QColor(28, 31, 36));
|
||||||
// Disassembly nodes background when selected
|
// Disassembly nodes background when selected
|
||||||
setColor("gui.disass_selected", QColor(44, 53, 54));
|
setColor("gui.disass_selected", QColor(31, 34, 40));
|
||||||
// Disassembly line selected
|
// Disassembly line selected
|
||||||
setColor("highlight", QColor(21, 29, 29));
|
setColor("highlight", QColor(21, 29, 29, 150));
|
||||||
setColor("highlightWord", QColor(100, 100, 100));
|
setColor("highlightWord", QColor(100, 100, 100));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QFont Configuration::getFont() const
|
const QFont Configuration::getFont() const
|
||||||
{
|
{
|
||||||
QFont font = s.value("font", QFont("Inconsolata", 12)).value<QFont>();
|
QFont font = s.value("font", QFont("Inconsolata", 11)).value<QFont>();
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,6 +332,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
p.setBrush(Qt::gray);
|
p.setBrush(Qt::gray);
|
||||||
p.drawRect(block.x, block.y, block.width, block.height);
|
p.drawRect(block.x, block.y, block.width, block.height);
|
||||||
|
|
||||||
|
breakpoints = Core()->getBreakpointsAddresses();
|
||||||
|
|
||||||
// Render node
|
// Render node
|
||||||
DisassemblyBlock &db = disassembly_blocks[block.entry];
|
DisassemblyBlock &db = disassembly_blocks[block.entry];
|
||||||
@ -350,6 +351,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
if ((instr.addr <= PCAddr) && (PCAddr <= instr.addr + instr.size)) {
|
if ((instr.addr <= PCAddr) && (PCAddr <= instr.addr + instr.size)) {
|
||||||
PCInBlock = true;
|
PCInBlock = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: L219
|
// TODO: L219
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,12 +361,13 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
} else if (db.indirectcall) {
|
} else if (db.indirectcall) {
|
||||||
p.setBrush(indirectcallShadowColor);
|
p.setBrush(indirectcallShadowColor);
|
||||||
} else {
|
} else {
|
||||||
p.setBrush(QColor(0, 0, 0, 128));
|
p.setBrush(QColor(0, 0, 0, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
p.drawRect(block.x + 4, block.y + 4,
|
// Node's shadow effect
|
||||||
block.width + 4, block.height + 4);
|
p.drawRect(block.x + 2, block.y + 2,
|
||||||
p.setPen(graphNodeColor);
|
block.width, block.height);
|
||||||
|
p.setPen(QPen(graphNodeColor, 1));
|
||||||
|
|
||||||
if (block_selected) {
|
if (block_selected) {
|
||||||
p.setBrush(disassemblySelectedBackgroundColor);
|
p.setBrush(disassemblySelectedBackgroundColor);
|
||||||
@ -436,6 +439,14 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
|
|||||||
y += charHeight;
|
y += charHeight;
|
||||||
}
|
}
|
||||||
for (Instr &instr : db.instrs) {
|
for (Instr &instr : db.instrs) {
|
||||||
|
if (Core()->isBreakpoint(breakpoints, instr.addr)) {
|
||||||
|
p.fillRect(QRect(block.x + charWidth, y, block.width - (10 + 2 * charWidth),
|
||||||
|
int(instr.text.lines.size()) * charHeight), ConfigColor("gui.breakpoint_background"));
|
||||||
|
if (instr.addr == selected_instruction) {
|
||||||
|
p.fillRect(QRect(block.x + charWidth, y, block.width - (10 + 2 * charWidth),
|
||||||
|
int(instr.text.lines.size()) * charHeight), disassemblySelectionColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto &line : instr.text.lines) {
|
for (auto &line : instr.text.lines) {
|
||||||
int rectSize = qRound(charWidth);
|
int rectSize = qRound(charWidth);
|
||||||
if (rectSize % 2) {
|
if (rectSize % 2) {
|
||||||
|
@ -197,6 +197,7 @@ private:
|
|||||||
void seekInstruction(bool previous_instr);
|
void seekInstruction(bool previous_instr);
|
||||||
CutterSeekableWidget *seekable = nullptr;
|
CutterSeekableWidget *seekable = nullptr;
|
||||||
QList<QShortcut *> shortcuts;
|
QList<QShortcut *> shortcuts;
|
||||||
|
QList<RVA> breakpoints;
|
||||||
|
|
||||||
QColor disassemblyBackgroundColor;
|
QColor disassemblyBackgroundColor;
|
||||||
QColor disassemblySelectedBackgroundColor;
|
QColor disassemblySelectedBackgroundColor;
|
||||||
|
@ -209,6 +209,7 @@ void DisassemblyWidget::refreshDisasm(RVA offset)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
breakpoints = Core()->getBreakpointsAddresses();
|
||||||
int horizontalScrollValue = mDisasTextEdit->horizontalScrollBar()->value();
|
int horizontalScrollValue = mDisasTextEdit->horizontalScrollBar()->value();
|
||||||
mDisasTextEdit->setLockScroll(true); // avoid flicker
|
mDisasTextEdit->setLockScroll(true); // avoid flicker
|
||||||
|
|
||||||
@ -224,14 +225,21 @@ void DisassemblyWidget::refreshDisasm(RVA offset)
|
|||||||
|
|
||||||
mDisasTextEdit->document()->clear();
|
mDisasTextEdit->document()->clear();
|
||||||
QTextCursor cursor(mDisasTextEdit->document());
|
QTextCursor cursor(mDisasTextEdit->document());
|
||||||
|
QTextBlockFormat regular = cursor.blockFormat();
|
||||||
for (DisassemblyLine line : disassemblyLines) {
|
for (DisassemblyLine line : disassemblyLines) {
|
||||||
if (line.offset < topOffset) { // overflow
|
if (line.offset < topOffset) { // overflow
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cursor.insertHtml(line.text);
|
cursor.insertHtml(line.text);
|
||||||
|
if(Core()->isBreakpoint(breakpoints,line.offset)) {
|
||||||
|
QTextBlockFormat f;
|
||||||
|
f.setBackground(ConfigColor("gui.breakpoint_background"));
|
||||||
|
cursor.setBlockFormat(f);
|
||||||
|
}
|
||||||
auto a = new DisassemblyTextBlockUserData(line);
|
auto a = new DisassemblyTextBlockUserData(line);
|
||||||
cursor.block().setUserData(a);
|
cursor.block().setUserData(a);
|
||||||
cursor.insertBlock();
|
cursor.insertBlock();
|
||||||
|
cursor.setBlockFormat(regular);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!disassemblyLines.isEmpty()) {
|
if (!disassemblyLines.isEmpty()) {
|
||||||
|
@ -61,6 +61,8 @@ private:
|
|||||||
RVA readDisassemblyOffset(QTextCursor tc);
|
RVA readDisassemblyOffset(QTextCursor tc);
|
||||||
bool eventFilter(QObject *obj, QEvent *event);
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
|
||||||
|
QList<RVA> breakpoints;
|
||||||
|
|
||||||
void setupFonts();
|
void setupFonts();
|
||||||
void setupColors();
|
void setupColors();
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ void QuickFilterView::clearFilter()
|
|||||||
|
|
||||||
void QuickFilterView::closeFilter()
|
void QuickFilterView::closeFilter()
|
||||||
{
|
{
|
||||||
|
ui->filterLineEdit->setText("");
|
||||||
hide();
|
hide();
|
||||||
emit filterClosed();
|
emit filterClosed();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user