From 7110d7397969826e39ebae71a45eee4f65cdb630 Mon Sep 17 00:00:00 2001 From: Dhaval Purohit Date: Sat, 4 Apr 2020 09:09:30 +0200 Subject: [PATCH] Add tooltip for displaying flag and comment in hexdump (#1471) (#2116) * Add tooltip for displaying flag and comment in hexdump (#1471) Co-authored-by: Itay Cohen Co-authored-by: karliss --- src/core/Cutter.cpp | 21 +++++++++++++++++++++ src/core/Cutter.h | 2 ++ src/widgets/HexWidget.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/widgets/HexWidget.h | 1 + 4 files changed, 63 insertions(+) diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 805f1600f..225264801 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -775,6 +775,16 @@ void CutterCore::delComment(RVA addr) emit commentsChanged(); } +/** + * @brief Gets the comment present at a specific address + * @param addr The address to be checked + * @return String containing comment + */ +QString CutterCore::getCommentAt(RVA addr) +{ + return Core()->cmdRawAt("CC.", addr); +} + void CutterCore::setImmediateBase(const QString &r2BaseName, RVA offset) { if (offset == RVA_INVALID) { @@ -3465,6 +3475,17 @@ void CutterCore::addFlag(RVA offset, QString name, RVA size) emit flagsChanged(); } +/** + * @brief Gets all the flags present at a specific address + * @param addr The address to be checked + * @return String containing all the flags which are comma-separated + */ +QString CutterCore::listFlagsAsStringAt(RVA addr) +{ + CORE_LOCK(); + return r_flag_get_liststr (core->flags, addr); +} + QString CutterCore::nearestFlag(RVA offset, RVA *flagOffsetOut) { auto r = cmdj(QString("fdj @") + QString::number(offset)).object(); diff --git a/src/core/Cutter.h b/src/core/Cutter.h index d6f09a0ba..0ad33ad04 100644 --- a/src/core/Cutter.h +++ b/src/core/Cutter.h @@ -169,6 +169,7 @@ class CutterCore: public QObject void delFlag(RVA addr); void delFlag(const QString &name); void addFlag(RVA offset, QString name, RVA size); + QString listFlagsAsStringAt(RVA addr); /** * @brief Get nearest flag at or before offset. * @param offset search position @@ -217,6 +218,7 @@ class CutterCore: public QObject /* Comments */ void setComment(RVA addr, const QString &cmt); void delComment(RVA addr); + QString getCommentAt(RVA addr); void setImmediateBase(const QString &r2BaseName, RVA offset = RVA_INVALID); void setCurrentBits(int bits, RVA offset = RVA_INVALID); diff --git a/src/widgets/HexWidget.cpp b/src/widgets/HexWidget.cpp index d82fc5099..599ba8ad2 100644 --- a/src/widgets/HexWidget.cpp +++ b/src/widgets/HexWidget.cpp @@ -19,6 +19,7 @@ #include #include #include +#include static constexpr uint64_t MAX_COPY_SIZE = 128 * 1024 * 1024; static constexpr int MAX_LINE_WIDTH_PRESET = 32; @@ -467,6 +468,15 @@ void HexWidget::mouseMoveEvent(QMouseEvent *event) QPoint pos = event->pos(); pos.rx() += horizontalScrollBar()->value(); + auto mouseAddr = mousePosToAddr(pos).address; + + QString metaData = getFlagsAndComment(mouseAddr); + if (!metaData.isEmpty() && itemArea.contains(pos)) { + QToolTip::showText(event->globalPos(), metaData.replace(",", ", "), this); + } else { + QToolTip::hideText(); + } + if (!updatingSelection) { if (itemArea.contains(pos) || asciiArea.contains(pos)) setCursor(Qt::IBeamCursor); @@ -1010,6 +1020,14 @@ void HexWidget::drawItemArea(QPainter &painter) for (int j = 0; j < itemColumns; ++j) { for (int k = 0; k < itemGroupSize && itemAddr <= data->maxIndex(); ++k, itemAddr += itemByteLen) { itemString = renderItem(itemAddr - startAddress, &itemColor); + + if (!getFlagsAndComment(itemAddr).isEmpty()) { + QColor markerColor(borderColor); + markerColor.setAlphaF(0.5); + const auto shape = rangePolygons(itemAddr, itemAddr, false)[0]; + painter.setPen(markerColor); + painter.drawPolyline(shape); + } if (selection.contains(itemAddr) && !cursorOnAscii) { itemColor = palette().highlightedText().color(); } @@ -1454,6 +1472,27 @@ QChar HexWidget::renderAscii(int offset, QColor *color) return QChar(byte); } +/** + * @brief Gets the available flags and comment at a specific address. + * @param address Address of Item to be checked. + * @return String containing the flags and comment available at the address. + */ +QString HexWidget::getFlagsAndComment(uint64_t address) +{ + QString flagNames = Core()->listFlagsAsStringAt(address); + QString metaData = flagNames.isEmpty() ? "" : "Flags: " + flagNames.trimmed(); + + QString comment = Core()->getCommentAt(address); + if (!comment.isEmpty()) { + if (!metaData.isEmpty()) { + metaData.append("\n"); + } + metaData.append("Comment: " + comment.trimmed()); + } + + return metaData; +} + void HexWidget::fetchData() { data.swap(oldData); diff --git a/src/widgets/HexWidget.h b/src/widgets/HexWidget.h index 0cb1bd109..0cc603eb5 100644 --- a/src/widgets/HexWidget.h +++ b/src/widgets/HexWidget.h @@ -329,6 +329,7 @@ private slots: QVariant readItem(int offset, QColor *color = nullptr); QString renderItem(int offset, QColor *color = nullptr); QChar renderAscii(int offset, QColor *color = nullptr); + QString getFlagsAndComment(uint64_t address); /** * @brief Get the location on which operations such as Writing should apply. * @return Start of selection if multiple bytes are selected. Otherwise, the curren seek of the widget.