Adding Labels to Graph Blocks in Disassembly (#2482)

This commit is contained in:
Pulak Malhotra 2020-11-29 20:11:13 +05:30 committed by GitHub
parent 79a323489a
commit ef9b1328f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 239 additions and 160 deletions

View File

@ -780,3 +780,13 @@ bool Configuration::getOutputRedirectionEnabled() const
{ {
return outputRedirectEnabled; return outputRedirectEnabled;
} }
bool Configuration::getGraphBlockEntryOffset()
{
return s.value("graphBlockEntryOffset", true).value<bool>();
}
void Configuration::setGraphBlockEntryOffset(bool enabled)
{
s.setValue("graphBlockEntryOffset", enabled);
}

View File

@ -132,7 +132,7 @@ public:
QString getColorTheme() const { return s.value("theme", "cutter").toString(); } QString getColorTheme() const { return s.value("theme", "cutter").toString(); }
void setColorTheme(const QString &theme); void setColorTheme(const QString &theme);
/** /**
* @brief Change current color theme if it doesnt't much native theme's darkness. * @brief Change current color theme if it doesn't much native theme's darkness.
*/ */
void adjustColorThemeDarkness(); void adjustColorThemeDarkness();
int colorThemeDarkness(const QString &colorTheme) const; int colorThemeDarkness(const QString &colorTheme) const;
@ -187,9 +187,21 @@ public:
QPoint getGraphBlockSpacing(); QPoint getGraphBlockSpacing();
QPoint getGraphEdgeSpacing(); QPoint getGraphEdgeSpacing();
/**
* @brief Gets whether the entry offset of each block has to be displayed or not
* @return true if the entry offset has to be displayed, false otherwise
*/
bool getGraphBlockEntryOffset();
/**
* @brief Enable or disable the displaying of the entry offset in each graph block
* @param enabled set this to true for displaying the entry offset in each graph block, false otherwise
*/
void setGraphBlockEntryOffset(bool enabled);
/** /**
* @brief Enable or disable Cutter output redirection. * @brief Enable or disable Cutter output redirection.
* Output redirection state can only be changed early during Cutter initalization. * Output redirection state can only be changed early during Cutter initialization.
* Changing it later will have no effect * Changing it later will have no effect
* @param enabled set this to false for disabling output redirection * @param enabled set this to false for disabling output redirection
*/ */

View File

@ -15,11 +15,13 @@ GraphOptionsWidget::GraphOptionsWidget(PreferencesDialog *dialog)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->checkTransparent->setChecked(Config()->getBitmapTransparentState()); ui->checkTransparent->setChecked(Config()->getBitmapTransparentState());
ui->blockEntryCheckBox->setChecked(Config()->getGraphBlockEntryOffset());
ui->bitmapGraphScale->setValue(Config()->getBitmapExportScaleFactor()*100.0); ui->bitmapGraphScale->setValue(Config()->getBitmapExportScaleFactor()*100.0);
updateOptionsFromVars(); updateOptionsFromVars();
connect<void(QDoubleSpinBox::*)(double)>(ui->bitmapGraphScale, (&QDoubleSpinBox::valueChanged), this, &GraphOptionsWidget::bitmapGraphScaleValueChanged); connect<void(QDoubleSpinBox::*)(double)>(ui->bitmapGraphScale, (&QDoubleSpinBox::valueChanged), this, &GraphOptionsWidget::bitmapGraphScaleValueChanged);
connect(ui->checkTransparent, &QCheckBox::stateChanged, this, &GraphOptionsWidget::checkTransparentStateChanged); connect(ui->checkTransparent, &QCheckBox::stateChanged, this, &GraphOptionsWidget::checkTransparentStateChanged);
connect(ui->blockEntryCheckBox, &QCheckBox::stateChanged, this, &GraphOptionsWidget::checkGraphBlockEntryOffsetChanged);
connect(Core(), &CutterCore::graphOptionsChanged, this, &GraphOptionsWidget::updateOptionsFromVars); connect(Core(), &CutterCore::graphOptionsChanged, this, &GraphOptionsWidget::updateOptionsFromVars);
QSpinBox* graphSpacingWidgets[] = { QSpinBox* graphSpacingWidgets[] = {
@ -89,3 +91,8 @@ void GraphOptionsWidget::layoutSpacingChanged()
triggerOptionsChanged(); triggerOptionsChanged();
} }
void GraphOptionsWidget::checkGraphBlockEntryOffsetChanged(bool checked)
{
Config()->setGraphBlockEntryOffset(checked);
triggerOptionsChanged();
}

View File

@ -34,6 +34,7 @@ private slots:
void checkTransparentStateChanged(int checked); void checkTransparentStateChanged(int checked);
void bitmapGraphScaleValueChanged(double value); void bitmapGraphScaleValueChanged(double value);
void checkGraphBlockEntryOffsetChanged(bool checked);
void layoutSpacingChanged(); void layoutSpacingChanged();
}; };

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>403</width> <width>742</width>
<height>296</height> <height>698</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -15,164 +15,206 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
<layout class="QFormLayout" name="formLayout"> <layout class="QVBoxLayout" name="verticalLayout_8">
<item row="0" column="0"> <item>
<widget class="QLabel" name="maxColsLabel"> <widget class="QGroupBox" name="GraphBlockOptions">
<property name="text"> <property name="title">
<string>Maximum Line Length:</string> <string>Graph Block Options </string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="topMargin">
<number>24</number>
</property>
<item>
<widget class="QCheckBox" name="blockEntryCheckBox">
<property name="toolTip">
<string>The offset of the first instruction of a graph block is shown in the header of the respective graph block</string>
</property>
<property name="text">
<string>Show offset of the first instruction in each graph block</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="graphOffsetCheckBox">
<property name="text">
<string>Show offset for each instruction (graph.offset)</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="maxColsLabel">
<property name="text">
<string>Maximum Line Length:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="maxColsSpinBox">
<property name="minimum">
<number>25</number>
</property>
<property name="maximum">
<number>256</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item>
<widget class="QSpinBox" name="maxColsSpinBox"> <widget class="QGroupBox" name="LayoutBlock">
<property name="minimum"> <property name="title">
<number>25</number> <string>Graph Layout Options</string>
</property>
<property name="maximum">
<number>256</number>
</property>
<property name="value">
<number>100</number>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QSpinBox" name="horizontalBlockSpacing">
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Vertical</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="horizontalEdgeSpacing">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Horizontal</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="verticalEdgeSpacing">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="verticalBlockSpacing">
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>40</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Block spacing:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Edge spacing</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item>
<widget class="QLabel" name="bitmapGraphScaleLabel"> <widget class="QGroupBox" name="BitmapExportBlock">
<property name="text"> <property name="title">
<string>Graph Bitmap Export Scale: </string> <string>Bitmap Export Options</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="bitmapGraphScale">
<property name="suffix">
<string>%</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="minimum">
<double>100.000000000000000</double>
</property>
<property name="maximum">
<double>30000.000000000000000</double>
</property>
<property name="singleStep">
<double>50.000000000000000</double>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<property name="topMargin">
<number>24</number>
</property>
<item>
<widget class="QCheckBox" name="checkTransparent">
<property name="text">
<string>Export Transparent Bitmap Graphs</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="bitmapGraphScaleLabel">
<property name="text">
<string>Graph Bitmap Export Scale: </string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="bitmapGraphScale">
<property name="suffix">
<string>%</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="minimum">
<double>100.000000000000000</double>
</property>
<property name="maximum">
<double>30000.000000000000000</double>
</property>
<property name="singleStep">
<double>50.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QCheckBox" name="graphOffsetCheckBox">
<property name="text">
<string>Show offsets (graph.offset)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkTransparent">
<property name="text">
<string>Export Transparent Bitmap Graphs</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Layout</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Horizontal</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Block spacing</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Edge spacing</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="horizontalBlockSpacing">
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="verticalBlockSpacing">
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>40</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="horizontalEdgeSpacing">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="verticalEdgeSpacing">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>400</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Vertical</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
@ -189,14 +231,15 @@
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>maxColsSpinBox</tabstop> <tabstop>blockEntryCheckBox</tabstop>
<tabstop>bitmapGraphScale</tabstop>
<tabstop>graphOffsetCheckBox</tabstop> <tabstop>graphOffsetCheckBox</tabstop>
<tabstop>checkTransparent</tabstop> <tabstop>maxColsSpinBox</tabstop>
<tabstop>horizontalBlockSpacing</tabstop> <tabstop>horizontalBlockSpacing</tabstop>
<tabstop>verticalBlockSpacing</tabstop> <tabstop>verticalBlockSpacing</tabstop>
<tabstop>horizontalEdgeSpacing</tabstop> <tabstop>horizontalEdgeSpacing</tabstop>
<tabstop>verticalEdgeSpacing</tabstop> <tabstop>verticalEdgeSpacing</tabstop>
<tabstop>checkTransparent</tabstop>
<tabstop>bitmapGraphScale</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -235,6 +235,11 @@ void DisassemblerGraphView::loadCurrentGraph()
GraphBlock gb; GraphBlock gb;
gb.entry = block_entry; gb.entry = block_entry;
db.entry = block_entry; db.entry = block_entry;
if (Config()->getGraphBlockEntryOffset()) {
// QColor(0,0,0,0) is transparent
db.header_text = Text("[" + RAddressString(db.entry) + "]", ConfigColor("offset"),
QColor(0, 0, 0, 0));
}
db.true_path = RVA_INVALID; db.true_path = RVA_INVALID;
db.false_path = RVA_INVALID; db.false_path = RVA_INVALID;
if (block_fail) { if (block_fail) {
@ -435,7 +440,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block,
qreal highlightWidth = tokenWidth; qreal highlightWidth = tokenWidth;
if (charWidth * 3 + widthBefore + tokenWidth >= block.width - (10 + padding)) { if (charWidth * 3 + widthBefore + tokenWidth >= block.width - (10 + padding)) {
highlightWidth = block.width - widthBefore - (10 + 2 * padding); highlightWidth = block.width - widthBefore - (10 + 2 * padding);
} }
QColor selectionColor = ConfigColor("wordHighlight"); QColor selectionColor = ConfigColor("wordHighlight");
@ -536,8 +541,8 @@ RVA DisassemblerGraphView::getAddrForMouseEvent(GraphBlock &block, QPoint *point
int text_point_y = point->y() - off_y; int text_point_y = point->y() - off_y;
int mouse_row = text_point_y / charHeight; int mouse_row = text_point_y / charHeight;
int cur_row = static_cast<int>(db.header_text.lines.size()); // If mouse coordinate is in header region or margin above
if (mouse_row < cur_row) { if (mouse_row < 0) {
return db.entry; return db.entry;
} }
@ -561,10 +566,11 @@ DisassemblerGraphView::Instr *DisassemblerGraphView::getInstrForMouseEvent(
int text_point_y = point->y() - off_y; int text_point_y = point->y() - off_y;
int mouse_row = text_point_y / charHeight; int mouse_row = text_point_y / charHeight;
int cur_row = static_cast<int>(db.header_text.lines.size()); // Row in actual text
int cur_row = 0;
for (Instr &instr : db.instrs) { for (Instr &instr : db.instrs) {
if (mouse_row < cur_row + (int)instr.text.lines.size()) { if (mouse_row < cur_row + (int) instr.text.lines.size()) {
return &instr; return &instr;
} }
cur_row += instr.text.lines.size(); cur_row += instr.text.lines.size();