GUI: resolved issue #232 (copy in dump windows)
This commit is contained in:
parent
abe53d3492
commit
597298f90f
|
|
@ -2,6 +2,7 @@
|
|||
#include "Configuration.h"
|
||||
#include "Bridge.h"
|
||||
#include "StringUtil.h"
|
||||
#include <QMessageBox>
|
||||
|
||||
HexDump::HexDump(QWidget* parent)
|
||||
: AbstractTableView(parent)
|
||||
|
|
@ -31,6 +32,7 @@ HexDump::HexDump(QWidget* parent)
|
|||
// Slots
|
||||
connect(Bridge::getBridge(), SIGNAL(updateDump()), this, SLOT(updateDumpSlot()));
|
||||
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChanged(DBGSTATE)));
|
||||
setupCopyMenu();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
|
@ -55,6 +57,13 @@ void HexDump::updateFonts()
|
|||
setFont(ConfigFont("HexDump"));
|
||||
}
|
||||
|
||||
void HexDump::updateShortcuts()
|
||||
{
|
||||
AbstractTableView::updateShortcuts();
|
||||
mCopyAddress->setShortcut(ConfigShortcut("ActionCopyAddress"));
|
||||
mCopySelection->setShortcut(ConfigShortcut("ActionCopy"));
|
||||
}
|
||||
|
||||
void HexDump::updateDumpSlot()
|
||||
{
|
||||
if(mSyncAddrExpression.length() && DbgFunctions()->ValFromString)
|
||||
|
|
@ -69,6 +78,11 @@ void HexDump::updateDumpSlot()
|
|||
reloadData();
|
||||
}
|
||||
|
||||
void HexDump::copySelectionSlot()
|
||||
{
|
||||
Bridge::CopyToClipboard(makeCopyText());
|
||||
}
|
||||
|
||||
void HexDump::printDumpAt(dsint parVA, bool select, bool repaint, bool updateTableOffset)
|
||||
{
|
||||
dsint wBase = DbgMemFindBaseAddr(parVA, 0); //get memory base
|
||||
|
|
@ -126,6 +140,79 @@ duint HexDump::getTableOffsetRva()
|
|||
return getTableOffset() * getBytePerRowCount() - mByteOffset;
|
||||
}
|
||||
|
||||
QString HexDump::makeAddrText(duint va)
|
||||
{
|
||||
char label[MAX_LABEL_SIZE] = "";
|
||||
QString addrText = "";
|
||||
dsint cur_addr = va;
|
||||
if(mRvaDisplayEnabled) //RVA display
|
||||
{
|
||||
dsint rva = cur_addr - mRvaDisplayBase;
|
||||
if(rva == 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$ ==> ";
|
||||
#else
|
||||
addrText = "$ ==> ";
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(rva > 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$+" + QString("%1").arg(rva, -15, 16, QChar(' ')).toUpper();
|
||||
#else
|
||||
addrText = "$+" + QString("%1").arg(rva, -7, 16, QChar(' ')).toUpper();
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(rva < 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$-" + QString("%1").arg(-rva, -15, 16, QChar(' ')).toUpper();
|
||||
#else
|
||||
addrText = "$-" + QString("%1").arg(-rva, -7, 16, QChar(' ')).toUpper();
|
||||
#endif //_WIN64
|
||||
}
|
||||
}
|
||||
addrText += ToPtrString(cur_addr);
|
||||
if(DbgGetLabelAt(cur_addr, SEG_DEFAULT, label)) //has label
|
||||
{
|
||||
char module[MAX_MODULE_SIZE] = "";
|
||||
if(DbgGetModuleAt(cur_addr, module) && !QString(label).startsWith("JMP.&"))
|
||||
addrText += " <" + QString(module) + "." + QString(label) + ">";
|
||||
else
|
||||
addrText += " <" + QString(label) + ">";
|
||||
}
|
||||
else
|
||||
*label = 0;
|
||||
return addrText;
|
||||
}
|
||||
|
||||
QString HexDump::makeCopyText()
|
||||
{
|
||||
dsint deltaRowBase = getSelectionStart() % getBytePerRowCount() + mByteOffset;
|
||||
if(deltaRowBase >= getBytePerRowCount())
|
||||
deltaRowBase -= getBytePerRowCount();
|
||||
auto curRow = getSelectionStart() - deltaRowBase;
|
||||
QString result;
|
||||
while(curRow < getSelectionEnd())
|
||||
{
|
||||
for(int col = 0; col < getColumnCount(); col++)
|
||||
{
|
||||
if(col)
|
||||
result += " ";
|
||||
RichTextPainter::List richText;
|
||||
getColumnRichText(col, curRow, richText);
|
||||
QString colText;
|
||||
for(auto & r : richText)
|
||||
colText += r.text;
|
||||
result += colText.leftJustified(getColumnWidth(col) / getCharWidth(), QChar(' '), true);
|
||||
}
|
||||
curRow += getBytePerRowCount();
|
||||
result += "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void HexDump::addVaToHistory(dsint parVa)
|
||||
{
|
||||
//truncate everything right from the current VA
|
||||
|
|
@ -177,6 +264,44 @@ void HexDump::historyClear()
|
|||
mVaHistory.clear();
|
||||
}
|
||||
|
||||
void HexDump::setupCopyMenu()
|
||||
{
|
||||
// Copy -> Data
|
||||
mCopySelection = new QAction(tr("&Selection"), this);
|
||||
connect(mCopySelection, SIGNAL(triggered(bool)), this, SLOT(copySelectionSlot()));
|
||||
mCopySelection->setShortcutContext(Qt::WidgetShortcut);
|
||||
addAction(mCopySelection);
|
||||
|
||||
// Copy -> Address
|
||||
mCopyAddress = new QAction(tr("&Address"), this);
|
||||
connect(mCopyAddress, SIGNAL(triggered()), this, SLOT(copyAddressSlot()));
|
||||
mCopyAddress->setShortcutContext(Qt::WidgetShortcut);
|
||||
addAction(mCopyAddress);
|
||||
|
||||
// Copy -> RVA
|
||||
mCopyRva = new QAction("&RVA", this);
|
||||
connect(mCopyRva, SIGNAL(triggered()), this, SLOT(copyRvaSlot()));
|
||||
}
|
||||
|
||||
void HexDump::copyAddressSlot()
|
||||
{
|
||||
QString addrText = QString("%1").arg(rvaToVa(getInitialSelection()), sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
Bridge::CopyToClipboard(addrText);
|
||||
}
|
||||
|
||||
void HexDump::copyRvaSlot()
|
||||
{
|
||||
duint addr = rvaToVa(getInitialSelection());
|
||||
duint base = DbgFunctions()->ModBaseFromAddr(addr);
|
||||
if(base)
|
||||
{
|
||||
QString addrText = QString("%1").arg(addr - base, 0, 16, QChar('0')).toUpper();
|
||||
Bridge::CopyToClipboard(addrText);
|
||||
}
|
||||
else
|
||||
QMessageBox::warning(this, "Error!", "Selection not in a module...");
|
||||
}
|
||||
|
||||
void HexDump::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
bool wAccept = true;
|
||||
|
|
@ -332,20 +457,14 @@ QString HexDump::paintContent(QPainter* painter, dsint rowBase, int rowOffset, i
|
|||
int wBytePerRowCount = getBytePerRowCount();
|
||||
dsint wRva = (rowBase + rowOffset) * wBytePerRowCount - mByteOffset;
|
||||
|
||||
QString wStr = "";
|
||||
if(col == 0) // Addresses
|
||||
{
|
||||
wStr += QString("%1").arg(rvaToVa(wRva), sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
}
|
||||
else if(mDescriptor.at(col - 1).isData == true) //paint data
|
||||
{
|
||||
if(col && mDescriptor.at(col - 1).isData)
|
||||
printSelected(painter, rowBase, rowOffset, col, x, y, w, h);
|
||||
RichTextPainter::List richText;
|
||||
getString(col - 1, wRva, richText);
|
||||
RichTextPainter::paintRichText(painter, x, y, w, h, 4, richText, getCharWidth());
|
||||
}
|
||||
|
||||
return wStr;
|
||||
RichTextPainter::List richText;
|
||||
getColumnRichText(col, wRva, richText);
|
||||
RichTextPainter::paintRichText(painter, x, y, w, h, 4, richText, getCharWidth());
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void HexDump::printSelected(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
|
|
@ -434,45 +553,56 @@ bool HexDump::isSelected(dsint rva)
|
|||
return false;
|
||||
}
|
||||
|
||||
void HexDump::getString(int col, dsint rva, RichTextPainter::List & richText)
|
||||
void HexDump::getColumnRichText(int col, dsint rva, RichTextPainter::List & richText)
|
||||
{
|
||||
int wI;
|
||||
QString wStr = "";
|
||||
|
||||
int wByteCount = getSizeOf(mDescriptor.at(col).data.itemSize);
|
||||
int wBufferByteCount = mDescriptor.at(col).itemCount * wByteCount;
|
||||
|
||||
wBufferByteCount = wBufferByteCount > (dsint)(mMemPage->getSize() - rva) ? mMemPage->getSize() - rva : wBufferByteCount;
|
||||
|
||||
byte_t* wData = new byte_t[wBufferByteCount];
|
||||
//byte_t wData[mDescriptor.at(col).itemCount * wByteCount];
|
||||
|
||||
mMemPage->read(wData, rva, wBufferByteCount);
|
||||
|
||||
RichTextPainter::CustomRichText_t curData;
|
||||
curData.highlight = false;
|
||||
curData.flags = RichTextPainter::FlagColor;
|
||||
|
||||
QColor highlightColor = ConfigColor("HexDumpModifiedBytesColor");
|
||||
|
||||
for(wI = 0; wI < mDescriptor.at(col).itemCount && (rva + wI) < (dsint)mMemPage->getSize(); wI++)
|
||||
curData.textColor = textColor;
|
||||
if(!col) //address
|
||||
{
|
||||
int maxLen = getStringMaxLength(mDescriptor.at(col).data);
|
||||
QString append = " ";
|
||||
if(!maxLen)
|
||||
append = "";
|
||||
if((rva + wI + wByteCount - 1) < (dsint)mMemPage->getSize())
|
||||
wStr = toString(mDescriptor.at(col).data, (void*)(wData + wI * wByteCount)).rightJustified(maxLen, ' ') + append;
|
||||
else
|
||||
wStr = QString("?").rightJustified(maxLen, ' ') + append;
|
||||
curData.text = wStr;
|
||||
dsint start = rvaToVa(rva + wI * wByteCount);
|
||||
dsint end = start + wByteCount - 1;
|
||||
curData.textColor = DbgFunctions()->PatchInRange(start, end) ? highlightColor : textColor;
|
||||
curData.text = makeAddrText(rvaToVa(rva));
|
||||
richText.push_back(curData);
|
||||
}
|
||||
else if(mDescriptor.at(col - 1).isData == true)
|
||||
{
|
||||
int wI;
|
||||
QString wStr = "";
|
||||
|
||||
delete[] wData;
|
||||
int wByteCount = getSizeOf(mDescriptor.at(col - 1).data.itemSize);
|
||||
int wBufferByteCount = mDescriptor.at(col - 1).itemCount * wByteCount;
|
||||
|
||||
wBufferByteCount = wBufferByteCount > (dsint)(mMemPage->getSize() - rva) ? mMemPage->getSize() - rva : wBufferByteCount;
|
||||
|
||||
byte_t* wData = new byte_t[wBufferByteCount];
|
||||
//byte_t wData[mDescriptor.at(col).itemCount * wByteCount];
|
||||
|
||||
mMemPage->read(wData, rva, wBufferByteCount);
|
||||
|
||||
QColor highlightColor = ConfigColor("HexDumpModifiedBytesColor");
|
||||
|
||||
for(wI = 0; wI < mDescriptor.at(col - 1).itemCount && (rva + wI) < (dsint)mMemPage->getSize(); wI++)
|
||||
{
|
||||
int maxLen = getStringMaxLength(mDescriptor.at(col - 1).data);
|
||||
QString append = " ";
|
||||
if(!maxLen)
|
||||
append = "";
|
||||
if((rva + wI + wByteCount - 1) < (dsint)mMemPage->getSize())
|
||||
wStr = toString(mDescriptor.at(col - 1).data, (void*)(wData + wI * wByteCount)).rightJustified(maxLen, ' ') + append;
|
||||
else
|
||||
wStr = QString("?").rightJustified(maxLen, ' ') + append;
|
||||
curData.text = wStr;
|
||||
dsint start = rvaToVa(rva + wI * wByteCount);
|
||||
dsint end = start + wByteCount - 1;
|
||||
if(DbgFunctions()->PatchInRange(start, end))
|
||||
curData.textColor = highlightColor;
|
||||
else
|
||||
curData.textColor = textColor;
|
||||
richText.push_back(curData);
|
||||
}
|
||||
|
||||
delete[] wData;
|
||||
}
|
||||
}
|
||||
|
||||
QString HexDump::toString(DataDescriptor_t desc, void* data) //convert data to string
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ public:
|
|||
// Configuration
|
||||
virtual void updateColors();
|
||||
virtual void updateFonts();
|
||||
virtual void updateShortcuts();
|
||||
|
||||
//QString getStringToPrint(int rowBase, int rowOffset, int col);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
|
|
@ -101,7 +102,7 @@ public:
|
|||
dsint getSelectionEnd();
|
||||
bool isSelected(dsint rva);
|
||||
|
||||
void getString(int col, dsint rva, RichTextPainter::List & richText);
|
||||
virtual void getColumnRichText(int col, dsint rva, RichTextPainter::List & richText);
|
||||
int getSizeOf(DataSize_e size);
|
||||
|
||||
QString toString(DataDescriptor_t desc, void* data);
|
||||
|
|
@ -134,6 +135,8 @@ public:
|
|||
void printDumpAt(dsint parVA, bool select, bool repaint = true, bool updateTableOffset = true);
|
||||
duint rvaToVa(dsint rva);
|
||||
duint getTableOffsetRva();
|
||||
QString makeAddrText(duint va);
|
||||
QString makeCopyText();
|
||||
|
||||
void addVaToHistory(dsint parVa);
|
||||
bool historyHasPrev();
|
||||
|
|
@ -142,6 +145,8 @@ public:
|
|||
void historyNext();
|
||||
void historyClear();
|
||||
|
||||
void setupCopyMenu();
|
||||
|
||||
signals:
|
||||
void selectionUpdated();
|
||||
|
||||
|
|
@ -149,6 +154,9 @@ public slots:
|
|||
void printDumpAt(dsint parVA);
|
||||
void debugStateChanged(DBGSTATE state);
|
||||
void updateDumpSlot();
|
||||
void copySelectionSlot();
|
||||
void copyAddressSlot();
|
||||
void copyRvaSlot();
|
||||
|
||||
private:
|
||||
enum GuiState_t {NoState, MultiRowsSelectionState};
|
||||
|
|
@ -176,6 +184,9 @@ protected:
|
|||
duint mRvaDisplayBase;
|
||||
dsint mRvaDisplayPageBase;
|
||||
QString mSyncAddrExpression;
|
||||
QAction* mCopyAddress;
|
||||
QAction* mCopyRva;
|
||||
QAction* mCopySelection;
|
||||
};
|
||||
|
||||
#endif // _HEXDUMP_H
|
||||
|
|
|
|||
|
|
@ -459,22 +459,7 @@ void CPUDump::setupContextMenu()
|
|||
mPluginMenu->setIcon(QIcon(":/icons/images/plugin.png"));
|
||||
Bridge::getBridge()->emitMenuAddToList(this, mPluginMenu, GUI_DUMP_MENU);
|
||||
|
||||
//Copy
|
||||
mCopyMenu = new QMenu(tr("&Copy"), this);
|
||||
mCopyMenu->setIcon(QIcon(":/icons/images/copy.png"));
|
||||
|
||||
// Copy -> Address
|
||||
mCopyAddress = new QAction(tr("&Address"), this);
|
||||
connect(mCopyAddress, SIGNAL(triggered()), this, SLOT(copyAddressSlot()));
|
||||
mCopyAddress->setShortcutContext(Qt::WidgetShortcut);
|
||||
this->addAction(mCopyAddress);
|
||||
mCopyMenu->addAction(mCopyAddress);
|
||||
|
||||
// Copy -> RVA
|
||||
mCopyRva = new QAction("&RVA", this);
|
||||
connect(mCopyRva, SIGNAL(triggered()), this, SLOT(copyRvaSlot()));
|
||||
mCopyMenu->addAction(mCopyRva);
|
||||
|
||||
updateShortcuts();
|
||||
refreshShortcutsSlot();
|
||||
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcutsSlot()));
|
||||
}
|
||||
|
|
@ -497,7 +482,51 @@ void CPUDump::refreshShortcutsSlot()
|
|||
mGotoEnd->setShortcut(ConfigShortcut("ActionGotoEnd"));
|
||||
mGotoFileOffset->setShortcut(ConfigShortcut("ActionGotoFileOffset"));
|
||||
mYaraAction->setShortcut(ConfigShortcut("ActionYara"));
|
||||
mCopyAddress->setShortcut(ConfigShortcut("ActionCopyAddress"));
|
||||
}
|
||||
|
||||
void CPUDump::getColumnRichText(int col, dsint rva, RichTextPainter::List & richText)
|
||||
{
|
||||
if(col && !mDescriptor.at(col - 1).isData && mDescriptor.at(col - 1).itemCount) //print comments
|
||||
{
|
||||
RichTextPainter::CustomRichText_t curData;
|
||||
curData.flags = RichTextPainter::FlagColor;
|
||||
curData.textColor = textColor;
|
||||
duint data = 0;
|
||||
mMemPage->read((byte_t*)&data, rva, sizeof(duint));
|
||||
|
||||
char modname[MAX_MODULE_SIZE] = "";
|
||||
if(!DbgGetModuleAt(data, modname))
|
||||
modname[0] = '\0';
|
||||
char label_text[MAX_LABEL_SIZE] = "";
|
||||
if(DbgGetLabelAt(data, SEG_DEFAULT, label_text))
|
||||
curData.text = QString(modname) + "." + QString(label_text);
|
||||
char string_text[MAX_STRING_SIZE] = "";
|
||||
if(DbgGetStringAt(data, string_text))
|
||||
curData.text = string_text;
|
||||
if(!curData.text.length()) //stack comments
|
||||
{
|
||||
auto va = rvaToVa(rva);
|
||||
duint stackSize;
|
||||
duint csp = DbgValFromString("csp");
|
||||
duint stackBase = DbgMemFindBaseAddr(csp, &stackSize);
|
||||
STACK_COMMENT comment;
|
||||
if(va >= stackBase && va < stackBase + stackSize && DbgStackCommentGet(va, &comment))
|
||||
{
|
||||
if(va >= csp) //active stack
|
||||
{
|
||||
if(*comment.color)
|
||||
curData.textColor = QColor(QString(comment.color));
|
||||
}
|
||||
else
|
||||
curData.textColor = ConfigColor("StackInactiveTextColor");
|
||||
curData.text = comment.comment;
|
||||
}
|
||||
}
|
||||
if(curData.text.length())
|
||||
richText.push_back(curData);
|
||||
}
|
||||
else
|
||||
HexDump::getColumnRichText(col, rva, richText);
|
||||
}
|
||||
|
||||
QString CPUDump::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
|
|
@ -506,111 +535,27 @@ QString CPUDump::paintContent(QPainter* painter, dsint rowBase, int rowOffset, i
|
|||
if(rowBase == 0 && mByteOffset != 0)
|
||||
printDumpAt(mMemPage->getBase(), false, false);
|
||||
|
||||
QString wStr = "";
|
||||
if(!col) //address
|
||||
{
|
||||
char label[MAX_LABEL_SIZE] = "";
|
||||
QString addrText = "";
|
||||
dsint cur_addr = rvaToVa((rowBase + rowOffset) * getBytePerRowCount() - mByteOffset);
|
||||
if(mRvaDisplayEnabled) //RVA display
|
||||
QColor background;
|
||||
if(DbgGetLabelAt(cur_addr, SEG_DEFAULT, label)) //label
|
||||
{
|
||||
dsint rva = cur_addr - mRvaDisplayBase;
|
||||
if(rva == 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$ ==> ";
|
||||
#else
|
||||
addrText = "$ ==> ";
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(rva > 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$+" + QString("%1").arg(rva, -15, 16, QChar(' ')).toUpper();
|
||||
#else
|
||||
addrText = "$+" + QString("%1").arg(rva, -7, 16, QChar(' ')).toUpper();
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(rva < 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$-" + QString("%1").arg(-rva, -15, 16, QChar(' ')).toUpper();
|
||||
#else
|
||||
addrText = "$-" + QString("%1").arg(-rva, -7, 16, QChar(' ')).toUpper();
|
||||
#endif //_WIN64
|
||||
}
|
||||
}
|
||||
addrText += QString("%1").arg(cur_addr, sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
if(DbgGetLabelAt(cur_addr, SEG_DEFAULT, label)) //has label
|
||||
{
|
||||
char module[MAX_MODULE_SIZE] = "";
|
||||
if(DbgGetModuleAt(cur_addr, module) && !QString(label).startsWith("JMP.&"))
|
||||
addrText += " <" + QString(module) + "." + QString(label) + ">";
|
||||
else
|
||||
addrText += " <" + QString(label) + ">";
|
||||
}
|
||||
else
|
||||
*label = 0;
|
||||
if(*label) //label
|
||||
{
|
||||
QColor background = ConfigColor("HexDumpLabelBackgroundColor");
|
||||
if(background.alpha())
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(background)); //fill bookmark color
|
||||
background = ConfigColor("HexDumpLabelBackgroundColor");
|
||||
painter->setPen(ConfigColor("HexDumpLabelColor")); //TODO: config
|
||||
}
|
||||
else
|
||||
{
|
||||
QColor background = ConfigColor("HexDumpAddressBackgroundColor");
|
||||
if(background.alpha())
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(background)); //fill bookmark color
|
||||
background = ConfigColor("HexDumpAddressBackgroundColor");
|
||||
painter->setPen(ConfigColor("HexDumpAddressColor")); //TODO: config
|
||||
}
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, addrText);
|
||||
if(background.alpha())
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(background)); //fill background color
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, makeAddrText(cur_addr));
|
||||
return "";
|
||||
}
|
||||
else if(mDescriptor.at(col - 1).isData) //print data
|
||||
{
|
||||
wStr = HexDump::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);
|
||||
}
|
||||
else if(!mDescriptor.at(col - 1).isData && mDescriptor.at(col - 1).itemCount) //print comments
|
||||
{
|
||||
duint data = 0;
|
||||
dsint wRva = (rowBase + rowOffset) * getBytePerRowCount() - mByteOffset;
|
||||
mMemPage->read((byte_t*)&data, wRva, sizeof(duint));
|
||||
|
||||
char modname[MAX_MODULE_SIZE] = "";
|
||||
if(!DbgGetModuleAt(data, modname))
|
||||
modname[0] = '\0';
|
||||
char label_text[MAX_LABEL_SIZE] = "";
|
||||
if(DbgGetLabelAt(data, SEG_DEFAULT, label_text))
|
||||
wStr = QString(modname) + "." + QString(label_text);
|
||||
char string_text[MAX_STRING_SIZE] = "";
|
||||
if(DbgGetStringAt(data, string_text))
|
||||
wStr = string_text;
|
||||
if(!wStr.length()) //stack comments
|
||||
{
|
||||
auto va = rvaToVa(wRva);
|
||||
duint stackSize;
|
||||
duint csp = DbgValFromString("csp");
|
||||
duint stackBase = DbgMemFindBaseAddr(csp, &stackSize);
|
||||
STACK_COMMENT comment;
|
||||
if(va >= stackBase && va < stackBase + stackSize && DbgStackCommentGet(rvaToVa(wRva), &comment))
|
||||
{
|
||||
painter->save();
|
||||
if(va >= csp) //active stack
|
||||
{
|
||||
if(*comment.color)
|
||||
painter->setPen(QPen(QColor(QString(comment.color))));
|
||||
else
|
||||
painter->setPen(QPen(textColor));
|
||||
}
|
||||
else
|
||||
painter->setPen(QPen(ConfigColor("StackInactiveTextColor")));
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, comment.comment);
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
return wStr;
|
||||
return HexDump::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);
|
||||
}
|
||||
|
||||
void CPUDump::contextMenuEvent(QContextMenuEvent* event)
|
||||
|
|
@ -619,12 +564,19 @@ void CPUDump::contextMenuEvent(QContextMenuEvent* event)
|
|||
return;
|
||||
|
||||
dsint selectedAddr = rvaToVa(getInitialSelection());
|
||||
dsint start = rvaToVa(getSelectionStart());
|
||||
dsint end = rvaToVa(getSelectionEnd());
|
||||
|
||||
QMenu wMenu(this); //create context menu
|
||||
wMenu.addMenu(mBinaryMenu);
|
||||
wMenu.addMenu(mCopyMenu);
|
||||
dsint start = rvaToVa(getSelectionStart());
|
||||
dsint end = rvaToVa(getSelectionEnd());
|
||||
QMenu wCopyMenu("&Copy", this);
|
||||
wCopyMenu.setIcon(QIcon(":/icons/images/copy.png"));
|
||||
wCopyMenu.addAction(mCopySelection);
|
||||
wCopyMenu.addAction(mCopyAddress);
|
||||
if(DbgFunctions()->ModBaseFromAddr(selectedAddr))
|
||||
wCopyMenu.addAction(mCopyRva);
|
||||
wMenu.addMenu(&wCopyMenu);
|
||||
|
||||
if(DbgFunctions()->PatchInRange(start, end)) //nothing patched in selected range
|
||||
wMenu.addAction(mUndoSelection);
|
||||
if(DbgMemIsValidReadPtr(start) && DbgMemFindBaseAddr(start, 0) == DbgMemFindBaseAddr(DbgValFromString("csp"), 0))
|
||||
|
|
@ -1681,25 +1633,6 @@ void CPUDump::syncWithExpressionSlot()
|
|||
DbgCmdExec(QString("dump \"%1\"").arg(mSyncAddrExpression).toUtf8().constData());
|
||||
}
|
||||
|
||||
void CPUDump::copyAddressSlot()
|
||||
{
|
||||
QString addrText = QString("%1").arg(rvaToVa(getInitialSelection()), sizeof(dsint) * 2, 16, QChar('0')).toUpper();
|
||||
Bridge::CopyToClipboard(addrText);
|
||||
}
|
||||
|
||||
void CPUDump::copyRvaSlot()
|
||||
{
|
||||
duint addr = rvaToVa(getInitialSelection());
|
||||
duint base = DbgFunctions()->ModBaseFromAddr(addr);
|
||||
if(base)
|
||||
{
|
||||
QString addrText = QString("%1").arg(addr - base, 0, 16, QChar('0')).toUpper();
|
||||
Bridge::CopyToClipboard(addrText);
|
||||
}
|
||||
else
|
||||
QMessageBox::warning(this, "Error!", "Selection not in a module...");
|
||||
}
|
||||
|
||||
void CPUDump::followInDumpNSlot()
|
||||
{
|
||||
for(int i = 0; i < mFollowInDumpActions.length(); i++)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class CPUDump : public HexDump
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit CPUDump(CPUDisassembly* disas, CPUMultiDump* multiDump, QWidget* parent = 0);
|
||||
void getColumnRichText(int col, dsint rva, RichTextPainter::List & richText) override;
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h);
|
||||
void setupContextMenu();
|
||||
void contextMenuEvent(QContextMenuEvent* event);
|
||||
|
|
@ -94,8 +95,6 @@ public slots:
|
|||
void dataCopySlot();
|
||||
void entropySlot();
|
||||
void syncWithExpressionSlot();
|
||||
void copyAddressSlot();
|
||||
void copyRvaSlot();
|
||||
void followInDumpNSlot();
|
||||
|
||||
void gotoNextSlot();
|
||||
|
|
@ -195,13 +194,9 @@ private:
|
|||
QAction* mFollowDataDump;
|
||||
QAction* mSyncWithExpression;
|
||||
QAction* mEntropy;
|
||||
QAction* mCopyAddress;
|
||||
QAction* mCopyRva;
|
||||
|
||||
QMenu* mSpecialMenu;
|
||||
QMenu* mCustomMenu;
|
||||
QMenu* mPluginMenu;
|
||||
QMenu* mCopyMenu;
|
||||
QMenu* mFollowInDumpMenu;
|
||||
QList<QAction*> mFollowInDumpActions;
|
||||
|
||||
|
|
|
|||
|
|
@ -308,12 +308,55 @@ void CPUStack::refreshShortcutsSlot()
|
|||
mGotoNext->setShortcut(ConfigShortcut("ActionGotoNext"));
|
||||
}
|
||||
|
||||
void CPUStack::getColumnRichText(int col, dsint rva, RichTextPainter::List & richText)
|
||||
{
|
||||
// Compute RVA
|
||||
dsint wRva = rva;
|
||||
duint wVa = rvaToVa(wRva);
|
||||
|
||||
bool wActiveStack = true;
|
||||
if(wVa < mCsp) //inactive stack
|
||||
wActiveStack = false;
|
||||
|
||||
STACK_COMMENT comment;
|
||||
RichTextPainter::CustomRichText_t curData;
|
||||
curData.highlight = false;
|
||||
curData.flags = RichTextPainter::FlagColor;
|
||||
curData.textColor = textColor;
|
||||
|
||||
if(col && mDescriptor.at(col - 1).isData == true) //paint stack data
|
||||
{
|
||||
HexDump::getColumnRichText(col, rva, richText);
|
||||
if(!wActiveStack)
|
||||
{
|
||||
QColor inactiveColor = ConfigColor("StackInactiveTextColor");
|
||||
for(int i = 0; i < int(richText.size()); i++)
|
||||
{
|
||||
richText[i].flags = RichTextPainter::FlagColor;
|
||||
richText[i].textColor = inactiveColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(col && DbgStackCommentGet(rvaToVa(wRva), &comment)) //paint stack comments
|
||||
{
|
||||
if(wActiveStack)
|
||||
{
|
||||
if(*comment.color)
|
||||
curData.textColor = QColor(QString(comment.color));
|
||||
else
|
||||
curData.textColor = textColor;
|
||||
}
|
||||
else
|
||||
curData.textColor = ConfigColor("StackInactiveTextColor");
|
||||
curData.text = comment.comment;
|
||||
richText.push_back(curData);
|
||||
}
|
||||
else
|
||||
HexDump::getColumnRichText(col, rva, richText);
|
||||
}
|
||||
|
||||
QString CPUStack::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
{
|
||||
// Reset byte offset when base address is reached
|
||||
if(rowBase == 0 && mByteOffset != 0)
|
||||
printDumpAt(mMemPage->getBase(), false, false);
|
||||
|
||||
// Compute RVA
|
||||
int wBytePerRowCount = getBytePerRowCount();
|
||||
dsint wRva = (rowBase + rowOffset) * wBytePerRowCount - mByteOffset;
|
||||
|
|
@ -327,58 +370,10 @@ QString CPUStack::paintContent(QPainter* painter, dsint rowBase, int rowOffset,
|
|||
if(wIsSelected) //highlight if selected
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(selectionColor));
|
||||
|
||||
bool wActiveStack = true;
|
||||
if(wVa < mCsp) //inactive stack
|
||||
wActiveStack = false;
|
||||
|
||||
STACK_COMMENT comment;
|
||||
|
||||
if(col == 0) // paint stack address
|
||||
{
|
||||
char label[MAX_LABEL_SIZE] = "";
|
||||
QString addrText = "";
|
||||
dsint cur_addr = rvaToVa((rowBase + rowOffset) * getBytePerRowCount() - mByteOffset);
|
||||
if(mRvaDisplayEnabled) //RVA display
|
||||
{
|
||||
dsint rva = cur_addr - mRvaDisplayBase;
|
||||
if(rva == 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$ ==> ";
|
||||
#else
|
||||
addrText = "$ ==> ";
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(rva > 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$+" + QString("%1").arg(rva, -15, 16, QChar(' ')).toUpper();
|
||||
#else
|
||||
addrText = "$+" + QString("%1").arg(rva, -7, 16, QChar(' ')).toUpper();
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(rva < 0)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
addrText = "$-" + QString("%1").arg(-rva, -15, 16, QChar(' ')).toUpper();
|
||||
#else
|
||||
addrText = "$-" + QString("%1").arg(-rva, -7, 16, QChar(' ')).toUpper();
|
||||
#endif //_WIN64
|
||||
}
|
||||
}
|
||||
addrText += ToPtrString(cur_addr);
|
||||
if(DbgGetLabelAt(cur_addr, SEG_DEFAULT, label)) //has label
|
||||
{
|
||||
char module[MAX_MODULE_SIZE] = "";
|
||||
if(DbgGetModuleAt(cur_addr, module) && !QString(label).startsWith("JMP.&"))
|
||||
addrText += " <" + QString(module) + "." + QString(label) + ">";
|
||||
else
|
||||
addrText += " <" + QString(label) + ">";
|
||||
}
|
||||
else
|
||||
*label = 0;
|
||||
QColor background;
|
||||
if(*label) //label
|
||||
if(DbgGetLabelAt(wVa, SEG_DEFAULT, nullptr)) //label
|
||||
{
|
||||
if(wVa == mCsp) //CSP
|
||||
{
|
||||
|
|
@ -411,41 +406,10 @@ QString CPUStack::paintContent(QPainter* painter, dsint rowBase, int rowOffset,
|
|||
}
|
||||
if(background.alpha())
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(background)); //fill background when defined
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, addrText);
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, makeAddrText(wVa));
|
||||
return "";
|
||||
}
|
||||
else if(mDescriptor.at(col - 1).isData == true) //paint stack data
|
||||
{
|
||||
int wBytePerRowCount = getBytePerRowCount();
|
||||
dsint wRva = (rowBase + rowOffset) * wBytePerRowCount - mByteOffset;
|
||||
printSelected(painter, rowBase, rowOffset, col, x, y, w, h);
|
||||
RichTextPainter::List richText;
|
||||
getString(col - 1, wRva, richText);
|
||||
if(!wActiveStack)
|
||||
{
|
||||
QColor inactiveColor = ConfigColor("StackInactiveTextColor");
|
||||
for(int i = 0; i < int(richText.size()); i++)
|
||||
{
|
||||
richText[i].flags = RichTextPainter::FlagColor;
|
||||
richText[i].textColor = inactiveColor;
|
||||
}
|
||||
}
|
||||
RichTextPainter::paintRichText(painter, x, y, w, h, 4, richText, getCharWidth());
|
||||
}
|
||||
else if(DbgStackCommentGet(rvaToVa(wRva), &comment)) //paint stack comments
|
||||
{
|
||||
QString wStr = QString(comment.comment);
|
||||
if(wActiveStack)
|
||||
{
|
||||
if(*comment.color)
|
||||
painter->setPen(QPen(QColor(QString(comment.color))));
|
||||
else
|
||||
painter->setPen(QPen(textColor));
|
||||
}
|
||||
else
|
||||
painter->setPen(QPen(ConfigColor("StackInactiveTextColor")));
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, wStr);
|
||||
}
|
||||
return "";
|
||||
return HexDump::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);;
|
||||
}
|
||||
|
||||
void CPUStack::contextMenuEvent(QContextMenuEvent* event)
|
||||
|
|
@ -458,6 +422,13 @@ void CPUStack::contextMenuEvent(QContextMenuEvent* event)
|
|||
QMenu wMenu(this); //create context menu
|
||||
wMenu.addAction(mModifyAction);
|
||||
wMenu.addMenu(mBinaryMenu);
|
||||
QMenu wCopyMenu("&Copy", this);
|
||||
wCopyMenu.setIcon(QIcon(":/icons/images/copy.png"));
|
||||
wCopyMenu.addAction(mCopySelection);
|
||||
wCopyMenu.addAction(mCopyAddress);
|
||||
if(DbgFunctions()->ModBaseFromAddr(selectedAddr))
|
||||
wCopyMenu.addAction(mCopyRva);
|
||||
wMenu.addMenu(&wCopyMenu);
|
||||
wMenu.addMenu(mBreakpointMenu);
|
||||
dsint start = rvaToVa(getSelectionStart());
|
||||
dsint end = rvaToVa(getSelectionEnd());
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ public:
|
|||
virtual void updateColors();
|
||||
virtual void updateFonts();
|
||||
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h);
|
||||
void getColumnRichText(int col, dsint rva, RichTextPainter::List & richText) override;
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override;
|
||||
void contextMenuEvent(QContextMenuEvent* event);
|
||||
void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
void setupContextMenu();
|
||||
|
|
|
|||
Loading…
Reference in New Issue