mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 10:58:51 +00:00
Use p- in VisualNavbar
This commit is contained in:
parent
e41d408fda
commit
7e8e182f72
@ -1537,7 +1537,7 @@ QList<SearchDescription> CutterCore::getAllSearch(QString search_for, QString sp
|
|||||||
|
|
||||||
BlockStatistics CutterCore::getBlockStatistics(unsigned int blocksCount)
|
BlockStatistics CutterCore::getBlockStatistics(unsigned int blocksCount)
|
||||||
{
|
{
|
||||||
QJsonObject statsObj = cmdj("p- " + QString::number(blocksCount)).object();
|
QJsonObject statsObj = cmdj("p-j " + QString::number(blocksCount)).object();
|
||||||
|
|
||||||
BlockStatistics ret;
|
BlockStatistics ret;
|
||||||
ret.from = statsObj["from"].toVariant().toULongLong();
|
ret.from = statsObj["from"].toVariant().toULongLong();
|
||||||
@ -1545,7 +1545,7 @@ BlockStatistics CutterCore::getBlockStatistics(unsigned int blocksCount)
|
|||||||
ret.blocksize = statsObj["blocksize"].toVariant().toULongLong();
|
ret.blocksize = statsObj["blocksize"].toVariant().toULongLong();
|
||||||
|
|
||||||
QJsonArray blocksArray = statsObj["blocks"].toArray();
|
QJsonArray blocksArray = statsObj["blocks"].toArray();
|
||||||
for (QJsonValue value : blocksArray) {
|
for (const QJsonValue &value : blocksArray) {
|
||||||
QJsonObject blockObj = value.toObject();
|
QJsonObject blockObj = value.toObject();
|
||||||
BlockDescription block;
|
BlockDescription block;
|
||||||
block.addr = blockObj["offset"].toVariant().toULongLong();
|
block.addr = blockObj["offset"].toVariant().toULongLong();
|
||||||
|
@ -41,8 +41,8 @@ VisualNavbar::VisualNavbar(MainWindow *main, QWidget *parent) :
|
|||||||
|
|
||||||
connect(Core(), SIGNAL(seekChanged(RVA)), this, SLOT(on_seekChanged(RVA)));
|
connect(Core(), SIGNAL(seekChanged(RVA)), this, SLOT(on_seekChanged(RVA)));
|
||||||
connect(Core(), SIGNAL(refreshAll()), this, SLOT(fetchAndPaintData()));
|
connect(Core(), SIGNAL(refreshAll()), this, SLOT(fetchAndPaintData()));
|
||||||
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(updateMetadataAndPaint()));
|
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(fetchAndPaintData()));
|
||||||
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(updateMetadataAndPaint()));
|
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(fetchAndPaintData()));
|
||||||
|
|
||||||
graphicsScene = new QGraphicsScene(this);
|
graphicsScene = new QGraphicsScene(this);
|
||||||
|
|
||||||
@ -82,224 +82,85 @@ void VisualNavbar::fetchAndPaintData()
|
|||||||
fillData();
|
fillData();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VisualNavbar::sortSectionLessThan(const SectionDescription §ion1,
|
|
||||||
const SectionDescription §ion2)
|
|
||||||
{
|
|
||||||
return section1.vaddr < section2.vaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VisualNavbar::MappedSegment *VisualNavbar::mappedSegmentForAddress(RVA addr)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mappedSegments.length(); i++) {
|
|
||||||
MappedSegment *mappedSegment = &mappedSegments[i];
|
|
||||||
if ((mappedSegment->address_from <= addr) && (addr <= mappedSegment->address_to)) {
|
|
||||||
return mappedSegment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VisualNavbar::fetchData()
|
void VisualNavbar::fetchData()
|
||||||
{
|
{
|
||||||
// TODO: This code is quite verbose but very readable. The goal is to
|
statsWidth = graphicsView->width();
|
||||||
// experiment until we know what we want and then start to optimize.
|
stats = Core()->getBlockStatistics((unsigned int)statsWidth);
|
||||||
sections = Core()->getAllSections();
|
|
||||||
|
|
||||||
// Sort sections so we don't have to filter for overlaps afterwards
|
|
||||||
qSort(sections.begin(), sections.end(), sortSectionLessThan);
|
|
||||||
|
|
||||||
mappedSegments.clear();
|
|
||||||
for (SectionDescription section : sections) {
|
|
||||||
bool segment_found = false;
|
|
||||||
for (int i = 0; i < mappedSegments.count(); i++) {
|
|
||||||
MappedSegment &mappedSegment = mappedSegments[i];
|
|
||||||
// Check if the segment contains the section
|
|
||||||
bool segment_contains_section_start = false;
|
|
||||||
if ((mappedSegment.address_from <= section.vaddr) &&
|
|
||||||
(section.vaddr <= mappedSegment.address_to)) {
|
|
||||||
segment_contains_section_start = true;
|
|
||||||
}
|
|
||||||
bool segment_contains_section_end = false;
|
|
||||||
if ((mappedSegment.address_from <= section.vaddr + section.vsize) &&
|
|
||||||
(section.vaddr + section.vsize <= mappedSegment.address_to)) {
|
|
||||||
segment_contains_section_end = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the section contains the segment
|
enum class DataType: int { Empty, Code, String, Symbol, Count };
|
||||||
bool section_contains_segment_start = false;
|
|
||||||
bool section_contains_segment_end = false;
|
|
||||||
if ((section.vaddr <= mappedSegment.address_from) &&
|
|
||||||
(mappedSegment.address_from <= section.vaddr + section.vsize)) {
|
|
||||||
section_contains_segment_start = true;
|
|
||||||
}
|
|
||||||
if ((section.vaddr <= mappedSegment.address_to) &&
|
|
||||||
(mappedSegment.address_to <= section.vaddr + section.vsize)) {
|
|
||||||
section_contains_segment_end = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (segment_contains_section_start | segment_contains_section_end |
|
|
||||||
section_contains_segment_start | section_contains_segment_end) {
|
|
||||||
if (section.vaddr < mappedSegment.address_from) {
|
|
||||||
mappedSegment.address_from = section.vaddr;
|
|
||||||
}
|
|
||||||
if (mappedSegment.address_to < section.vaddr + section.vsize) {
|
|
||||||
mappedSegment.address_to = section.vaddr + section.vsize;
|
|
||||||
}
|
|
||||||
segment_found = true;
|
|
||||||
mappedSegment.sectionDescriptions.append(section);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!segment_found) {
|
|
||||||
MappedSegment mappedSegment;
|
|
||||||
mappedSegment.address_from = section.vaddr;
|
|
||||||
mappedSegment.address_to = section.vaddr + section.vsize;
|
|
||||||
mappedSegment.sectionDescriptions.append(section);
|
|
||||||
mappedSegments.append(mappedSegment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the file does not contain any sections we get the segments
|
|
||||||
// from the memory maps instead.
|
|
||||||
// It treats each map on its own, so overlapping maps will be shown
|
|
||||||
// seperated.
|
|
||||||
if (sections.count() == 0) {
|
|
||||||
QJsonArray maps = Core()->cmdj("omj").array();
|
|
||||||
for (QJsonValue mapValue : maps) {
|
|
||||||
QJsonObject map = mapValue.toObject();
|
|
||||||
MappedSegment mappedSegment;
|
|
||||||
mappedSegment.address_from = map["from"].toVariant().toULongLong();
|
|
||||||
mappedSegment.address_to = map["to"].toVariant().toULongLong();
|
|
||||||
mappedSegments.append(mappedSegment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
totalMappedSize = 0;
|
|
||||||
for (auto &mappedSegment : mappedSegments) {
|
|
||||||
totalMappedSize += mappedSegment.address_to - mappedSegment.address_from;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VisualNavbar::updateMetadataAndPaint()
|
|
||||||
{
|
|
||||||
qWarning() << "Update metadata & paint";
|
|
||||||
updateMetadata();
|
|
||||||
fillData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VisualNavbar::updateMetadata()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mappedSegments.length(); i++) {
|
|
||||||
mappedSegments[i].functions.clear();
|
|
||||||
mappedSegments[i].symbols.clear();
|
|
||||||
mappedSegments[i].strings.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<FunctionDescription> functions = Core()->getAllFunctions();
|
|
||||||
for (auto function : functions) {
|
|
||||||
auto mappedSegment = mappedSegmentForAddress(function.offset);
|
|
||||||
if (mappedSegment) {
|
|
||||||
MappedSegmentMetadata metadata;
|
|
||||||
metadata.address = function.offset;
|
|
||||||
metadata.size = function.size;
|
|
||||||
mappedSegment->functions.append(metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<SymbolDescription> symbols = Core()->getAllSymbols();
|
|
||||||
for (auto symbol : symbols) {
|
|
||||||
auto mappedSegment = mappedSegmentForAddress(symbol.vaddr);
|
|
||||||
if (mappedSegment) {
|
|
||||||
MappedSegmentMetadata metadata;
|
|
||||||
metadata.address = symbol.vaddr;
|
|
||||||
metadata.size = 1;
|
|
||||||
mappedSegment->symbols.append(metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<StringDescription> strings = Core()->getAllStrings();
|
|
||||||
for (auto string : strings) {
|
|
||||||
MappedSegment *mappedSegment = mappedSegmentForAddress(string.vaddr);
|
|
||||||
if (mappedSegment) {
|
|
||||||
MappedSegmentMetadata metadata;
|
|
||||||
metadata.address = string.vaddr;
|
|
||||||
metadata.size = string.string.length();
|
|
||||||
mappedSegment->strings.append(metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VisualNavbar::drawMetadata(QList<MappedSegmentMetadata> metadata,
|
|
||||||
RVA offset,
|
|
||||||
double x,
|
|
||||||
double width_per_byte,
|
|
||||||
double h, QColor color)
|
|
||||||
{
|
|
||||||
for (auto s : metadata) {
|
|
||||||
double block_x = x + ((double)(s.address - offset) * width_per_byte);
|
|
||||||
double block_width = (double)s.size * width_per_byte;
|
|
||||||
QGraphicsRectItem *rect = new QGraphicsRectItem(block_x, 0, block_width, h);
|
|
||||||
rect->setPen(Qt::NoPen);
|
|
||||||
rect->setBrush(QBrush(color));
|
|
||||||
graphicsScene->addItem(rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VisualNavbar::fillData()
|
void VisualNavbar::fillData()
|
||||||
{
|
{
|
||||||
graphicsScene->clear();
|
graphicsScene->clear();
|
||||||
|
xToAddress.clear();
|
||||||
cursorGraphicsItem = nullptr;
|
cursorGraphicsItem = nullptr;
|
||||||
// Do not try to draw if no sections are available.
|
|
||||||
if (mappedSegments.length() == 0) {
|
graphicsScene->setBackgroundBrush(QBrush(Config()->getColor("gui.navbar.empty")));
|
||||||
|
|
||||||
|
if (stats.to <= stats.from) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w = this->graphicsView->width();
|
int w = graphicsView->width();
|
||||||
int h = this->graphicsView->height();
|
int h = graphicsView->height();
|
||||||
|
|
||||||
double width_per_byte = (double)w / (double)totalMappedSize;
|
RVA totalSize = stats.to - stats.from;
|
||||||
xToAddress.clear();
|
|
||||||
double current_x = 0;
|
|
||||||
for (auto mappedSegment : mappedSegments) {
|
|
||||||
RVA segment_size = mappedSegment.address_to - mappedSegment.address_from;
|
|
||||||
double segment_width = (double)segment_size * width_per_byte;
|
|
||||||
QGraphicsRectItem *rect = new QGraphicsRectItem(current_x, 0, segment_width, h);
|
|
||||||
rect->setBrush(QBrush(Config()->getColor("gui.navbar.empty")));
|
|
||||||
graphicsScene->addItem(rect);
|
|
||||||
drawMetadata(mappedSegment.strings,
|
|
||||||
mappedSegment.address_from,
|
|
||||||
current_x,
|
|
||||||
width_per_byte,
|
|
||||||
h, Config()->getColor("gui.navbar.str"));
|
|
||||||
drawMetadata(mappedSegment.symbols,
|
|
||||||
mappedSegment.address_from,
|
|
||||||
current_x,
|
|
||||||
width_per_byte,
|
|
||||||
h, Config()->getColor("gui.navbar.sym"));
|
|
||||||
drawMetadata(mappedSegment.functions,
|
|
||||||
mappedSegment.address_from,
|
|
||||||
current_x,
|
|
||||||
width_per_byte,
|
|
||||||
h, Config()->getColor("gui.navbar.code"));
|
|
||||||
|
|
||||||
|
double widthPerByte = (double)w / (double)totalSize;
|
||||||
|
auto xFromAddr = [widthPerByte] (RVA addr) -> double {
|
||||||
|
return addr * widthPerByte;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<QBrush, static_cast<int>(DataType::Count)> dataTypeBrushes;
|
||||||
|
dataTypeBrushes[static_cast<int>(DataType::Code)] = QBrush(Config()->getColor("gui.navbar.code"));
|
||||||
|
dataTypeBrushes[static_cast<int>(DataType::String)] = QBrush(Config()->getColor("gui.navbar.str"));
|
||||||
|
dataTypeBrushes[static_cast<int>(DataType::Symbol)] = QBrush(Config()->getColor("gui.navbar.sym"));
|
||||||
|
|
||||||
|
DataType lastDataType = DataType::Empty;
|
||||||
|
QGraphicsRectItem *dataItem = nullptr;
|
||||||
|
QRectF dataItemRect(0.0, 0.0, 0.0, h);
|
||||||
|
for (const BlockDescription &block : stats.blocks) {
|
||||||
// Keep track of where which memory segment is mapped so we are able to convert from
|
// Keep track of where which memory segment is mapped so we are able to convert from
|
||||||
// address to X coordinate and vice versa.
|
// address to X coordinate and vice versa.
|
||||||
struct xToAddress x2a;
|
XToAddress x2a;
|
||||||
x2a.x_start = current_x;
|
x2a.x_start = xFromAddr(block.addr);
|
||||||
x2a.x_end = current_x + segment_width;
|
x2a.x_end = xFromAddr(block.addr + block.size);
|
||||||
x2a.address_from = mappedSegment.address_from;
|
x2a.address_from = block.addr;
|
||||||
x2a.address_to = mappedSegment.address_to;
|
x2a.address_to = block.addr + block.size;
|
||||||
xToAddress.append(x2a);
|
xToAddress.append(x2a);
|
||||||
|
|
||||||
current_x += segment_width;
|
DataType dataType;
|
||||||
|
if (block.functions > 0) {
|
||||||
|
dataType = DataType::Code;
|
||||||
|
} else if (block.strings > 0) {
|
||||||
|
dataType = DataType::String;
|
||||||
|
} else if (block.symbols > 0) {
|
||||||
|
dataType = DataType::Symbol;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataType == lastDataType) {
|
||||||
|
dataItemRect.setRight(xFromAddr(block.addr + block.size));
|
||||||
|
dataItem->setRect(dataItemRect);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataItemRect.setX(xFromAddr(block.addr));
|
||||||
|
dataItemRect.setRight(xFromAddr(block.addr + block.size));
|
||||||
|
|
||||||
|
dataItem = new QGraphicsRectItem();
|
||||||
|
dataItem->setPen(Qt::NoPen);
|
||||||
|
dataItem->setBrush(dataTypeBrushes[static_cast<int>(dataType)]);
|
||||||
|
graphicsScene->addItem(dataItem);
|
||||||
|
|
||||||
|
lastDataType = dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update scene width
|
// Update scene width
|
||||||
graphicsScene->setSceneRect(graphicsScene->itemsBoundingRect());
|
graphicsScene->setSceneRect(graphicsScene->itemsBoundingRect());
|
||||||
|
|
||||||
// Draw cursor
|
|
||||||
drawCursor();
|
drawCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,11 +236,10 @@ double VisualNavbar::addressToLocalX(RVA address)
|
|||||||
QList<QString> VisualNavbar::sectionsForAddress(RVA address)
|
QList<QString> VisualNavbar::sectionsForAddress(RVA address)
|
||||||
{
|
{
|
||||||
QList<QString> ret;
|
QList<QString> ret;
|
||||||
for (auto mappedSegment : mappedSegments) {
|
QList<SectionDescription> sections = Core()->getAllSections();
|
||||||
for (auto section : mappedSegment.sectionDescriptions) {
|
for (const auto §ion : sections) {
|
||||||
if ((section.vaddr <= address) && (address <= section.vaddr + section.vsize)) {
|
if (address >= section.vaddr && address < section.vaddr + section.vsize) {
|
||||||
ret.append(section.name);
|
ret << section.name;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -13,27 +13,13 @@ class VisualNavbar : public QToolBar
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
struct xToAddress {
|
struct XToAddress {
|
||||||
double x_start;
|
double x_start;
|
||||||
double x_end;
|
double x_end;
|
||||||
RVA address_from;
|
RVA address_from;
|
||||||
RVA address_to;
|
RVA address_to;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MappedSegmentMetadata {
|
|
||||||
RVA address;
|
|
||||||
RVA size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MappedSegment {
|
|
||||||
QList<SectionDescription> sectionDescriptions;
|
|
||||||
QList<MappedSegmentMetadata> functions;
|
|
||||||
QList<MappedSegmentMetadata> symbols;
|
|
||||||
QList<MappedSegmentMetadata> strings;
|
|
||||||
RVA address_from;
|
|
||||||
RVA address_to;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VisualNavbar(MainWindow *main, QWidget *parent = nullptr);
|
explicit VisualNavbar(MainWindow *main, QWidget *parent = nullptr);
|
||||||
|
|
||||||
@ -43,8 +29,6 @@ public slots:
|
|||||||
private slots:
|
private slots:
|
||||||
void fetchAndPaintData();
|
void fetchAndPaintData();
|
||||||
void fetchData();
|
void fetchData();
|
||||||
void updateMetadataAndPaint();
|
|
||||||
void updateMetadata();
|
|
||||||
void fillData();
|
void fillData();
|
||||||
void drawCursor();
|
void drawCursor();
|
||||||
void on_seekChanged(RVA addr);
|
void on_seekChanged(RVA addr);
|
||||||
@ -54,30 +38,20 @@ private:
|
|||||||
QGraphicsScene *graphicsScene;
|
QGraphicsScene *graphicsScene;
|
||||||
QGraphicsRectItem *cursorGraphicsItem;
|
QGraphicsRectItem *cursorGraphicsItem;
|
||||||
MainWindow *main;
|
MainWindow *main;
|
||||||
RVA totalMappedSize;
|
|
||||||
QList<SectionDescription> sections;
|
|
||||||
QList<struct xToAddress> xToAddress;
|
|
||||||
|
|
||||||
QList<MappedSegment> mappedSegments;
|
BlockStatistics stats;
|
||||||
|
int statsWidth;
|
||||||
|
|
||||||
|
QList<XToAddress> xToAddress;
|
||||||
|
|
||||||
// Used to check whether the width changed. If yes we need to re-initialize the scene (slow)
|
// Used to check whether the width changed. If yes we need to re-initialize the scene (slow)
|
||||||
int previousWidth = -1;
|
int previousWidth = -1;
|
||||||
void drawMetadata(QList<MappedSegmentMetadata> metadata,
|
|
||||||
RVA offset,
|
|
||||||
double x,
|
|
||||||
double width_per_byte,
|
|
||||||
double h, QColor color);
|
|
||||||
|
|
||||||
struct MappedSegment *mappedSegmentForAddress(RVA addr);
|
|
||||||
RVA localXToAddress(double x);
|
RVA localXToAddress(double x);
|
||||||
double addressToLocalX(RVA address);
|
double addressToLocalX(RVA address);
|
||||||
QList<QString> sectionsForAddress(RVA address);
|
QList<QString> sectionsForAddress(RVA address);
|
||||||
QString toolTipForAddress(RVA address);
|
QString toolTipForAddress(RVA address);
|
||||||
|
|
||||||
static bool sortSectionLessThan(const SectionDescription §ion1,
|
|
||||||
const SectionDescription §ion2);
|
|
||||||
|
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user