From 5c9dec657d68e3a788ffd92c1dce37c5db59a37a Mon Sep 17 00:00:00 2001 From: "Thomas (nezza-_-) Roth" Date: Fri, 8 Dec 2017 00:41:15 +0100 Subject: [PATCH] Fix & extend CodeGraphic. Adds symbols, strings, etc (#187) * Fix & extend CodeGraphic. Adds symbols, strings, etc, makes it clickable and shows the current position in the file. * Don't use designated initializer (fails on AppVeyor). * CodeGraphic: Change color of symbols to orange for increased contrast. --- src/widgets/CodeGraphic.cpp | 209 ++++++++++++++++++++++++++++-------- src/widgets/CodeGraphic.h | 21 +++- 2 files changed, 184 insertions(+), 46 deletions(-) diff --git a/src/widgets/CodeGraphic.cpp b/src/widgets/CodeGraphic.cpp index bd388568..faf0620b 100644 --- a/src/widgets/CodeGraphic.cpp +++ b/src/widgets/CodeGraphic.cpp @@ -1,6 +1,7 @@ #include "CodeGraphic.h" #include "MainWindow.h" +#include "utils/TempConfig.h" #include #include @@ -40,7 +41,8 @@ GraphicsBar::GraphicsBar(MainWindow *main, QWidget *parent) : addWidget(this->codeGraphic); //addWidget(addsCombo); - connect(Core(), SIGNAL(refreshAll()), this, SLOT(fillData())); + connect(Core(), SIGNAL(seekChanged(RVA)), this, SLOT(on_seekChanged(RVA))); + connect(Core(), SIGNAL(refreshAll()), this, SLOT(fetchAndPaintData())); } void GraphicsBar::paintEvent(QPaintEvent *event) @@ -51,8 +53,36 @@ void GraphicsBar::paintEvent(QPaintEvent *event) this->fillData(); } +void GraphicsBar::fetchAndPaintData() +{ + fetchData(); + fillData(); +} + +void GraphicsBar::fetchData() +{ + TempConfig tempConfig; + tempConfig.set("search.in", QString("io.section")); + sections = Core()->getAllSections(); + + totalSectionsSize = 0; + blockMaps.clear(); + for(SectionDescription section : sections) + { + QString command = "p-j @" + RAddressString(section.vaddr); + QJsonDocument doc = Core()->cmdj(command); + QJsonObject jObject = doc.object(); + QVariantMap mainMap = jObject.toVariantMap(); + blockMaps.append(mainMap); + totalSectionsSize += section.size; + } +} + void GraphicsBar::fillData() { + int from = blockMaps.first()["from"].toInt(); + int to = blockMaps.first()["to"].toInt(); + // Prepare the graph scene int w = this->codeGraphic->width(); int h = this->codeGraphic->height(); @@ -66,63 +96,152 @@ void GraphicsBar::fillData() this->codeGraphic->setRenderHints(QPainter::Antialiasing); this->codeGraphic->setToolTip("gap"); - // Parse JSON data - QJsonDocument doc = Core()->cmdj("p-j"); - //get the jsonObject - QJsonObject jObject = doc.object(); + RVA current_address = Core()->getOffset(); - //convert the json object to variantmap - QVariantMap mainMap = jObject.toVariantMap(); + double width_per_byte = (double)w/(double)totalSectionsSize; + xToAddress.clear(); + double x_start = 0.0; - int from = mainMap["from"].toInt(); - int to = mainMap["to"].toInt(); - int block = mainMap["blocksize"].toInt(); - int size = (to - from); - int num = 1; - if (block != 0) + + bool draw_cursor = false; + double cursor_x = 0.0; + + for(int i=0; i < sections.length(); i++) { - num = size / block; - } + SectionDescription section = sections[i]; + double width = ((double)section.size * width_per_byte); + double x_end = x_start + width; + double local_w = x_end - x_start; - if (num < 1) - { - num = 1; - } - int graph_block = w / num; - int counter = 0; - - for (auto i : mainMap["blocks"].toList()) - { - QMap map = i.toMap(); - if (map.empty()) + QVariantMap mainMap = blockMaps[i]; + from = mainMap["from"].toInt(); + to = mainMap["to"].toInt(); + int block = mainMap["blocksize"].toInt(); + int size = (to - from); + int num = 1; + if (block != 0) { - // Fill empty color - // addRect(qreal x, qreal y, qreal w, qreal h, const QPen &pen = QPen(), const QBrush &brush = QBrush()) - //scene->addRect(counter * graph_block, 0, graph_block ,h, QPen(Qt::NoPen), QBrush(QColor(252, 249, 190))); - QGraphicsRectItem *rect = new QGraphicsRectItem(counter * graph_block, 0, graph_block, h); - rect->setPen(Qt::NoPen); - rect->setBrush(QBrush(QColor(252, 249, 190))); - rect->setToolTip("Data"); - scene->addItem(rect); + num = size / block; } - else + + if (num < 1) { - // Fill type of color - //scene->addRect(counter * graph_block, 0, graph_block ,h, QPen(Qt::NoPen), QBrush(QColor(69, 104, 229))); - QGraphicsRectItem *rect = new QGraphicsRectItem(counter * graph_block, 0, graph_block, h); - rect->setPen(Qt::NoPen); - if (i.toMap()["functions"].toInt() == 0) + num = 1; + } + + int graph_block = local_w / num; + int counter = 0; + + for (auto j : mainMap["blocks"].toList()) + { + QMap map = j.toMap(); + + // The X of where this block will start + double block_x_start = x_start + (double)(counter * graph_block); + + // Keep X start and end as well as the start & end address in a list. + // This is used to convert address to an X position on the bar and vice versa. + struct xToAddress x2a; + x2a.x_start = block_x_start; + x2a.x_end = block_x_start + graph_block; + x2a.address_from = map["offset"].toULongLong(); + x2a.address_to = map["offset"].toULongLong() + map["size"].toULongLong(); + xToAddress.append(x2a); + + if (map.empty()) { - rect->setBrush(QBrush(QColor(190, 190, 190))); + // Fill as empty + QGraphicsRectItem *rect = new QGraphicsRectItem(block_x_start, 0, graph_block, h); + rect->setPen(Qt::NoPen); + rect->setBrush(QBrush(QColor(252, 249, 190))); + rect->setToolTip("Data"); + scene->addItem(rect); } else { - rect->setBrush(QBrush(QColor(69, 104, 229))); + // TODO: Make this compatible with theming + QGraphicsRectItem *rect = new QGraphicsRectItem(block_x_start, 0, graph_block, h); + rect->setPen(Qt::NoPen); + if (map["functions"].toInt() > 0) + { + rect->setBrush(QBrush(QColor(69, 104, 229))); + } + else if(map["symbols"].toInt() > 0) + { + rect->setBrush(QBrush(QColor(229, 150, 69))); + } + else if(map["strings"].toInt() > 0) + { + rect->setBrush(QBrush(QColor(104, 229, 69))); + } + else + { + rect->setBrush(QBrush(QColor(190, 190, 190))); + } + rect->setToolTip(generateTooltip(section.name, map)); + scene->addItem(rect); } - rect->setToolTip("Offset: 0x" + QString::number(i.toMap()["offset"].toInt(), 16) + "\nFunctions: " + QString::number(i.toMap()["functions"].toInt()) + "\nFlags: " + QString::number(i.toMap()["flags"].toInt())); - scene->addItem(rect); + + // Check whether this block contains the current address. + if ((x2a.address_from <= current_address) && (current_address < x2a.address_to)) + { + draw_cursor = true; + RVA cursor_offset = (double)(current_address - x2a.address_from) * width_per_byte; + cursor_x = block_x_start + cursor_offset; + } + + counter += 1; + } + x_start = x_end; + } + + // Draw the red cursor that shows where we are in the file (if we are in one of the rendered sections) + if(draw_cursor) + { + QGraphicsRectItem *rect = new QGraphicsRectItem(cursor_x, 0, 2, h); + rect->setPen(Qt::NoPen); + rect->setBrush(QBrush(QColor(255, 0, 0))); + scene->addItem(rect); + } +} + +QString GraphicsBar::generateTooltip(QString section_name, QMap map) +{ + QString ret = ""; + ret += "Offset: 0x" + QString::number(map["offset"].toInt(), 16) + "\n"; + ret += "Section: " + section_name + "\n"; + ret += "Size: " + QString::number(map["size"].toInt()) + "\n"; + ret += "Functions: " + QString::number(map["functions"].toInt()) + "\n"; + ret += "Flags: " + QString::number(map["flags"].toInt()) + "\n"; + ret += "Comments: " + QString::number(map["comments"].toInt()) + "\n"; + ret += "Symbols: " + QString::number(map["symbols"].toInt()) + "\n"; + ret += "Strings: " + QString::number(map["strings"].toInt()) + "\n"; + ret += "rwx: " + map["rwx"].toString() + "\n"; + + return ret; +} + +void GraphicsBar::on_seekChanged(RVA addr) +{ + Q_UNUSED(addr); + // Re-paint, which will also update the cursor. + this->fillData(); +} + +void GraphicsBar::mousePressEvent(QMouseEvent *event) +{ + event->accept(); + // Convert the local X coordinate to an address. + qreal x = event->localPos().x(); + for(auto x2a : xToAddress) + { + if ((x2a.x_start <= x) && (x <= x2a.x_end)) + { + double offset = (x - x2a.x_start) / (x2a.x_end - x2a.x_start); + double size = x2a.address_to - x2a.address_from; + Core()->seek(x2a.address_from + (offset * size)); + break; } - counter += 1; } } diff --git a/src/widgets/CodeGraphic.h b/src/widgets/CodeGraphic.h index b276b487..186fb19f 100644 --- a/src/widgets/CodeGraphic.h +++ b/src/widgets/CodeGraphic.h @@ -3,6 +3,8 @@ #include +#include "cutter.h" + class MainWindow; class QGraphicsView; @@ -10,18 +12,35 @@ class GraphicsBar : public QToolBar { Q_OBJECT + struct xToAddress { + double x_start; + double x_end; + RVA address_from; + RVA address_to; + }; + public: explicit GraphicsBar(MainWindow *main, QWidget *parent = 0); public slots: - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; private slots: + void fetchAndPaintData(); + void fetchData(); void fillData(); + void on_seekChanged(RVA addr); private: QGraphicsView *codeGraphic; MainWindow *main; + RVA totalSectionsSize; + QList sections; + QList blockMaps; + QList xToAddress; + QString generateTooltip(QString section_name, QMap map); + + void mousePressEvent(QMouseEvent *event) override; }; #endif // GRAPHICSBAR_H