mirror of
https://github.com/rizinorg/cutter.git
synced 2025-02-01 09:07:26 +00:00
Highlight in red changes in the Hexdump Widget (#1880)
* Highlight changes in the Hexdump Widget
This commit is contained in:
parent
d0da81b592
commit
c1093f3971
@ -124,6 +124,7 @@ HexWidget::HexWidget(QWidget *parent) :
|
|||||||
startAddress = 0ULL;
|
startAddress = 0ULL;
|
||||||
cursor.address = 0ULL;
|
cursor.address = 0ULL;
|
||||||
data.reset(new MemoryData());
|
data.reset(new MemoryData());
|
||||||
|
oldData.reset(new MemoryData());
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
updateCursorMeta();
|
updateCursorMeta();
|
||||||
@ -206,6 +207,27 @@ void HexWidget::setItemGroupSize(int size)
|
|||||||
viewport()->update();
|
viewport()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if Item at the address changed compared to the last read data.
|
||||||
|
* @param address Address of Item to be compared.
|
||||||
|
* @return True if Item is different, False if Item is equal or last read didn't contain the address.
|
||||||
|
* @see HexWidget#readItem
|
||||||
|
*
|
||||||
|
* Checks if current Item at the address changed compared to the last read data.
|
||||||
|
* It is assumed that the current read data buffer contains the address.
|
||||||
|
*/
|
||||||
|
bool HexWidget::isItemDifferentAt(uint64_t address) {
|
||||||
|
if (address >= oldData->minIndex() && address < oldData->maxIndex()) {
|
||||||
|
uint64_t itemOffset = address - startAddress;
|
||||||
|
QVariant curItem = readItem(itemOffset);
|
||||||
|
data.swap(oldData);
|
||||||
|
QVariant oldItem = readItem(itemOffset);
|
||||||
|
data.swap(oldData);
|
||||||
|
return (oldItem != curItem);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void HexWidget::updateCounts()
|
void HexWidget::updateCounts()
|
||||||
{
|
{
|
||||||
actionHexPairs->setEnabled(rowSizeBytes > 1 && itemByteLen == 1
|
actionHexPairs->setEnabled(rowSizeBytes > 1 && itemByteLen == 1
|
||||||
@ -335,6 +357,7 @@ void HexWidget::updateColors()
|
|||||||
printableColor = Config()->getColor("ai.write");
|
printableColor = Config()->getColor("ai.write");
|
||||||
defColor = Config()->getColor("btext");
|
defColor = Config()->getColor("btext");
|
||||||
addrColor = Config()->getColor("func_var_addr");
|
addrColor = Config()->getColor("func_var_addr");
|
||||||
|
diffColor = Config()->getColor("graph.diff.unmatch");
|
||||||
|
|
||||||
updateCursorMeta();
|
updateCursorMeta();
|
||||||
viewport()->update();
|
viewport()->update();
|
||||||
@ -465,13 +488,13 @@ void HexWidget::wheelEvent(QWheelEvent *event)
|
|||||||
startAddress = 0;
|
startAddress = 0;
|
||||||
} else if (delta > 0 && data->maxIndex() < static_cast<uint64_t>(bytesPerScreen())) {
|
} else if (delta > 0 && data->maxIndex() < static_cast<uint64_t>(bytesPerScreen())) {
|
||||||
startAddress = 0;
|
startAddress = 0;
|
||||||
} else if (delta > 0
|
|
||||||
&& (data->maxIndex() - startAddress) <= static_cast<uint64_t>(bytesPerScreen() + delta - 1)) {
|
|
||||||
startAddress = (data->maxIndex() - bytesPerScreen()) + 1;
|
|
||||||
} else {
|
} else {
|
||||||
startAddress += delta;
|
startAddress += delta;
|
||||||
}
|
}
|
||||||
fetchData();
|
fetchData();
|
||||||
|
if ((data->maxIndex() - startAddress) <= static_cast<uint64_t>(bytesPerScreen() + delta - 1)) {
|
||||||
|
startAddress = (data->maxIndex() - bytesPerScreen()) + 1;
|
||||||
|
}
|
||||||
if (cursor.address >= startAddress && cursor.address <= lastVisibleAddr()) {
|
if (cursor.address >= startAddress && cursor.address <= lastVisibleAddr()) {
|
||||||
/* Don't enable cursor blinking if selection isn't empty */
|
/* Don't enable cursor blinking if selection isn't empty */
|
||||||
cursorEnabled = selection.isEmpty();
|
cursorEnabled = selection.isEmpty();
|
||||||
@ -756,6 +779,9 @@ void HexWidget::drawItemArea(QPainter &painter)
|
|||||||
if (selection.contains(itemAddr) && !cursorOnAscii) {
|
if (selection.contains(itemAddr) && !cursorOnAscii) {
|
||||||
itemColor = palette().highlightedText().color();
|
itemColor = palette().highlightedText().color();
|
||||||
}
|
}
|
||||||
|
if (isItemDifferentAt(itemAddr)) {
|
||||||
|
itemColor.setRgb(diffColor.rgb());
|
||||||
|
}
|
||||||
painter.setPen(itemColor);
|
painter.setPen(itemColor);
|
||||||
painter.drawText(itemRect, Qt::AlignVCenter, itemString);
|
painter.drawText(itemRect, Qt::AlignVCenter, itemString);
|
||||||
itemRect.translate(itemWidth(), 0);
|
itemRect.translate(itemWidth(), 0);
|
||||||
@ -789,8 +815,12 @@ void HexWidget::drawAsciiArea(QPainter &painter)
|
|||||||
charRect.moveLeft(asciiArea.left());
|
charRect.moveLeft(asciiArea.left());
|
||||||
for (int j = 0; j < itemRowByteLen() && address <= data->maxIndex(); ++j, ++address) {
|
for (int j = 0; j < itemRowByteLen() && address <= data->maxIndex(); ++j, ++address) {
|
||||||
ascii = renderAscii(address - startAddress, &color);
|
ascii = renderAscii(address - startAddress, &color);
|
||||||
if (selection.contains(address) && cursorOnAscii)
|
if (selection.contains(address) && cursorOnAscii) {
|
||||||
color = palette().highlightedText().color();
|
color = palette().highlightedText().color();
|
||||||
|
}
|
||||||
|
if (isItemDifferentAt(address)) {
|
||||||
|
color.setRgb(diffColor.rgb());
|
||||||
|
}
|
||||||
painter.setPen(color);
|
painter.setPen(color);
|
||||||
/* Dots look ugly. Use fillRect() instead of drawText(). */
|
/* Dots look ugly. Use fillRect() instead of drawText(). */
|
||||||
if (ascii == '.') {
|
if (ascii == '.') {
|
||||||
@ -985,10 +1015,6 @@ void HexWidget::setCursorAddr(BasicCursor addr, bool select)
|
|||||||
/* Align start address */
|
/* Align start address */
|
||||||
addressValue -= (addressValue % itemRowByteLen());
|
addressValue -= (addressValue % itemRowByteLen());
|
||||||
|
|
||||||
if (addressValue > (data->maxIndex() - bytesPerScreen()) + 1) {
|
|
||||||
addressValue = (data->maxIndex() - bytesPerScreen()) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: handling Page Up/Down */
|
/* FIXME: handling Page Up/Down */
|
||||||
if (addressValue == startAddress + bytesPerScreen()) {
|
if (addressValue == startAddress + bytesPerScreen()) {
|
||||||
startAddress += itemRowByteLen();
|
startAddress += itemRowByteLen();
|
||||||
@ -997,6 +1023,10 @@ void HexWidget::setCursorAddr(BasicCursor addr, bool select)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
|
|
||||||
|
if (startAddress > (data->maxIndex() - bytesPerScreen()) + 1) {
|
||||||
|
startAddress = (data->maxIndex() - bytesPerScreen()) + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCursorMeta();
|
updateCursorMeta();
|
||||||
@ -1192,6 +1222,7 @@ QChar HexWidget::renderAscii(int offset, QColor *color)
|
|||||||
|
|
||||||
void HexWidget::fetchData()
|
void HexWidget::fetchData()
|
||||||
{
|
{
|
||||||
|
data.swap(oldData);
|
||||||
data->fetch(startAddress, bytesPerScreen());
|
data->fetch(startAddress, bytesPerScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ public:
|
|||||||
virtual void fetch(uint64_t addr, int len) = 0;
|
virtual void fetch(uint64_t addr, int len) = 0;
|
||||||
virtual const void *dataPtr(uint64_t addr) = 0;
|
virtual const void *dataPtr(uint64_t addr) = 0;
|
||||||
virtual uint64_t maxIndex() = 0;
|
virtual uint64_t maxIndex() = 0;
|
||||||
|
virtual uint64_t minIndex() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferData : public AbstractData
|
class BufferData : public AbstractData
|
||||||
@ -121,14 +122,20 @@ public:
|
|||||||
void fetch(uint64_t address, int length) override
|
void fetch(uint64_t address, int length) override
|
||||||
{
|
{
|
||||||
// FIXME: reuse data if possible
|
// FIXME: reuse data if possible
|
||||||
uint64_t alignedAddr = address & ~(4096ULL - 1);
|
const uint64_t blockSize = 0x1000ULL;
|
||||||
|
uint64_t alignedAddr = address & ~(blockSize - 1);
|
||||||
int offset = address - alignedAddr;
|
int offset = address - alignedAddr;
|
||||||
int len = (offset + length + (4096 - 1)) & ~(4096 - 1);
|
int len = (offset + length + (blockSize - 1)) & ~(blockSize - 1);
|
||||||
m_firstBlockAddr = alignedAddr;
|
m_firstBlockAddr = alignedAddr;
|
||||||
|
m_lastValidAddr = length ? alignedAddr + len - 1 : 0;
|
||||||
|
if (m_lastValidAddr < m_firstBlockAddr) {
|
||||||
|
m_lastValidAddr = -1;
|
||||||
|
len = m_lastValidAddr - m_firstBlockAddr + 1;
|
||||||
|
}
|
||||||
m_blocks.clear();
|
m_blocks.clear();
|
||||||
uint64_t addr = alignedAddr;
|
uint64_t addr = alignedAddr;
|
||||||
for (int i = 0; i < len / 4096; ++i, addr += 4096) {
|
for (int i = 0; i < len / blockSize; ++i, addr += blockSize) {
|
||||||
m_blocks.append(Core()->ioRead(addr, 4096));
|
m_blocks.append(Core()->ioRead(addr, blockSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,12 +149,18 @@ public:
|
|||||||
|
|
||||||
virtual uint64_t maxIndex() override
|
virtual uint64_t maxIndex() override
|
||||||
{
|
{
|
||||||
return UINT64_MAX;
|
return m_lastValidAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint64_t minIndex() override
|
||||||
|
{
|
||||||
|
return m_firstBlockAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<QByteArray> m_blocks;
|
QVector<QByteArray> m_blocks;
|
||||||
uint64_t m_firstBlockAddr;
|
uint64_t m_firstBlockAddr = 0;
|
||||||
|
uint64_t m_lastValidAddr = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HexSelection
|
class HexSelection
|
||||||
@ -298,6 +311,7 @@ private:
|
|||||||
void setCursorAddr(BasicCursor addr, bool select = false);
|
void setCursorAddr(BasicCursor addr, bool select = false);
|
||||||
void updateCursorMeta();
|
void updateCursorMeta();
|
||||||
void setCursorOnAscii(bool ascii);
|
void setCursorOnAscii(bool ascii);
|
||||||
|
bool isItemDifferentAt(uint64_t address);
|
||||||
const QColor itemColor(uint8_t byte);
|
const QColor itemColor(uint8_t byte);
|
||||||
QVariant readItem(int offset, QColor *color = nullptr);
|
QVariant readItem(int offset, QColor *color = nullptr);
|
||||||
QString renderItem(int offset, QColor *color = nullptr);
|
QString renderItem(int offset, QColor *color = nullptr);
|
||||||
@ -446,6 +460,7 @@ private:
|
|||||||
QColor backgroundColor;
|
QColor backgroundColor;
|
||||||
QColor defColor;
|
QColor defColor;
|
||||||
QColor addrColor;
|
QColor addrColor;
|
||||||
|
QColor diffColor;
|
||||||
QColor b0x00Color;
|
QColor b0x00Color;
|
||||||
QColor b0x7fColor;
|
QColor b0x7fColor;
|
||||||
QColor b0xffColor;
|
QColor b0xffColor;
|
||||||
@ -469,6 +484,7 @@ private:
|
|||||||
QAction *actionCopyAddress;
|
QAction *actionCopyAddress;
|
||||||
QAction *actionSelectRange;
|
QAction *actionSelectRange;
|
||||||
|
|
||||||
|
std::unique_ptr<AbstractData> oldData;
|
||||||
std::unique_ptr<AbstractData> data;
|
std::unique_ptr<AbstractData> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,6 +80,9 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
|||||||
|
|
||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
||||||
connect(Core(), &CutterCore::refreshAll, this, [this]() { refresh(); });
|
connect(Core(), &CutterCore::refreshAll, this, [this]() { refresh(); });
|
||||||
|
connect(Core(), &CutterCore::instructionChanged, this, [this]() { refresh(); });
|
||||||
|
connect(Core(), &CutterCore::stackChanged, this, [this]() { refresh(); });
|
||||||
|
connect(Core(), &CutterCore::registersChanged, this, [this]() { refresh(); });
|
||||||
|
|
||||||
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::onSeekChanged);
|
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::onSeekChanged);
|
||||||
connect(ui->hexTextView, &HexWidget::positionChanged, this, [this](RVA addr) {
|
connect(ui->hexTextView, &HexWidget::positionChanged, this, [this](RVA addr) {
|
||||||
|
Loading…
Reference in New Issue
Block a user