1
0
Fork 0
x64dbg/src/gui/Src/Gui/CPUDump.cpp

1620 lines
58 KiB
C++

#include "CPUDump.h"
#include <QMessageBox>
#include <QClipboard>
#include <QFileDialog>
#include <QToolTip>
#include "Configuration.h"
#include "Bridge.h"
#include "HexEditDialog.h"
#include "CPUMultiDump.h"
#include "GotoDialog.h"
#include "CPUDisassembly.h"
#include "CommonActions.h"
#include "WordEditDialog.h"
#include "CodepageSelectionDialog.h"
#include "MiscUtil.h"
#include "BackgroundFlickerThread.h"
CPUDump::CPUDump(CPUDisassembly* disas, CPUMultiDump* multiDump, QWidget* parent) : HexDump(parent)
{
mDisas = disas;
mMultiDump = multiDump;
duint setting;
if(BridgeSettingGetUint("Gui", "AsciiSeparator", &setting))
mAsciiSeparator = setting & 0xF;
setView((ViewEnum_t)ConfigUint("HexDump", "DefaultView"));
connect(this, SIGNAL(selectionUpdated()), this, SLOT(selectionUpdatedSlot()));
connect(this, SIGNAL(headerButtonReleased(int)), this, SLOT(headerButtonReleasedSlot(int)));
mPluginMenu = multiDump->mDumpPluginMenu;
setupContextMenu();
}
void CPUDump::setupContextMenu()
{
mMenuBuilder = new MenuBuilder(this, [](QMenu*)
{
return DbgIsDebugging();
});
mCommonActions = new CommonActions(this, getActionHelperFuncs(), [this]()
{
return rvaToVa(getSelectionStart());
});
MenuBuilder* binaryMenu = new MenuBuilder(this);
binaryMenu->addAction(makeShortcutAction(DIcon("binary_edit"), tr("&Edit"), SLOT(binaryEditSlot()), "ActionBinaryEdit"));
binaryMenu->addAction(makeShortcutAction(DIcon("binary_fill"), tr("&Fill..."), SLOT(binaryFillSlot()), "ActionBinaryFill"));
binaryMenu->addSeparator();
binaryMenu->addAction(makeShortcutAction(DIcon("binary_copy"), tr("&Copy"), SLOT(binaryCopySlot()), "ActionBinaryCopy"));
binaryMenu->addAction(makeShortcutAction(DIcon("binary_paste"), tr("&Paste"), SLOT(binaryPasteSlot()), "ActionBinaryPaste"), [](QMenu*)
{
return QApplication::clipboard()->mimeData()->hasText();
});
binaryMenu->addAction(makeShortcutAction(DIcon("binary_paste_ignoresize"), tr("Paste (&Ignore Size)"), SLOT(binaryPasteIgnoreSizeSlot()), "ActionBinaryPasteIgnoreSize"), [](QMenu*)
{
return QApplication::clipboard()->mimeData()->hasText();
});
binaryMenu->addAction(makeShortcutAction(DIcon("binary_save"), tr("Save To a File"), SLOT(binarySaveToFileSlot()), "ActionBinarySave"));
mMenuBuilder->addMenu(makeMenu(DIcon("binary"), tr("B&inary")), binaryMenu);
MenuBuilder* copyMenu = new MenuBuilder(this);
copyMenu->addAction(mCopySelection);
copyMenu->addAction(mCopyAddress);
copyMenu->addAction(mCopyRva, [this](QMenu*)
{
return DbgFunctions()->ModBaseFromAddr(rvaToVa(getInitialSelection())) != 0;
});
copyMenu->addAction(makeShortcutAction(DIcon("fileoffset"), tr("&File Offset"), SLOT(copyFileOffsetSlot()), "ActionCopyFileOffset"), [this](QMenu*)
{
return DbgFunctions()->VaToFileOffset(rvaToVa(getInitialSelection())) != 0;
});
mMenuBuilder->addMenu(makeMenu(DIcon("copy"), tr("&Copy")), copyMenu);
mMenuBuilder->addAction(makeShortcutAction(DIcon("eraser"), tr("&Restore selection"), SLOT(undoSelectionSlot()), "ActionUndoSelection"), [this](QMenu*)
{
return DbgFunctions()->PatchInRange(rvaToVa(getSelectionStart()), rvaToVa(getSelectionEnd()));
});
mCommonActions->build(mMenuBuilder, CommonActions::ActionDisasm | CommonActions::ActionMemoryMap | CommonActions::ActionDumpData | CommonActions::ActionDumpN
| CommonActions::ActionDisasmData | CommonActions::ActionStackDump | CommonActions::ActionLabel | CommonActions::ActionWatch);
mMenuBuilder->addAction(makeShortcutAction(DIcon("modify"), tr("&Modify Value"), SLOT(modifyValueSlot()), "ActionModifyValue"), [this](QMenu*)
{
auto d = mDescriptor.at(0).data;
return getSizeOf(d.itemSize) <= sizeof(duint) || (d.itemSize == 4 && d.dwordMode == FloatDword || d.itemSize == 8 && d.qwordMode == DoubleQword);
});
MenuBuilder* breakpointMenu = new MenuBuilder(this);
MenuBuilder* hardwareAccessMenu = new MenuBuilder(this, [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_hardware) == 0;
});
MenuBuilder* hardwareWriteMenu = new MenuBuilder(this, [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_hardware) == 0;
});
MenuBuilder* memoryAccessMenu = new MenuBuilder(this, [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_memory) == 0;
});
MenuBuilder* memoryReadMenu = new MenuBuilder(this, [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_memory) == 0;
});
MenuBuilder* memoryWriteMenu = new MenuBuilder(this, [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_memory) == 0;
});
MenuBuilder* memoryExecuteMenu = new MenuBuilder(this, [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_memory) == 0;
});
hardwareAccessMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_byte"), tr("&Byte"), "bphws $, r, 1"));
hardwareAccessMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_word"), tr("&Word"), "bphws $, r, 2"));
hardwareAccessMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_dword"), tr("&Dword"), "bphws $, r, 4"));
#ifdef _WIN64
hardwareAccessMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_qword"), tr("&Qword"), "bphws $, r, 8"));
#endif //_WIN64
hardwareWriteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_byte"), tr("&Byte"), "bphws $, w, 1"));
hardwareWriteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_word"), tr("&Word"), "bphws $, w, 2"));
hardwareWriteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_dword"), tr("&Dword"), "bphws $, w, 4"));
#ifdef _WIN64
hardwareWriteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_qword"), tr("&Qword"), "bphws $, w, 8"));
#endif //_WIN64
breakpointMenu->addMenu(makeMenu(DIcon("breakpoint_access"), tr("Hardware, &Access")), hardwareAccessMenu);
breakpointMenu->addMenu(makeMenu(DIcon("breakpoint_write"), tr("Hardware, &Write")), hardwareWriteMenu);
breakpointMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_execute"), tr("Hardware, &Execute"), "bphws $, x"), [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_hardware) == 0;
});
breakpointMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_remove"), tr("Remove &Hardware"), "bphwc $"), [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_hardware) != 0;
});
breakpointMenu->addSeparator();
memoryAccessMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_singleshoot"), tr("&Singleshoot"), "bpm $, 0, a"));
memoryAccessMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_restore_on_hit"), tr("&Restore on hit"), "bpm $, 1, a"));
memoryReadMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_singleshoot"), tr("&Singleshoot"), "bpm $, 0, r"));
memoryReadMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_restore_on_hit"), tr("&Restore on hit"), "bpm $, 1, r"));
memoryWriteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_singleshoot"), tr("&Singleshoot"), "bpm $, 0, w"));
memoryWriteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_restore_on_hit"), tr("&Restore on hit"), "bpm $, 1, w"));
memoryExecuteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_singleshoot"), tr("&Singleshoot"), "bpm $, 0, x"));
memoryExecuteMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_memory_restore_on_hit"), tr("&Restore on hit"), "bpm $, 1, x"));
breakpointMenu->addMenu(makeMenu(DIcon("breakpoint_memory_access"), tr("Memory, Access")), memoryAccessMenu);
breakpointMenu->addMenu(makeMenu(DIcon("breakpoint_memory_read"), tr("Memory, Read")), memoryReadMenu);
breakpointMenu->addMenu(makeMenu(DIcon("breakpoint_memory_write"), tr("Memory, Write")), memoryWriteMenu);
breakpointMenu->addMenu(makeMenu(DIcon("breakpoint_memory_execute"), tr("Memory, Execute")), memoryExecuteMenu);
breakpointMenu->addAction(mCommonActions->makeCommandAction(DIcon("breakpoint_remove"), tr("Remove &Memory"), "bpmc $"), [this](QMenu*)
{
return (DbgGetBpxTypeAt(rvaToVa(getSelectionStart())) & bp_memory) != 0;
});
mMenuBuilder->addMenu(makeMenu(DIcon("breakpoint"), tr("&Breakpoint")), breakpointMenu);
mMenuBuilder->addAction(makeShortcutAction(DIcon("search-for"), tr("&Find Pattern..."), SLOT(findPattern()), "ActionFindPattern"));
mMenuBuilder->addAction(makeShortcutAction(DIcon("find"), tr("Find &References"), SLOT(findReferencesSlot()), "ActionFindReferences"));
mMenuBuilder->addAction(makeShortcutAction(DIcon("sync"), tr("&Sync with expression"), SLOT(syncWithExpressionSlot()), "ActionSync"));
mMenuBuilder->addAction(makeShortcutAction(DIcon("memmap_alloc_memory"), tr("Allocate Memory"), SLOT(allocMemorySlot()), "ActionAllocateMemory"));
MenuBuilder* gotoMenu = new MenuBuilder(this);
gotoMenu->addAction(makeShortcutAction(DIcon("geolocation-goto"), tr("&Expression"), SLOT(gotoExpressionSlot()), "ActionGotoExpression"));
gotoMenu->addAction(makeShortcutAction(DIcon("fileoffset"), tr("File Offset"), SLOT(gotoFileOffsetSlot()), "ActionGotoFileOffset"));
gotoMenu->addAction(makeShortcutAction(DIcon("top"), tr("Start of Page"), SLOT(gotoStartSlot()), "ActionGotoStart"), [this](QMenu*)
{
return getSelectionStart() != 0;
});
gotoMenu->addAction(makeShortcutAction(DIcon("bottom"), tr("End of Page"), SLOT(gotoEndSlot()), "ActionGotoEnd"));
gotoMenu->addAction(makeShortcutAction(DIcon("previous"), tr("Previous"), SLOT(gotoPreviousSlot()), "ActionGotoPrevious"), [this](QMenu*)
{
return mHistory.historyHasPrev();
});
gotoMenu->addAction(makeShortcutAction(DIcon("next"), tr("Next"), SLOT(gotoNextSlot()), "ActionGotoNext"), [this](QMenu*)
{
return mHistory.historyHasNext();
});
gotoMenu->addAction(makeShortcutAction(DIcon("prevref"), tr("Previous Reference"), SLOT(gotoPreviousReferenceSlot()), "ActionGotoPreviousReference"), [](QMenu*)
{
return !!DbgEval("refsearch.count() && ($__dump_refindex > 0 || dump.sel() != refsearch.addr($__dump_refindex))");
});
gotoMenu->addAction(makeShortcutAction(DIcon("nextref"), tr("Next Reference"), SLOT(gotoNextReferenceSlot()), "ActionGotoNextReference"), [](QMenu*)
{
return !!DbgEval("refsearch.count() && ($__dump_refindex < refsearch.count() || dump.sel() != refsearch.addr($__dump_refindex))");
});
mMenuBuilder->addMenu(makeMenu(DIcon("goto"), tr("&Go to")), gotoMenu);
mMenuBuilder->addSeparator();
MenuBuilder* hexMenu = new MenuBuilder(this);
hexMenu->addAction(makeAction(DIcon("ascii"), tr("&ASCII"), SLOT(hexAsciiSlot())));
hexMenu->addAction(makeAction(DIcon("ascii-extended"), tr("&Extended ASCII"), SLOT(hexUnicodeSlot())));
QAction* hexLastCodepage = makeAction(DIcon("codepage"), "?", SLOT(hexLastCodepageSlot()));
hexMenu->addAction(hexLastCodepage, [hexLastCodepage](QMenu*)
{
duint lastCodepage;
auto allCodecs = QTextCodec::availableCodecs();
if(!BridgeSettingGetUint("Misc", "LastCodepage", &lastCodepage) || lastCodepage >= duint(allCodecs.size()))
return false;
hexLastCodepage->setText(QString::fromLocal8Bit(allCodecs.at(lastCodepage)));
return true;
});
hexMenu->addAction(makeAction(DIcon("codepage"), tr("&Codepage..."), SLOT(hexCodepageSlot())));
mMenuBuilder->addMenu(makeMenu(DIcon("hex"), tr("&Hex")), hexMenu);
MenuBuilder* textMenu = new MenuBuilder(this);
textMenu->addAction(makeAction(DIcon("ascii"), tr("&ASCII"), SLOT(textAsciiSlot())));
textMenu->addAction(makeAction(DIcon("ascii-extended"), tr("&Extended ASCII"), SLOT(textUnicodeSlot())));
QAction* textLastCodepage = makeAction(DIcon("codepage"), "?", SLOT(textLastCodepageSlot()));
textMenu->addAction(textLastCodepage, [textLastCodepage](QMenu*)
{
duint lastCodepage;
auto allCodecs = QTextCodec::availableCodecs();
if(!BridgeSettingGetUint("Misc", "LastCodepage", &lastCodepage) || lastCodepage >= duint(allCodecs.size()))
return false;
textLastCodepage->setText(QString::fromLocal8Bit(allCodecs.at(lastCodepage)));
return true;
});
textMenu->addAction(makeAction(DIcon("codepage"), tr("&Codepage..."), SLOT(textCodepageSlot())));
mMenuBuilder->addMenu(makeMenu(DIcon("strings"), tr("&Text")), textMenu);
MenuBuilder* integerMenu = new MenuBuilder(this);
integerMenu->addAction(makeAction(DIcon("byte"), tr("Signed byte (8-bit)"), SLOT(integerSignedByteSlot())));
integerMenu->addAction(makeAction(DIcon("word"), tr("Signed short (16-bit)"), SLOT(integerSignedShortSlot())));
integerMenu->addAction(makeAction(DIcon("dword"), tr("Signed long (32-bit)"), SLOT(integerSignedLongSlot())));
integerMenu->addAction(makeAction(DIcon("qword"), tr("Signed long long (64-bit)"), SLOT(integerSignedLongLongSlot())));
integerMenu->addAction(makeAction(DIcon("byte"), tr("Unsigned byte (8-bit)"), SLOT(integerUnsignedByteSlot())));
integerMenu->addAction(makeAction(DIcon("word"), tr("Unsigned short (16-bit)"), SLOT(integerUnsignedShortSlot())));
integerMenu->addAction(makeAction(DIcon("dword"), tr("Unsigned long (32-bit)"), SLOT(integerUnsignedLongSlot())));
integerMenu->addAction(makeAction(DIcon("qword"), tr("Unsigned long long (64-bit)"), SLOT(integerUnsignedLongLongSlot())));
integerMenu->addAction(makeAction(DIcon("word"), tr("Hex short (16-bit)"), SLOT(integerHexShortSlot())));
integerMenu->addAction(makeAction(DIcon("dword"), tr("Hex long (32-bit)"), SLOT(integerHexLongSlot())));
integerMenu->addAction(makeAction(DIcon("qword"), tr("Hex long long (64-bit)"), SLOT(integerHexLongLongSlot())));
mMenuBuilder->addMenu(makeMenu(DIcon("integer"), tr("&Integer")), integerMenu);
MenuBuilder* floatMenu = new MenuBuilder(this);
floatMenu->addAction(makeAction(DIcon("32bit-float"), tr("&Float (32-bit)"), SLOT(floatFloatSlot())));
floatMenu->addAction(makeAction(DIcon("64bit-float"), tr("&Double (64-bit)"), SLOT(floatDoubleSlot())));
floatMenu->addAction(makeAction(DIcon("80bit-float"), tr("&Long double (80-bit)"), SLOT(floatLongDoubleSlot())));
mMenuBuilder->addMenu(makeMenu(DIcon("float"), tr("&Float")), floatMenu);
mMenuBuilder->addAction(makeAction(DIcon("address"), tr("&Address"), SLOT(addressAsciiSlot())));
mMenuBuilder->addAction(makeAction(DIcon("processor-cpu"), tr("&Disassembly"), SLOT(disassemblySlot())));
mMenuBuilder->addSeparator();
mMenuBuilder->addBuilder(new MenuBuilder(this, [this](QMenu * menu)
{
DbgMenuPrepare(GUI_DUMP_MENU);
menu->addActions(mPluginMenu->actions());
return true;
}));
mMenuBuilder->loadFromConfig();
updateShortcuts();
}
void CPUDump::getAttention()
{
BackgroundFlickerThread* thread = new BackgroundFlickerThread(this, mBackgroundColor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
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 = mTextColor;
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] = "";
char string_text[MAX_STRING_SIZE] = "";
if(DbgGetLabelAt(data, SEG_DEFAULT, label_text))
curData.text = QString(modname) + "." + QString(label_text);
else 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)
{
// Reset byte offset when base address is reached
if(rowBase == 0 && mByteOffset != 0)
printDumpAt(mMemPage->getBase(), false, false);
if(!col) //address
{
char label[MAX_LABEL_SIZE] = "";
dsint cur_addr = rvaToVa((rowBase + rowOffset) * getBytePerRowCount() - mByteOffset);
QColor background;
if(DbgGetLabelAt(cur_addr, SEG_DEFAULT, label)) //label
{
background = ConfigColor("HexDumpLabelBackgroundColor");
painter->setPen(ConfigColor("HexDumpLabelColor")); //TODO: config
}
else
{
background = ConfigColor("HexDumpAddressBackgroundColor");
painter->setPen(ConfigColor("HexDumpAddressColor")); //TODO: config
}
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 QString();
}
return HexDump::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);
}
void CPUDump::contextMenuEvent(QContextMenuEvent* event)
{
QMenu menu(this);
mMenuBuilder->build(&menu);
menu.exec(event->globalPos());
}
void CPUDump::mouseDoubleClickEvent(QMouseEvent* event)
{
if(event->button() != Qt::LeftButton || !DbgIsDebugging())
return;
switch(getColumnIndexFromX(event->x()))
{
case 0: //address
{
//very ugly way to calculate the base of the current row (no clue why it works)
duint deltaRowBase = getInitialSelection() % getBytePerRowCount() + mByteOffset;
if(deltaRowBase >= getBytePerRowCount())
deltaRowBase -= getBytePerRowCount();
dsint mSelectedVa = rvaToVa(getInitialSelection() - deltaRowBase);
if(mRvaDisplayEnabled && mSelectedVa == mRvaDisplayBase)
mRvaDisplayEnabled = false;
else
{
mRvaDisplayEnabled = true;
mRvaDisplayBase = mSelectedVa;
mRvaDisplayPageBase = mMemPage->getBase();
}
reloadData();
}
break;
default:
{
auto d = mDescriptor.at(0).data;
if(getSizeOf(d.itemSize) <= sizeof(duint) || (d.itemSize == 4 && d.dwordMode == FloatDword || d.itemSize == 8 && d.qwordMode == DoubleQword))
modifyValueSlot();
else
binaryEditSlot();
}
break;
}
}
static QString getTooltipForVa(duint va, int depth)
{
duint ptr = 0;
if(!DbgMemRead(va, &ptr, sizeof(duint)))
return QString();
QString tooltip;
/* TODO: if this is enabled, make sure the context menu items also work
// If the VA is not a valid pointer, try to align it
if(!DbgMemIsValidReadPtr(ptr))
{
va -= va % sizeof(duint);
DbgMemRead(va, &ptr, sizeof(duint));
}*/
// Check if its a pointer
switch(DbgGetEncodeTypeAt(va, 1))
{
// Get information about the pointer type
case enc_unknown:
default:
if(DbgMemIsValidReadPtr(ptr) && depth >= 0)
{
tooltip = QString("[%1] = %2").arg(ToPtrString(ptr), getTooltipForVa(ptr, depth - 1));
}
// If not a pointer, hide tooltips
else
{
bool isCodePage;
isCodePage = DbgFunctions()->MemIsCodePage(va, false);
char disassembly[GUI_MAX_DISASSEMBLY_SIZE];
if(isCodePage)
{
if(GuiGetDisassembly(va, disassembly))
tooltip = QString::fromUtf8(disassembly);
else
tooltip = "";
}
else
tooltip = QString("[%1] = %2").arg(ToPtrString(va)).arg(ToPtrString(ptr));
if(DbgFunctions()->ModGetParty(va) == 1)
tooltip += " (" + (isCodePage ? CPUDump::tr("System Code") : CPUDump::tr("System Data")) + ")";
else
tooltip += " (" + (isCodePage ? CPUDump::tr("User Code") : CPUDump::tr("User Data")) + ")";
}
break;
case enc_code:
char disassembly[GUI_MAX_DISASSEMBLY_SIZE];
if(GuiGetDisassembly(va, disassembly))
tooltip = QString::fromUtf8(disassembly);
else
tooltip = "";
if(DbgFunctions()->ModGetParty(va) == 1)
tooltip += " (" + CPUDump::tr("System Code") + ")";
else
tooltip += " (" + CPUDump::tr("User Code") + ")";
break;
case enc_real4:
tooltip = ToFloatString(&va) + CPUDump::tr(" (Real4)");
break;
case enc_real8:
double numd;
DbgMemRead(va, &numd, sizeof(double));
tooltip = ToDoubleString(&numd) + CPUDump::tr(" (Real8)");
break;
case enc_byte:
tooltip = ToByteString(va) + CPUDump::tr(" (BYTE)");
break;
case enc_word:
tooltip = ToWordString(va) + CPUDump::tr(" (WORD)");
break;
case enc_dword:
tooltip = QString("%1").arg((unsigned int)va, 8, 16, QChar('0')).toUpper() + CPUDump::tr(" (DWORD)");
break;
case enc_qword:
#ifdef _WIN64
tooltip = QString("%1").arg((unsigned long long)va, 16, 16, QChar('0')).toUpper() + CPUDump::tr(" (QWORD)");
#else //x86
unsigned long long qword;
qword = 0;
DbgMemRead(va, &qword, 8);
tooltip = QString("%1").arg((unsigned long long)qword, 16, 16, QChar('0')).toUpper() + CPUDump::tr(" (QWORD)");
#endif //_WIN64
break;
case enc_ascii:
case enc_unicode:
char str[MAX_STRING_SIZE];
if(DbgGetStringAt(va, str))
tooltip = QString::fromUtf8(str) + CPUDump::tr(" (String)");
else
tooltip = CPUDump::tr("(Unknown String)");
break;
}
return tooltip;
}
void CPUDump::mouseMoveEvent(QMouseEvent* event)
{
// Get mouse pointer relative position
int x = event->x();
int y = event->y();
// Get HexDump own RVA address, then VA in memory
auto va = rvaToVa(getItemStartingAddress(x, y));
// Read VA
QToolTip::showText(event->globalPos(), getTooltipForVa(va, 4));
HexDump::mouseMoveEvent(event);
}
void CPUDump::modifyValueSlot()
{
dsint addr = getSelectionStart();
auto d = mDescriptor.at(0).data;
if(d.itemSize == 4 && d.dwordMode == FloatDword || d.itemSize == 8 && d.qwordMode == DoubleQword)
{
auto size = std::min(getSizeOf(mDescriptor.at(0).data.itemSize), sizeof(double));
if(size == 4)
{
float value;
mMemPage->read(&value, addr, size);
QString current = QString::number(value);
QString newvalue;
if(SimpleInputBox(this, tr("Modify value"), current, newvalue, current))
{
bool ok;
value = newvalue.toFloat(&ok);
if(ok)
mMemPage->write(&value, addr, size);
else
SimpleErrorBox(this, tr("Error"), tr("The input text is not a number!"));
}
}
else if(size == 8)
{
double value;
mMemPage->read(&value, addr, size);
QString current = QString::number(value);
QString newvalue;
if(SimpleInputBox(this, tr("Modify value"), current, newvalue, current))
{
bool ok;
value = newvalue.toDouble(&ok);
if(ok)
mMemPage->write(&value, addr, size);
else
SimpleErrorBox(this, tr("Error"), tr("The input text is not a number!"));
}
}
}
else
{
auto size = std::min(getSizeOf(mDescriptor.at(0).data.itemSize), sizeof(dsint));
WordEditDialog editDialog(this);
dsint value = 0;
mMemPage->read(&value, addr, size);
editDialog.setup(tr("Modify value"), value, (int)size);
if(editDialog.exec() != QDialog::Accepted)
return;
value = editDialog.getVal();
mMemPage->write(&value, addr, size);
}
GuiUpdateAllViews();
}
void CPUDump::gotoExpressionSlot()
{
if(!DbgIsDebugging())
return;
if(!mGoto)
mGoto = new GotoDialog(this);
mGoto->setWindowTitle(tr("Enter expression to follow in Dump..."));
mGoto->setInitialExpression(ToPtrString(rvaToVa(getInitialSelection())));
if(mGoto->exec() == QDialog::Accepted)
{
duint value = DbgValFromString(mGoto->expressionText.toUtf8().constData());
DbgCmdExec(QString().sprintf("dump %p", value));
}
}
void CPUDump::gotoFileOffsetSlot()
{
if(!DbgIsDebugging())
return;
char modname[MAX_MODULE_SIZE] = "";
if(!DbgFunctions()->ModNameFromAddr(rvaToVa(getSelectionStart()), modname, true))
{
SimpleErrorBox(this, tr("Error!"), tr("Not inside a module..."));
return;
}
if(!mGotoOffset)
mGotoOffset = new GotoDialog(this);
mGotoOffset->fileOffset = true;
mGotoOffset->modName = QString(modname);
mGotoOffset->setWindowTitle(tr("Goto File Offset in %1").arg(QString(modname)));
duint addr = rvaToVa(getInitialSelection());
duint offset = DbgFunctions()->VaToFileOffset(addr);
if(offset)
mGotoOffset->setInitialExpression(ToHexString(offset));
if(mGotoOffset->exec() != QDialog::Accepted)
return;
duint value = DbgValFromString(mGotoOffset->expressionText.toUtf8().constData());
value = DbgFunctions()->FileOffsetToVa(modname, value);
DbgCmdExec(QString().sprintf("dump \"%p\"", value));
}
void CPUDump::gotoStartSlot()
{
duint dest = mMemPage->getBase();
DbgCmdExec(QString().sprintf("dump \"%p\"", dest));
}
void CPUDump::gotoEndSlot()
{
duint dest = mMemPage->getBase() + mMemPage->getSize() - (getViewableRowsCount() * getBytePerRowCount());
DbgCmdExec(QString().sprintf("dump \"%p\"", dest));
}
void CPUDump::gotoPreviousReferenceSlot()
{
auto count = DbgEval("refsearch.count()"), index = DbgEval("$__dump_refindex"), addr = DbgEval("refsearch.addr($__dump_refindex)");
if(count)
{
if(index > 0 && addr == rvaToVa(getInitialSelection()))
DbgValToString("$__dump_refindex", index - 1);
DbgCmdExec("dump refsearch.addr($__dump_refindex)");
GuiReferenceSetSingleSelection(int(DbgEval("$__dump_refindex")), false);
}
}
void CPUDump::gotoNextReferenceSlot()
{
auto count = DbgEval("refsearch.count()"), index = DbgEval("$__dump_refindex"), addr = DbgEval("refsearch.addr($__dump_refindex)");
if(count)
{
if(index + 1 < count && addr == rvaToVa(getInitialSelection()))
DbgValToString("$__dump_refindex", index + 1);
DbgCmdExec("dump refsearch.addr($__dump_refindex)");
GuiReferenceSetSingleSelection(int(DbgEval("$__dump_refindex")), false);
}
}
void CPUDump::hexAsciiSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewHexAscii);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //hex byte
colDesc.itemCount = 16;
colDesc.separator = mAsciiSeparator ? mAsciiSeparator : 4;
dDesc.itemSize = Byte;
dDesc.byteMode = HexByte;
colDesc.data = dDesc;
appendResetDescriptor(8 + charwidth * 47, tr("Hex"), false, colDesc);
colDesc.isData = true; //ascii byte
colDesc.itemCount = 16;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(8 + charwidth * 16, tr("ASCII"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::hexUnicodeSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewHexUnicode);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //hex byte
colDesc.itemCount = 16;
colDesc.separator = mAsciiSeparator ? mAsciiSeparator : 4;
dDesc.itemSize = Byte;
dDesc.byteMode = HexByte;
colDesc.data = dDesc;
appendResetDescriptor(8 + charwidth * 47, tr("Hex"), false, colDesc);
colDesc.isData = true; //unicode short
colDesc.itemCount = 8;
colDesc.separator = 0;
dDesc.itemSize = Word;
dDesc.wordMode = UnicodeWord;
colDesc.data = dDesc;
appendDescriptor(8 + charwidth * 8, tr("UNICODE"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::hexCodepageSlot()
{
CodepageSelectionDialog dialog(this);
if(dialog.exec() != QDialog::Accepted)
return;
auto codepage = dialog.getSelectedCodepage();
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //hex byte
colDesc.itemCount = 16;
colDesc.separator = mAsciiSeparator ? mAsciiSeparator : 4;
dDesc.itemSize = Byte;
dDesc.byteMode = HexByte;
colDesc.data = dDesc;
appendResetDescriptor(8 + charwidth * 47, tr("Hex"), false, colDesc);
colDesc.isData = true; //text (in code page)
colDesc.itemCount = 16;
colDesc.separator = 0;
colDesc.textEncoding = codepage;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, codepage, false, colDesc);
reloadData();
}
void CPUDump::hexLastCodepageSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewHexCodepage);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
duint lastCodepage;
auto allCodecs = QTextCodec::availableCodecs();
if(!BridgeSettingGetUint("Misc", "LastCodepage", &lastCodepage) || lastCodepage >= duint(allCodecs.size()))
return;
colDesc.isData = true; //hex byte
colDesc.itemCount = 16;
colDesc.separator = mAsciiSeparator ? mAsciiSeparator : 4;
dDesc.itemSize = Byte;
dDesc.byteMode = HexByte;
colDesc.data = dDesc;
appendResetDescriptor(8 + charwidth * 47, tr("Hex"), false, colDesc);
colDesc.isData = true; //text (in code page)
colDesc.itemCount = 16;
colDesc.separator = 0;
colDesc.textEncoding = allCodecs.at(lastCodepage);
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, allCodecs.at(lastCodepage), false, colDesc);
reloadData();
}
void CPUDump::textLastCodepageSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewTextCodepage);
ColumnDescriptor colDesc;
DataDescriptor dDesc;
duint lastCodepage;
auto allCodecs = QTextCodec::availableCodecs();
if(!BridgeSettingGetUint("Misc", "LastCodepage", &lastCodepage) || lastCodepage >= duint(allCodecs.size()))
return;
colDesc.isData = true; //text (in code page)
colDesc.itemCount = 64;
colDesc.separator = 0;
colDesc.textEncoding = allCodecs.at(lastCodepage);
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendResetDescriptor(0, allCodecs.at(lastCodepage), false, colDesc);
reloadData();
}
void CPUDump::textAsciiSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewTextAscii);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //ascii byte
colDesc.itemCount = 64;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendResetDescriptor(8 + charwidth * 64, tr("ASCII"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::textUnicodeSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewTextUnicode);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //unicode short
colDesc.itemCount = 64;
colDesc.separator = 0;
dDesc.itemSize = Word;
dDesc.wordMode = UnicodeWord;
colDesc.data = dDesc;
appendResetDescriptor(8 + charwidth * 64, tr("UNICODE"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::textCodepageSlot()
{
CodepageSelectionDialog dialog(this);
if(dialog.exec() != QDialog::Accepted)
return;
auto codepage = dialog.getSelectedCodepage();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //text (in code page)
colDesc.itemCount = 64;
colDesc.separator = 0;
colDesc.textEncoding = codepage;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendResetDescriptor(0, codepage, false, colDesc);
reloadData();
}
void CPUDump::integerSignedByteSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerSignedByte);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //signed short
colDesc.itemCount = 8;
colDesc.separator = 0;
colDesc.data.itemSize = Byte;
colDesc.data.wordMode = SignedDecWord;
appendResetDescriptor(8 + charwidth * 40, tr("Signed byte (8-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerSignedShortSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerSignedShort);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //signed short
colDesc.itemCount = 8;
colDesc.separator = 0;
colDesc.data.itemSize = Word;
colDesc.data.wordMode = SignedDecWord;
appendResetDescriptor(8 + charwidth * 55, tr("Signed short (16-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerSignedLongSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerSignedLong);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //signed long
colDesc.itemCount = 4;
colDesc.separator = 0;
colDesc.data.itemSize = Dword;
colDesc.data.dwordMode = SignedDecDword;
appendResetDescriptor(8 + charwidth * 47, tr("Signed long (32-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerSignedLongLongSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerSignedLongLong);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //signed long long
colDesc.itemCount = 2;
colDesc.separator = 0;
colDesc.data.itemSize = Qword;
colDesc.data.qwordMode = SignedDecQword;
appendResetDescriptor(8 + charwidth * 41, tr("Signed long long (64-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerUnsignedByteSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerUnsignedByte);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //unsigned short
colDesc.itemCount = 8;
colDesc.separator = 0;
colDesc.data.itemSize = Byte;
colDesc.data.wordMode = UnsignedDecWord;
appendResetDescriptor(8 + charwidth * 32, tr("Unsigned byte (8-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerUnsignedShortSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerUnsignedShort);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //unsigned short
colDesc.itemCount = 8;
colDesc.separator = 0;
colDesc.data.itemSize = Word;
colDesc.data.wordMode = UnsignedDecWord;
appendResetDescriptor(8 + charwidth * 47, tr("Unsigned short (16-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerUnsignedLongSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerUnsignedLong);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //unsigned long
colDesc.itemCount = 4;
colDesc.separator = 0;
colDesc.data.itemSize = Dword;
colDesc.data.dwordMode = UnsignedDecDword;
appendResetDescriptor(8 + charwidth * 43, tr("Unsigned long (32-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerUnsignedLongLongSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerUnsignedLongLong);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //unsigned long long
colDesc.itemCount = 2;
colDesc.separator = 0;
colDesc.data.itemSize = Qword;
colDesc.data.qwordMode = UnsignedDecQword;
appendResetDescriptor(8 + charwidth * 41, tr("Unsigned long long (64-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerHexShortSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerHexShort);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //hex short
colDesc.itemCount = 8;
colDesc.separator = 0;
colDesc.data.itemSize = Word;
colDesc.data.wordMode = HexWord;
appendResetDescriptor(8 + charwidth * 39, tr("Hex short (16-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerHexLongSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerHexLong);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //hex long
colDesc.itemCount = 4;
colDesc.separator = 0;
colDesc.data.itemSize = Dword;
colDesc.data.dwordMode = HexDword;
appendResetDescriptor(8 + charwidth * 35, tr("Hex long (32-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::integerHexLongLongSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewIntegerHexLongLong);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //hex long long
colDesc.itemCount = 2;
colDesc.separator = 0;
colDesc.data.itemSize = Qword;
colDesc.data.qwordMode = HexQword;
appendResetDescriptor(8 + charwidth * 33, tr("Hex long long (64-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::floatFloatSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewFloatFloat);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //float dword
colDesc.itemCount = 4;
colDesc.separator = 0;
colDesc.data.itemSize = Dword;
colDesc.data.dwordMode = FloatDword;
appendResetDescriptor(8 + charwidth * 55, tr("Float (32-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::floatDoubleSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewFloatDouble);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //float qword
colDesc.itemCount = 2;
colDesc.separator = 0;
colDesc.data.itemSize = Qword;
colDesc.data.qwordMode = DoubleQword;
appendResetDescriptor(8 + charwidth * 47, tr("Double (64-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::floatLongDoubleSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewFloatLongDouble);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //float qword
colDesc.itemCount = 2;
colDesc.separator = 0;
colDesc.data.itemSize = Tword;
colDesc.data.twordMode = FloatTword;
appendResetDescriptor(8 + charwidth * 59, tr("Long double (80-bit)"), false, colDesc);
colDesc.isData = false; //empty column
colDesc.itemCount = 0;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, "", false, colDesc);
reloadData();
}
void CPUDump::addressAsciiSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewAddressAscii);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //void*
colDesc.itemCount = 1;
colDesc.separator = 0;
#ifdef _WIN64
colDesc.data.itemSize = Qword;
colDesc.data.qwordMode = HexQword;
#else
colDesc.data.itemSize = Dword;
colDesc.data.dwordMode = HexDword;
#endif
appendResetDescriptor(8 + charwidth * 2 * sizeof(duint), tr("Value"), false, colDesc);
colDesc.isData = true;
colDesc.separator = 0;
#ifdef _WIN64
colDesc.itemCount = 8;
#else
colDesc.itemCount = 4;
#endif
colDesc.data.itemSize = Byte;
colDesc.data.byteMode = AsciiByte;
colDesc.columnSwitch = [this]()
{
this->setView(ViewAddressUnicode);
};
appendDescriptor(8 + charwidth * colDesc.itemCount, tr("ASCII"), true, colDesc);
colDesc.isData = false; //comments
colDesc.itemCount = 1;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, tr("Comments"), false, colDesc);
reloadData();
}
void CPUDump::addressUnicodeSlot()
{
Config()->setUint("HexDump", "DefaultView", (duint)ViewAddressUnicode);
int charwidth = getCharWidth();
ColumnDescriptor colDesc;
DataDescriptor dDesc;
colDesc.isData = true; //void*
colDesc.itemCount = 1;
colDesc.separator = 0;
#ifdef _WIN64
colDesc.data.itemSize = Qword;
colDesc.data.qwordMode = HexQword;
#else
colDesc.data.itemSize = Dword;
colDesc.data.dwordMode = HexDword;
#endif
appendResetDescriptor(8 + charwidth * 2 * sizeof(duint), tr("Value"), false, colDesc);
colDesc.isData = true;
colDesc.separator = 0;
#ifdef _WIN64
colDesc.itemCount = 4;
#else
colDesc.itemCount = 2;
#endif
colDesc.data.itemSize = Word;
colDesc.data.wordMode = UnicodeWord;
colDesc.columnSwitch = [this]()
{
this->setView(ViewAddressAscii);
};
appendDescriptor(8 + charwidth * colDesc.itemCount, tr("UNICODE"), true, colDesc);
colDesc.isData = false; //comments
colDesc.itemCount = 1;
colDesc.separator = 0;
dDesc.itemSize = Byte;
dDesc.byteMode = AsciiByte;
colDesc.data = dDesc;
appendDescriptor(0, tr("Comments"), false, colDesc);
reloadData();
}
void CPUDump::disassemblySlot()
{
SELECTIONDATA selection;
selectionGet(&selection);
emit showDisassemblyTab(selection.start, selection.end, rvaToVa(getTableOffsetRva()));
}
void CPUDump::selectionGet(SELECTIONDATA* selection)
{
selection->start = rvaToVa(getSelectionStart());
selection->end = rvaToVa(getSelectionEnd());
Bridge::getBridge()->setResult(BridgeResult::SelectionGet, 1);
}
void CPUDump::selectionSet(const SELECTIONDATA* selection)
{
dsint selMin = mMemPage->getBase();
dsint selMax = selMin + mMemPage->getSize();
dsint start = selection->start;
dsint end = selection->end;
if(start < selMin || start >= selMax || end < selMin || end >= selMax) //selection out of range
{
Bridge::getBridge()->setResult(BridgeResult::SelectionSet, 0);
return;
}
setSingleSelection(start - selMin);
expandSelectionUpTo(end - selMin);
reloadData();
Bridge::getBridge()->setResult(BridgeResult::SelectionSet, 1);
}
void CPUDump::findReferencesSlot()
{
QString addrStart = ToPtrString(rvaToVa(getSelectionStart()));
QString addrEnd = ToPtrString(rvaToVa(getSelectionEnd()));
QString addrDisasm = ToPtrString(mDisas->rvaToVa(mDisas->getSelectionStart()));
DbgCmdExec(QString("findrefrange " + addrStart + ", " + addrEnd + ", " + addrDisasm));
emit displayReferencesWidget();
}
void CPUDump::binaryEditSlot()
{
HexEditDialog hexEdit(this);
dsint selStart = getSelectionStart();
dsint selSize = getSelectionEnd() - selStart + 1;
byte_t* data = new byte_t[selSize];
mMemPage->read(data, selStart, selSize);
hexEdit.mHexEdit->setData(QByteArray((const char*)data, selSize));
delete [] data;
hexEdit.setWindowTitle(tr("Edit data at %1").arg(ToPtrString(rvaToVa(selStart))));
if(hexEdit.exec() != QDialog::Accepted)
return;
dsint dataSize = hexEdit.mHexEdit->data().size();
dsint newSize = selSize > dataSize ? selSize : dataSize;
data = new byte_t[newSize];
mMemPage->read(data, selStart, newSize);
QByteArray patched = hexEdit.mHexEdit->applyMaskedData(QByteArray((const char*)data, newSize));
mMemPage->write(patched.constData(), selStart, patched.size());
GuiUpdateAllViews();
}
void CPUDump::binaryFillSlot()
{
HexEditDialog hexEdit(this);
hexEdit.showKeepSize(false);
hexEdit.mHexEdit->setOverwriteMode(false);
dsint selStart = getSelectionStart();
hexEdit.setWindowTitle(tr("Fill data at %1").arg(ToPtrString(rvaToVa(selStart))));
if(hexEdit.exec() != QDialog::Accepted)
return;
QString pattern = hexEdit.mHexEdit->pattern();
dsint selSize = getSelectionEnd() - selStart + 1;
byte_t* data = new byte_t[selSize];
mMemPage->read(data, selStart, selSize);
hexEdit.mHexEdit->setData(QByteArray((const char*)data, selSize));
delete [] data;
hexEdit.mHexEdit->fill(0, QString(pattern));
QByteArray patched(hexEdit.mHexEdit->data());
mMemPage->write(patched, selStart, patched.size());
GuiUpdateAllViews();
}
void CPUDump::binaryCopySlot()
{
HexEditDialog hexEdit(this);
dsint selStart = getSelectionStart();
dsint selSize = getSelectionEnd() - selStart + 1;
byte_t* data = new byte_t[selSize];
mMemPage->read(data, selStart, selSize);
hexEdit.mHexEdit->setData(QByteArray((const char*)data, selSize));
delete [] data;
Bridge::CopyToClipboard(hexEdit.mHexEdit->pattern(true));
}
void CPUDump::binaryPasteSlot()
{
if(!QApplication::clipboard()->mimeData()->hasText())
return;
HexEditDialog hexEdit(this);
dsint selStart = getSelectionStart();
dsint selSize = getSelectionEnd() - selStart + 1;
QClipboard* clipboard = QApplication::clipboard();
hexEdit.mHexEdit->setData(clipboard->text());
byte_t* data = new byte_t[selSize];
mMemPage->read(data, selStart, selSize);
QByteArray patched = hexEdit.mHexEdit->applyMaskedData(QByteArray((const char*)data, selSize));
if(patched.size() < selSize)
selSize = patched.size();
mMemPage->write(patched.constData(), selStart, selSize);
GuiUpdateAllViews();
}
void CPUDump::binaryPasteIgnoreSizeSlot()
{
if(!QApplication::clipboard()->mimeData()->hasText())
return;
HexEditDialog hexEdit(this);
dsint selStart = getSelectionStart();
dsint selSize = getSelectionEnd() - selStart + 1;
QClipboard* clipboard = QApplication::clipboard();
hexEdit.mHexEdit->setData(clipboard->text());
byte_t* data = new byte_t[selSize];
mMemPage->read(data, selStart, selSize);
QByteArray patched = hexEdit.mHexEdit->applyMaskedData(QByteArray((const char*)data, selSize));
delete [] data;
mMemPage->write(patched.constData(), selStart, patched.size());
GuiUpdateAllViews();
}
void CPUDump::binarySaveToFileSlot()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save to file"), QDir::currentPath(), tr("All files (*.*)"));
if(fileName.length())
{
// Get starting selection and selection size, then convert selStart to VA
dsint selStart = getSelectionStart();
dsint selSize = getSelectionEnd() - selStart + 1;
// Prepare command
fileName = QDir::toNativeSeparators(fileName);
QString cmd = QString("savedata \"%1\",%2,%3").arg(fileName, ToHexString(rvaToVa(selStart)), ToHexString(selSize));
DbgCmdExec(cmd);
}
}
void CPUDump::findPattern()
{
HexEditDialog hexEdit(this);
hexEdit.showEntireBlock(true);
hexEdit.isDataCopiable(false);
hexEdit.mHexEdit->setOverwriteMode(false);
hexEdit.setWindowTitle(tr("Find Pattern..."));
if(hexEdit.exec() != QDialog::Accepted)
return;
dsint addr = rvaToVa(getSelectionStart());
if(hexEdit.entireBlock())
addr = DbgMemFindBaseAddr(addr, 0);
QString addrText = ToPtrString(addr);
DbgCmdExec(QString("findall " + addrText + ", " + hexEdit.mHexEdit->pattern() + ", &data&"));
emit displayReferencesWidget();
}
void CPUDump::copyFileOffsetSlot()
{
duint addr = rvaToVa(getInitialSelection());
duint offset = DbgFunctions()->VaToFileOffset(addr);
if(offset)
{
QString addrText = ToHexString(offset);
Bridge::CopyToClipboard(addrText);
}
else
QMessageBox::warning(this, tr("Error!"), tr("Selection not in a file..."));
}
void CPUDump::undoSelectionSlot()
{
dsint start = rvaToVa(getSelectionStart());
dsint end = rvaToVa(getSelectionEnd());
if(!DbgFunctions()->PatchInRange(start, end)) //nothing patched in selected range
return;
DbgFunctions()->PatchRestoreRange(start, end);
reloadData();
}
void CPUDump::selectionUpdatedSlot()
{
QString selStart = ToPtrString(rvaToVa(getSelectionStart()));
QString selEnd = ToPtrString(rvaToVa(getSelectionEnd()));
QString info = tr("Dump");
char mod[MAX_MODULE_SIZE] = "";
if(DbgFunctions()->ModNameFromAddr(rvaToVa(getSelectionStart()), mod, true))
info = QString(mod) + "";
GuiAddStatusBarMessage(QString(info + ": " + selStart + " -> " + selEnd + QString().sprintf(" (0x%.8X bytes)\n", getSelectionEnd() - getSelectionStart() + 1)).toUtf8().constData());
}
void CPUDump::syncWithExpressionSlot()
{
if(!DbgIsDebugging())
return;
GotoDialog gotoDialog(this, true);
gotoDialog.setWindowTitle(tr("Enter expression to sync with..."));
gotoDialog.setInitialExpression(mSyncAddrExpression);
if(gotoDialog.exec() != QDialog::Accepted)
return;
mSyncAddrExpression = gotoDialog.expressionText;
updateDumpSlot();
}
void CPUDump::allocMemorySlot()
{
WordEditDialog mLineEdit(this);
mLineEdit.setup(tr("Size"), 0x1000, sizeof(duint));
if(mLineEdit.exec() == QDialog::Accepted)
{
duint memsize = mLineEdit.getVal();
if(memsize == 0) // 1GB
{
SimpleWarningBox(this, tr("Warning"), tr("You're trying to allocate a zero-sized buffer just now."));
return;
}
if(memsize > 1024 * 1024 * 1024)
{
SimpleErrorBox(this, tr("Error"), tr("The size of buffer you're trying to allocate exceeds 1GB. Please check your expression to ensure nothing is wrong."));
return;
}
DbgCmdExecDirect(QString("alloc %1").arg(ToPtrString(memsize)));
duint addr = DbgValFromString("$result");
if(addr != 0)
{
DbgCmdExec("Dump $result");
}
else
{
SimpleErrorBox(this, tr("Error"), tr("Memory allocation failed!"));
return;
}
}
}
void CPUDump::setView(ViewEnum_t view)
{
switch(view)
{
case ViewHexAscii:
hexAsciiSlot();
break;
case ViewHexUnicode:
hexUnicodeSlot();
break;
case ViewTextAscii:
textAsciiSlot();
break;
case ViewTextUnicode:
textUnicodeSlot();
break;
case ViewIntegerSignedByte:
integerSignedByteSlot();
break;
case ViewIntegerSignedShort:
integerSignedShortSlot();
break;
case ViewIntegerSignedLong:
integerSignedLongSlot();
break;
case ViewIntegerSignedLongLong:
integerSignedLongLongSlot();
break;
case ViewIntegerUnsignedByte:
integerUnsignedByteSlot();
break;
case ViewIntegerUnsignedShort:
integerUnsignedShortSlot();
break;
case ViewIntegerUnsignedLong:
integerUnsignedLongSlot();
break;
case ViewIntegerUnsignedLongLong:
integerUnsignedLongLongSlot();
break;
case ViewIntegerHexShort:
integerHexShortSlot();
break;
case ViewIntegerHexLong:
integerHexLongSlot();
break;
case ViewIntegerHexLongLong:
integerHexLongLongSlot();
break;
case ViewFloatFloat:
floatFloatSlot();
break;
case ViewFloatDouble:
floatDoubleSlot();
break;
case ViewFloatLongDouble:
floatLongDoubleSlot();
break;
case ViewAddress:
case ViewAddressAscii:
addressAsciiSlot();
break;
case ViewAddressUnicode:
addressUnicodeSlot();
break;
case ViewHexCodepage:
hexLastCodepageSlot();
break;
case ViewTextCodepage:
textLastCodepageSlot();
break;
default:
hexAsciiSlot();
break;
}
}
void CPUDump::headerButtonReleasedSlot(int colIndex)
{
auto callback = mDescriptor[colIndex].columnSwitch;
if(callback)
callback();
}