From 08867b705d2a877ff8db4a729c90064eed091804 Mon Sep 17 00:00:00 2001 From: Dhaval Purohit Date: Sat, 28 Mar 2020 13:31:02 +0100 Subject: [PATCH 1/6] Add tooltip for displaying flag and comment in hexdump (#1471) --- src/widgets/HexWidget.cpp | 48 ++++++++++++++++++++++++++++++++++++++- src/widgets/HexWidget.h | 1 + 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/widgets/HexWidget.cpp b/src/widgets/HexWidget.cpp index d82fc5099..430a58b75 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 addr = currentAreaPosToAddr(pos, true); + + QString ret = getFlagAndComment(addr.address); + if (!ret.isEmpty() && itemArea.contains(pos)) { + QToolTip::showText(event->globalPos(), ret, this); + } else { + QToolTip::hideText(); + } + if (!updatingSelection) { if (itemArea.contains(pos) || asciiArea.contains(pos)) setCursor(Qt::IBeamCursor); @@ -480,7 +490,6 @@ void HexWidget::mouseMoveEvent(QMouseEvent *event) pos.setX(area.left()); else if (pos.x() > area.right()) pos.setX(area.right()); - auto addr = currentAreaPosToAddr(pos, true); setCursorAddr(addr, true); /* Stop blinking */ @@ -1010,6 +1019,11 @@ 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 (!getFlagAndComment(itemAddr).isEmpty()) { + painter.setPen(QColor(255, 255, 0)); + painter.drawRect(itemRect); + } if (selection.contains(itemAddr) && !cursorOnAscii) { itemColor = palette().highlightedText().color(); } @@ -1454,6 +1468,38 @@ QChar HexWidget::renderAscii(int offset, QColor *color) return QChar(byte); } +QString HexWidget::getFlagAndComment(uint64_t address) +{ + QString ret = ""; + QString flagName = ""; + + RCore *core = Core()->core(); + RFlagItem *f = r_flag_get_i (core->flags, address); + + if (f) { + // Check if Realname is enabled. If yes, show it instead of the full flag-name. + if (Config()->getConfigBool("asm.flags.real") && f->realname) { + flagName = f->realname; + } else { + flagName = f->name; + } + + ret = "Flag: " + flagName.trimmed(); + } + + QString comment = Core()->cmd("CC." + RAddressString(address)); + + if (!(comment.isNull() || comment.isEmpty())) { + if (ret.isEmpty()) { + ret = "Comment: " + comment.trimmed(); + } else { + ret += "\nComment: " + comment.trimmed(); + } + } + + return ret; +} + void HexWidget::fetchData() { data.swap(oldData); diff --git a/src/widgets/HexWidget.h b/src/widgets/HexWidget.h index 0cb1bd109..bf8a863b4 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 getFlagAndComment(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. From 5fd4aaf245b53d18013c9d700d086e9905e75e94 Mon Sep 17 00:00:00 2001 From: Dhaval Purohit Date: Wed, 1 Apr 2020 09:05:54 +0200 Subject: [PATCH 2/6] Add review changes --- src/widgets/HexWidget.cpp | 50 ++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/widgets/HexWidget.cpp b/src/widgets/HexWidget.cpp index 430a58b75..5946d8c06 100644 --- a/src/widgets/HexWidget.cpp +++ b/src/widgets/HexWidget.cpp @@ -468,11 +468,11 @@ void HexWidget::mouseMoveEvent(QMouseEvent *event) QPoint pos = event->pos(); pos.rx() += horizontalScrollBar()->value(); - auto addr = currentAreaPosToAddr(pos, true); + auto mouseAddr = mousePosToAddr(pos).address; - QString ret = getFlagAndComment(addr.address); - if (!ret.isEmpty() && itemArea.contains(pos)) { - QToolTip::showText(event->globalPos(), ret, this); + QString metaData = getFlagAndComment(mouseAddr); + if (!metaData.isEmpty() && itemArea.contains(pos)) { + QToolTip::showText(event->globalPos(), metaData, this); } else { QToolTip::hideText(); } @@ -490,6 +490,7 @@ void HexWidget::mouseMoveEvent(QMouseEvent *event) pos.setX(area.left()); else if (pos.x() > area.right()) pos.setX(area.right()); + auto addr = currentAreaPosToAddr(pos, true); setCursorAddr(addr, true); /* Stop blinking */ @@ -1021,8 +1022,11 @@ void HexWidget::drawItemArea(QPainter &painter) itemString = renderItem(itemAddr - startAddress, &itemColor); if (!getFlagAndComment(itemAddr).isEmpty()) { - painter.setPen(QColor(255, 255, 0)); - painter.drawRect(itemRect); + 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(); @@ -1468,36 +1472,28 @@ 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::getFlagAndComment(uint64_t address) { - QString ret = ""; - QString flagName = ""; - RCore *core = Core()->core(); - RFlagItem *f = r_flag_get_i (core->flags, address); + QString flagName = r_flag_get_liststr (core->flags, address); - if (f) { - // Check if Realname is enabled. If yes, show it instead of the full flag-name. - if (Config()->getConfigBool("asm.flags.real") && f->realname) { - flagName = f->realname; - } else { - flagName = f->name; - } + QString metaData = flagName.isEmpty() ? "" : "Flag: " + flagName.trimmed(); - ret = "Flag: " + flagName.trimmed(); - } + QString comment = Core()->cmdRawAt("CC.", address); - QString comment = Core()->cmd("CC." + RAddressString(address)); - - if (!(comment.isNull() || comment.isEmpty())) { - if (ret.isEmpty()) { - ret = "Comment: " + comment.trimmed(); - } else { - ret += "\nComment: " + comment.trimmed(); + if (!comment.isEmpty()) { + if (!metaData.isEmpty()) { + metaData.append("\n"); } + metaData.append("Comment: " + comment.trimmed()); } - return ret; + return metaData; } void HexWidget::fetchData() From acabc813fcdf5f217b5351461614768bf55b0050 Mon Sep 17 00:00:00 2001 From: Dhaval Purohit Date: Thu, 2 Apr 2020 01:12:43 +0200 Subject: [PATCH 3/6] Create narrow function for comment and flag --- src/core/Cutter.cpp | 11 +++++++++++ src/core/Cutter.h | 2 ++ src/widgets/HexWidget.cpp | 11 ++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 805f1600f..5281077f3 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -775,6 +775,11 @@ void CutterCore::delComment(RVA addr) emit commentsChanged(); } +QString CutterCore::getCommentAt(RVA addr) +{ + return Core()->cmdRawAt("CC.", addr); +} + void CutterCore::setImmediateBase(const QString &r2BaseName, RVA offset) { if (offset == RVA_INVALID) { @@ -3465,6 +3470,12 @@ void CutterCore::addFlag(RVA offset, QString name, RVA size) emit flagsChanged(); } +QString CutterCore::listFlagsAsStringAt(RVA addr) +{ + RCore *core = Core()->core(); + 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 5946d8c06..0ca1d49cf 100644 --- a/src/widgets/HexWidget.cpp +++ b/src/widgets/HexWidget.cpp @@ -472,7 +472,7 @@ void HexWidget::mouseMoveEvent(QMouseEvent *event) QString metaData = getFlagAndComment(mouseAddr); if (!metaData.isEmpty() && itemArea.contains(pos)) { - QToolTip::showText(event->globalPos(), metaData, this); + QToolTip::showText(event->globalPos(), metaData.replace(",", ", "), this); } else { QToolTip::hideText(); } @@ -1479,13 +1479,10 @@ QChar HexWidget::renderAscii(int offset, QColor *color) */ QString HexWidget::getFlagAndComment(uint64_t address) { - RCore *core = Core()->core(); - QString flagName = r_flag_get_liststr (core->flags, address); - - QString metaData = flagName.isEmpty() ? "" : "Flag: " + flagName.trimmed(); - - QString comment = Core()->cmdRawAt("CC.", address); + QString flagName = Core()->listFlagsAsStringAt(address); + QString metaData = flagName.isEmpty() ? "" : "Flags: " + flagName.trimmed(); + QString comment = Core()->getCommentAt(address); if (!comment.isEmpty()) { if (!metaData.isEmpty()) { metaData.append("\n"); From f25106dd26a82c1de6e31a94c28644967f2fe8b3 Mon Sep 17 00:00:00 2001 From: Dhaval Purohit Date: Thu, 2 Apr 2020 01:25:00 +0200 Subject: [PATCH 4/6] Document listFlagsAsStringAt function --- src/core/Cutter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 5281077f3..9ddd36009 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -3470,6 +3470,11 @@ 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) { RCore *core = Core()->core(); From e8721878336c1d8e79fdd544b4df3b36577a340f Mon Sep 17 00:00:00 2001 From: Dhaval Purohit Date: Thu, 2 Apr 2020 09:18:37 +0200 Subject: [PATCH 5/6] Fix function name to make it semantic --- src/core/Cutter.cpp | 5 +++++ src/widgets/HexWidget.cpp | 10 +++++----- src/widgets/HexWidget.h | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 9ddd36009..d62c6397e 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -775,6 +775,11 @@ 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); diff --git a/src/widgets/HexWidget.cpp b/src/widgets/HexWidget.cpp index 0ca1d49cf..599ba8ad2 100644 --- a/src/widgets/HexWidget.cpp +++ b/src/widgets/HexWidget.cpp @@ -470,7 +470,7 @@ void HexWidget::mouseMoveEvent(QMouseEvent *event) auto mouseAddr = mousePosToAddr(pos).address; - QString metaData = getFlagAndComment(mouseAddr); + QString metaData = getFlagsAndComment(mouseAddr); if (!metaData.isEmpty() && itemArea.contains(pos)) { QToolTip::showText(event->globalPos(), metaData.replace(",", ", "), this); } else { @@ -1021,7 +1021,7 @@ void HexWidget::drawItemArea(QPainter &painter) for (int k = 0; k < itemGroupSize && itemAddr <= data->maxIndex(); ++k, itemAddr += itemByteLen) { itemString = renderItem(itemAddr - startAddress, &itemColor); - if (!getFlagAndComment(itemAddr).isEmpty()) { + if (!getFlagsAndComment(itemAddr).isEmpty()) { QColor markerColor(borderColor); markerColor.setAlphaF(0.5); const auto shape = rangePolygons(itemAddr, itemAddr, false)[0]; @@ -1477,10 +1477,10 @@ QChar HexWidget::renderAscii(int offset, QColor *color) * @param address Address of Item to be checked. * @return String containing the flags and comment available at the address. */ -QString HexWidget::getFlagAndComment(uint64_t address) +QString HexWidget::getFlagsAndComment(uint64_t address) { - QString flagName = Core()->listFlagsAsStringAt(address); - QString metaData = flagName.isEmpty() ? "" : "Flags: " + flagName.trimmed(); + QString flagNames = Core()->listFlagsAsStringAt(address); + QString metaData = flagNames.isEmpty() ? "" : "Flags: " + flagNames.trimmed(); QString comment = Core()->getCommentAt(address); if (!comment.isEmpty()) { diff --git a/src/widgets/HexWidget.h b/src/widgets/HexWidget.h index bf8a863b4..0cc603eb5 100644 --- a/src/widgets/HexWidget.h +++ b/src/widgets/HexWidget.h @@ -329,7 +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 getFlagAndComment(uint64_t address); + 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. From f433ad3fa78ff8638b702df02752ea12ee9be56e Mon Sep 17 00:00:00 2001 From: Itay Cohen Date: Thu, 2 Apr 2020 15:27:25 +0300 Subject: [PATCH 6/6] Use CORE_LOCK() in Cutter.cpp Co-Authored-By: karliss --- src/core/Cutter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index d62c6397e..225264801 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -3482,7 +3482,7 @@ void CutterCore::addFlag(RVA offset, QString name, RVA size) */ QString CutterCore::listFlagsAsStringAt(RVA addr) { - RCore *core = Core()->core(); + CORE_LOCK(); return r_flag_get_liststr (core->flags, addr); }