1
0
Fork 0
x64dbg/x64_dbg_gui/Project/Src/Gui/RegistersView.cpp

784 lines
28 KiB
C++

#include "RegistersView.h"
#include <QClipboard>
#include "Configuration.h"
#include "WordEditDialog.h"
RegistersView::RegistersView(QWidget* parent) : QScrollArea(parent), mVScrollOffset(0)
{
// precreate ContextMenu Actions
wCM_Increment = new QAction(tr("Increment"), this);
wCM_Increment->setShortcutContext(Qt::WidgetShortcut);
this->addAction(wCM_Increment);
wCM_Decrement = new QAction(tr("Decrement"), this);
wCM_Decrement->setShortcutContext(Qt::WidgetShortcut);
this->addAction(wCM_Decrement);
wCM_Zero = new QAction(tr("Zero"), this);
wCM_Zero->setShortcutContext(Qt::WidgetShortcut);
this->addAction(wCM_Zero);
wCM_SetToOne = new QAction(tr("Set to 1"), this);
wCM_SetToOne->setShortcutContext(Qt::WidgetShortcut);
this->addAction(wCM_SetToOne);
wCM_Modify = new QAction(tr("Modify Value"), this);
wCM_Modify->setShortcut(QKeySequence(Qt::Key_Enter));
wCM_ToggleValue = new QAction(tr("Toggle"), this);
wCM_ToggleValue->setShortcutContext(Qt::WidgetShortcut);
this->addAction(wCM_ToggleValue);
wCM_CopyToClipboard = new QAction(tr("Copy Value to Clipboard"), this);
wCM_CopyToClipboard->setShortcutContext(Qt::WidgetShortcut);
this->addAction(wCM_CopyToClipboard);
wCM_CopySymbolToClipboard = new QAction(tr("Copy Symbol Value to Clipboard"), this);
wCM_CopySymbolToClipboard->setShortcutContext(Qt::WidgetShortcut);
this->addAction(wCM_CopySymbolToClipboard);
wCM_FollowInDisassembly = new QAction(tr("Follow in Disassembler"), this);
wCM_FollowInDump = new QAction(tr("Follow in Dump"), this);
wCM_FollowInStack = new QAction("Follow in Stack", this);
// general purposes register (we allow the user to modify the value)
mGPR.insert(CAX);
mGPR.insert(CBX);
mGPR.insert(CCX);
mGPR.insert(CDX);
mGPR.insert(CBP);
mGPR.insert(CSP);
mGPR.insert(CSI);
mGPR.insert(CDI);
mGPR.insert(R8);
mGPR.insert(R9);
mGPR.insert(R10);
mGPR.insert(R11);
mGPR.insert(R12);
mGPR.insert(R13);
mGPR.insert(R14);
mGPR.insert(R15);
mGPR.insert(EFLAGS);
// flags (we allow the user to toggle them)
mFlags.insert(CF);
mFlags.insert(PF);
mFlags.insert(AF);
mFlags.insert(ZF);
mFlags.insert(SF);
mFlags.insert(TF);
mFlags.insert(IF);
mFlags.insert(DF);
mFlags.insert(OF);
//registers that should not be changed
mNoChange.insert(GS);
mNoChange.insert(FS);
mNoChange.insert(ES);
mNoChange.insert(DS);
mNoChange.insert(CS);
mNoChange.insert(SS);
mNoChange.insert(DR0);
mNoChange.insert(DR1);
mNoChange.insert(DR2);
mNoChange.insert(DR3);
mNoChange.insert(DR6);
mNoChange.insert(DR7);
mNoChange.insert(CIP);
// create mapping from internal id to name
mRegisterMapping.clear();
mRegisterPlaces.clear();
int offset = 0;
/* Register_Position is a struct definition the position
*
* (line , start, labelwidth, valuesize )
*/
#ifdef _WIN64
mRegisterMapping.insert(CAX, "RAX");
mRegisterPlaces.insert(CAX, Register_Position(0, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CBX, "RBX");
mRegisterPlaces.insert(CBX, Register_Position(1, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CCX, "RCX");
mRegisterPlaces.insert(CCX, Register_Position(2, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CDX, "RDX");
mRegisterPlaces.insert(CDX, Register_Position(3, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CSI, "RSI");
mRegisterPlaces.insert(CSI, Register_Position(6, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CDI, "RDI");
mRegisterPlaces.insert(CDI, Register_Position(7, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CBP, "RBP");
mRegisterPlaces.insert(CBP, Register_Position(4, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CSP, "RSP");
mRegisterPlaces.insert(CSP, Register_Position(5, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R8, "R8");
mRegisterPlaces.insert(R8 , Register_Position(9, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R9, "R9");
mRegisterPlaces.insert(R9 , Register_Position(10, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R10, "R10");
mRegisterPlaces.insert(R10, Register_Position(11, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R11, "R11");
mRegisterPlaces.insert(R11, Register_Position(12, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R12, "R12");
mRegisterPlaces.insert(R12, Register_Position(13, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R13, "R13");
mRegisterPlaces.insert(R13, Register_Position(14, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R14, "R14");
mRegisterPlaces.insert(R14, Register_Position(15, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(R15, "R15");
mRegisterPlaces.insert(R15, Register_Position(16, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CIP, "RIP");
mRegisterPlaces.insert(CIP, Register_Position(18, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(EFLAGS, "RFLAGS");
mRegisterPlaces.insert(EFLAGS, Register_Position(20, 0, 9, sizeof(uint_t) * 2));
offset = 21;
#else
mRegisterMapping.insert(CAX, "EAX");
mRegisterPlaces.insert(CAX, Register_Position(0, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CBX, "EBX");
mRegisterPlaces.insert(CBX, Register_Position(1, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CCX, "ECX");
mRegisterPlaces.insert(CCX, Register_Position(2, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CDX, "EDX");
mRegisterPlaces.insert(CDX, Register_Position(3, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CSI, "ESI");
mRegisterPlaces.insert(CSI, Register_Position(6, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CDI, "EDI");
mRegisterPlaces.insert(CDI, Register_Position(7, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CBP, "EBP");
mRegisterPlaces.insert(CBP, Register_Position(4, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CSP, "ESP");
mRegisterPlaces.insert(CSP, Register_Position(5, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(CIP, "EIP");
mRegisterPlaces.insert(CIP, Register_Position(9, 0, 6, sizeof(uint_t) * 2));
mRegisterMapping.insert(EFLAGS, "EFLAGS");
mRegisterPlaces.insert(EFLAGS, Register_Position(11, 0, 9, sizeof(uint_t) * 2));
offset = 12;
#endif
mRegisterMapping.insert(ZF, "ZF");
mRegisterPlaces.insert(ZF, Register_Position(offset + 0, 0, 3, 1));
mRegisterMapping.insert(OF, "OF");
mRegisterPlaces.insert(OF, Register_Position(offset + 1, 0, 3, 1));
mRegisterMapping.insert(CF, "CF");
mRegisterPlaces.insert(CF, Register_Position(offset + 2, 0, 3, 1));
mRegisterMapping.insert(PF, "PF");
mRegisterPlaces.insert(PF, Register_Position(offset + 0, 6, 3, 1));
mRegisterMapping.insert(SF, "SF");
mRegisterPlaces.insert(SF, Register_Position(offset + 1, 6, 3, 1));
mRegisterMapping.insert(TF, "TF");
mRegisterPlaces.insert(TF, Register_Position(offset + 2, 6, 3, 1));
mRegisterMapping.insert(AF, "AF");
mRegisterPlaces.insert(AF, Register_Position(offset + 0, 12, 3, 1));
mRegisterMapping.insert(DF, "DF");
mRegisterPlaces.insert(DF, Register_Position(offset + 1, 12, 3, 1));
mRegisterMapping.insert(IF, "IF");
mRegisterPlaces.insert(IF, Register_Position(offset + 2, 12, 3, 1));
offset++;
mRegisterMapping.insert(GS, "GS");
mRegisterPlaces.insert(GS, Register_Position(offset + 3, 0, 3, 4));
mRegisterMapping.insert(ES, "ES");
mRegisterPlaces.insert(ES, Register_Position(offset + 4, 0, 3, 4));
mRegisterMapping.insert(CS, "CS");
mRegisterPlaces.insert(CS, Register_Position(offset + 5, 0, 3, 4));
mRegisterMapping.insert(FS, "FS");
mRegisterPlaces.insert(FS, Register_Position(offset + 3, 9, 3, 4));
mRegisterMapping.insert(DS, "DS");
mRegisterPlaces.insert(DS, Register_Position(offset + 4, 9, 3, 4));
mRegisterMapping.insert(SS, "SS");
mRegisterPlaces.insert(SS, Register_Position(offset + 5, 9, 3, 4));
offset++;
mRegisterMapping.insert(DR0, "DR0");
mRegisterPlaces.insert(DR0, Register_Position(offset + 6, 0, 4, sizeof(uint_t) * 2));
mRegisterMapping.insert(DR1, "DR1");
mRegisterPlaces.insert(DR1, Register_Position(offset + 7, 0, 4, sizeof(uint_t) * 2));
mRegisterMapping.insert(DR2, "DR2");
mRegisterPlaces.insert(DR2, Register_Position(offset + 8, 0, 4, sizeof(uint_t) * 2));
mRegisterMapping.insert(DR3, "DR3");
mRegisterPlaces.insert(DR3, Register_Position(offset + 9, 0, 4, sizeof(uint_t) * 2));
mRegisterMapping.insert(DR6, "DR6");
mRegisterPlaces.insert(DR6, Register_Position(offset + 10, 0, 4, sizeof(uint_t) * 2));
mRegisterMapping.insert(DR7, "DR7");
mRegisterPlaces.insert(DR7, Register_Position(offset + 11, 0, 4, sizeof(uint_t) * 2));
fontsUpdatedSlot();
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
memset(&wRegDumpStruct, 0, sizeof(REGDUMP));
memset(&wCipRegDumpStruct, 0, sizeof(REGDUMP));
mCip = 0;
mRegisterUpdates.clear();
mRowsNeeded = offset + 16;
mRowsNeeded++;
yTopSpacing = 3; //set top spacing (in pixels)
// Context Menu
this->setContextMenuPolicy(Qt::CustomContextMenu);
// foreign messages
connect(Bridge::getBridge(), SIGNAL(updateRegisters()), this, SLOT(updateRegistersSlot()));
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayCustomContextMenuSlot(QPoint)));
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChangedSlot(DBGSTATE)));
// self communication for repainting (maybe some other widgets needs this information, too)
connect(this, SIGNAL(refresh()), this, SLOT(repaint()));
// context menu actions
connect(wCM_Increment, SIGNAL(triggered()), this, SLOT(onIncrementAction()));
connect(wCM_Decrement, SIGNAL(triggered()), this, SLOT(onDecrementAction()));
connect(wCM_Zero, SIGNAL(triggered()), this, SLOT(onZeroAction()));
connect(wCM_SetToOne, SIGNAL(triggered()), this, SLOT(onSetToOneAction()));
connect(wCM_Modify, SIGNAL(triggered()), this, SLOT(onModifyAction()));
connect(wCM_ToggleValue, SIGNAL(triggered()), this, SLOT(onToggleValueAction()));
connect(wCM_CopyToClipboard, SIGNAL(triggered()), this, SLOT(onCopyToClipboardAction()));
connect(wCM_CopySymbolToClipboard, SIGNAL(triggered()), this, SLOT(onCopySymbolToClipboardAction()));
connect(wCM_FollowInDisassembly, SIGNAL(triggered()), this, SLOT(onFollowInDisassembly()));
connect(wCM_FollowInDump, SIGNAL(triggered()), this, SLOT(onFollowInDump()));
connect(wCM_FollowInStack, SIGNAL(triggered()), this, SLOT(onFollowInStack()));
refreshShortcutsSlot();
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcutsSlot()));
}
void RegistersView::refreshShortcutsSlot()
{
wCM_Increment->setShortcut(ConfigShortcut("ActionIncreaseRegister"));
wCM_Decrement->setShortcut(ConfigShortcut("ActionDecreaseRegister"));
wCM_Zero->setShortcut(ConfigShortcut("ActionZeroRegister"));
wCM_SetToOne->setShortcut(ConfigShortcut("ActionSetOneRegister"));
wCM_ToggleValue->setShortcut(ConfigShortcut("ActionToggleRegisterValue"));
wCM_CopyToClipboard->setShortcut(ConfigShortcut("ActionCopy"));
wCM_CopySymbolToClipboard->setShortcut(ConfigShortcut("ActionCopySymbol"));
}
RegistersView::~RegistersView()
{
}
void RegistersView::fontsUpdatedSlot()
{
setFont(ConfigFont("Registers"));
int wRowsHeight = QFontMetrics(this->font()).height();
wRowsHeight = (wRowsHeight * 105) / 100;
wRowsHeight = (wRowsHeight % 2) == 0 ? wRowsHeight : wRowsHeight + 1;
mRowHeight = wRowsHeight;
mCharWidth = QFontMetrics(this->font()).averageCharWidth();
repaint();
}
/**
* @brief retrieves the register id from given corrdinates of the viewport
* @param line
* @param offset (x-coord)
* @param resulting register-id
* @return true if register found
*/
bool RegistersView::identifyRegister(const int line, const int offset, REGISTER_NAME* clickedReg)
{
// we start by an unknown register id
if(clickedReg)
*clickedReg = UNKNOWN;
bool found_flag = false;
QMap<REGISTER_NAME, Register_Position>::const_iterator it = mRegisterPlaces.begin();
// iterate all registers that being displayed
while(it != mRegisterPlaces.end())
{
if((it.value().line == (line - mVScrollOffset)) /* same line ? */
&& ((1 + it.value().start) <= offset) /* between start ... ? */
&& (offset <= (1 + it.value().start + it.value().labelwidth + it.value().valuesize)) /* ... and end ? */
)
{
// we found a matching register in the viewport
if(clickedReg)
*clickedReg = (REGISTER_NAME)it.key();
found_flag = true;
break;
}
++it;
}
return found_flag;
}
void RegistersView::mousePressEvent(QMouseEvent* event)
{
if(!DbgIsDebugging())
return;
// get mouse position
const int y = (event->y() - 3) / (double)mRowHeight;
const int x = event->x() / (double)mCharWidth;
REGISTER_NAME r;
// do we find a corresponding register?
if(identifyRegister(y, x, &r))
{
mSelected = r;
emit refresh();
}
else
mSelected = UNKNOWN;
}
void RegistersView::mouseDoubleClickEvent(QMouseEvent* event)
{
Q_UNUSED(event);
if(!DbgIsDebugging() || event->button() != Qt::LeftButton)
return;
// get mouse position
const int y = (event->y() - 3) / (double)mRowHeight;
const int x = event->x() / (double)mCharWidth;
// do we find a corresponding register?
if(!identifyRegister(y, x, 0))
return;
// is current register general purposes register ?
if(mGPR.contains(mSelected))
{
wCM_Modify->trigger();
}
else if(mFlags.contains(mSelected)) // is flag ?
wCM_ToggleValue->trigger();
else if(mSelected == CIP) //double clicked on CIP register
DbgCmdExec("disasm cip");
}
void RegistersView::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter wPainter(this->viewport());
wPainter.fillRect(wPainter.viewport(), QBrush(ConfigColor("RegistersBackgroundColor")));
QMap<REGISTER_NAME, QString>::const_iterator it = mRegisterMapping.begin();
// iterate all registers
while(it != mRegisterMapping.end())
{
// paint register at given position
drawRegister(&wPainter, it.key(), registerValue(&wRegDumpStruct, it.key()));
it++;
}
}
void RegistersView::keyPressEvent(QKeyEvent* event)
{
if(!DbgIsDebugging())
return;
if(event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
wCM_Modify->trigger();
}
QSize RegistersView::sizeHint() const
{
// 32 character width
return QSize(32 * mCharWidth , this->viewport()->height());
}
QString RegistersView::getRegisterLabel(REGISTER_NAME register_selected)
{
char label_text[MAX_LABEL_SIZE] = "";
char module_text[MAX_MODULE_SIZE] = "";
char string_text[MAX_STRING_SIZE] = "";
QString valueText = QString("%1").arg(registerValue(&wRegDumpStruct, register_selected), mRegisterPlaces[mSelected].valuesize, 16, QChar('0')).toUpper();
duint register_value = registerValue(&wRegDumpStruct, register_selected);
QString newText = QString("");
bool hasString = DbgGetStringAt(register_value, string_text);
bool hasLabel = DbgGetLabelAt(register_value, SEG_DEFAULT, label_text);
bool hasModule = DbgGetModuleAt(register_value, module_text);
if(hasString)
{
newText = string_text;
}
else if(hasLabel && hasModule)
{
newText = "<" + QString(module_text) + "." + QString(label_text) + ">";
}
else if(hasModule)
{
newText = QString(module_text) + "." + valueText;
}
else if(hasLabel)
{
newText = "<" + QString(label_text) + ">";
}
return newText;
}
void RegistersView::drawRegister(QPainter* p, REGISTER_NAME reg, uint_t value)
{
// is the register-id known?
if(mRegisterMapping.contains(reg))
{
// padding to the left is at least one character (looks better)
int x = mCharWidth * (1 + mRegisterPlaces[reg].start);
int ySpace = yTopSpacing;
if(mVScrollOffset != 0)
ySpace = 0;
int y = mRowHeight * (mRegisterPlaces[reg].line + mVScrollOffset) + ySpace;
//draw raster
/*
p->save();
p->setPen(QColor("#FF0000"));
p->drawLine(0, y, this->viewport()->width(), y);
p->restore();
*/
// draw name of value
int width = mCharWidth * mRegisterMapping[reg].length();
p->setPen(ConfigColor("RegistersLabelColor"));
p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, mRegisterMapping[reg]);
x += (mRegisterPlaces[reg].labelwidth) * mCharWidth;
//p->drawText(offset,mRowHeight*(mRegisterPlaces[reg].line+1),mRegisterMapping[reg]);
//set highlighting
if(DbgIsDebugging() && mRegisterUpdates.contains(reg))
p->setPen(ConfigColor("RegistersModifiedColor"));
else
p->setPen(ConfigColor("RegistersColor"));
//selection
if(mSelected == reg)
{
p->fillRect(x, y, mRegisterPlaces[reg].valuesize * mCharWidth, mRowHeight, QBrush(ConfigColor("RegistersSelectionColor")));
//p->fillRect(QRect(x + (mRegisterPlaces[reg].labelwidth)*mCharWidth ,mRowHeight*(mRegisterPlaces[reg].line)+2, mRegisterPlaces[reg].valuesize*mCharWidth, mRowHeight), QBrush(ConfigColor("RegistersSelectionColor")));
}
// draw value
QString valueText = QString("%1").arg(value, mRegisterPlaces[reg].valuesize, 16, QChar('0')).toUpper();
width = mCharWidth * valueText.length();
p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, valueText);
//p->drawText(x + (mRegisterPlaces[reg].labelwidth)*mCharWidth ,mRowHeight*(mRegisterPlaces[reg].line+1),QString("%1").arg(value, mRegisterPlaces[reg].valuesize, 16, QChar('0')).toUpper());
// do we have a label ?
QString newText = getRegisterLabel(reg);
bool isCharacter = false;
x += valueText.length() * mCharWidth;
x += 5 * mCharWidth; //5 spaces
bool has_label;
if(newText != "")
has_label = true;
else
{
has_label = false;
// can we interpret the character as ASCII ??
if(mGPR.contains(reg))
{
if(value == (value & 0xFF))
{
QChar c = QChar((char)value);
if(c.isPrint())
{
newText = QString("'%1'").arg((char)value);
isCharacter = IsCharacterRegister(reg);
}
}
else if(value == (value & 0xFFF)) //UNICODE?
{
QChar c = QChar((wchar_t)value);
if(c.isPrint())
{
newText = "L'" + QString(c) + "'";
isCharacter = IsCharacterRegister(reg);
}
}
}
}
// are there additional informations?
if(has_label || isCharacter)
{
width = newText.length() * mCharWidth;
p->setPen(ConfigColor("RegistersExtraInfoColor"));
p->drawText(x, y, width, mRowHeight, Qt::AlignVCenter, newText);
//p->drawText(x,mRowHeight*(mRegisterPlaces[reg].line+1),newText);
}
}
}
void RegistersView::updateRegistersSlot()
{
// read registers
REGDUMP z;
memset(&z, 0, sizeof(REGDUMP));
DbgGetRegDump(&z);
// update gui
setRegisters(&z);
}
void RegistersView::displayEditDialog()
{
WordEditDialog wEditDial(this);
wEditDial.setup(QString("Edit"), registerValue(&wRegDumpStruct, mSelected), sizeof(int_t));
if(wEditDial.exec() == QDialog::Accepted) //OK button clicked
setRegister(mSelected, wEditDial.getVal());
}
void RegistersView::onIncrementAction()
{
if(mGPR.contains(mSelected))
setRegister(mSelected, registerValue(&wRegDumpStruct, mSelected) + 1);
}
void RegistersView::onDecrementAction()
{
if(mGPR.contains(mSelected))
setRegister(mSelected, registerValue(&wRegDumpStruct, mSelected) - 1);
}
void RegistersView::onZeroAction()
{
if(!mNoChange.contains(mSelected))
setRegister(mSelected, 0);
}
void RegistersView::onSetToOneAction()
{
if(!mNoChange.contains(mSelected))
setRegister(mSelected, 1);
}
void RegistersView::onModifyAction()
{
if(mGPR.contains(mSelected))
displayEditDialog();
}
void RegistersView::onToggleValueAction()
{
if(mFlags.contains(mSelected))
setRegister(mSelected, ((int)registerValue(&wRegDumpStruct, mSelected)) ^ 1);
else
{
int_t val = registerValue(&wRegDumpStruct, mSelected);
val++;
val *= -1;
setRegister(mSelected, val);
}
}
void RegistersView::onCopyToClipboardAction()
{
QClipboard* clipboard = QApplication::clipboard();
clipboard->setText(QString("%1").arg((uint_t)registerValue(&wRegDumpStruct, mSelected), sizeof(int_t) * 2, 16, QChar('0')).toUpper());
}
void RegistersView::onCopySymbolToClipboardAction()
{
QClipboard* clipboard = QApplication::clipboard();
QString symbol = getRegisterLabel(mSelected);
if(symbol != "")
clipboard->setText(symbol);
}
void RegistersView::onFollowInDisassembly()
{
if(mGPR.contains(mSelected))
{
QString addr = QString("%1").arg(registerValue(&wRegDumpStruct, mSelected), mRegisterPlaces[mSelected].valuesize, 16, QChar('0')).toUpper();
if(DbgMemIsValidReadPtr(registerValue(&wRegDumpStruct, mSelected)))
DbgCmdExec(QString().sprintf("disasm \"%s\"", addr.toUtf8().constData()).toUtf8().constData());
}
}
void RegistersView::onFollowInDump()
{
if(mGPR.contains(mSelected))
{
QString addr = QString("%1").arg(registerValue(&wRegDumpStruct, mSelected), mRegisterPlaces[mSelected].valuesize, 16, QChar('0')).toUpper();
if(DbgMemIsValidReadPtr(registerValue(&wRegDumpStruct, mSelected)))
DbgCmdExec(QString().sprintf("dump \"%s\"", addr.toUtf8().constData()).toUtf8().constData());
}
}
void RegistersView::onFollowInStack()
{
if(mGPR.contains(mSelected))
{
QString addr = QString("%1").arg(registerValue(&wRegDumpStruct, mSelected), mRegisterPlaces[mSelected].valuesize, 16, QChar('0')).toUpper();
if(DbgMemIsValidReadPtr(registerValue(&wRegDumpStruct, mSelected)))
DbgCmdExec(QString().sprintf("sdump \"%s\"", addr.toUtf8().constData()).toUtf8().constData());
}
}
void RegistersView::displayCustomContextMenuSlot(QPoint pos)
{
if(!DbgIsDebugging())
return;
QMenu wMenu(this);
if(mSelected != UNKNOWN)
{
if(!mNoChange.contains(mSelected))
{
if(registerValue(&wRegDumpStruct, mSelected) >= 1)
wMenu.addAction(wCM_Zero);
if(registerValue(&wRegDumpStruct, mSelected) == 0)
wMenu.addAction(wCM_SetToOne);
wMenu.addAction(wCM_ToggleValue);
}
if(mGPR.contains(mSelected))
{
wMenu.addAction(wCM_Modify);
wMenu.addAction(wCM_Increment);
wMenu.addAction(wCM_Decrement);
uint_t addr = registerValue(&wRegDumpStruct, mSelected);
if(DbgMemIsValidReadPtr(addr))
{
wMenu.addAction(wCM_FollowInDump);
wMenu.addAction(wCM_FollowInDisassembly);
duint size = 0;
duint base = DbgMemFindBaseAddr(DbgValFromString("csp"), &size);
if(addr >= base && addr < base + size)
wMenu.addAction(wCM_FollowInStack);
}
}
wMenu.addAction(wCM_CopyToClipboard);
QString symbol = getRegisterLabel(mSelected);
if(symbol != "")
wMenu.addAction(wCM_CopySymbolToClipboard);
wMenu.exec(this->mapToGlobal(pos));
}
else
{
wMenu.addSeparator();
#ifdef _WIN64
QAction* wHwbpCsp = wMenu.addAction("HW Break on [RSP]");
#else
QAction* wHwbpCsp = wMenu.addAction("HW Break on [ESP]");
#endif
QAction* wAction = wMenu.exec(this->mapToGlobal(pos));
if(wAction == wHwbpCsp)
DbgCmdExec("bphws csp,rw");
}
}
void RegistersView::setRegister(REGISTER_NAME reg, uint_t value)
{
// is register-id known?
if(mRegisterMapping.contains(reg))
{
// map "cax" to "eax" or "rax"
QString wRegName = mRegisterMapping.constFind(reg).value();
// flags need to '!' infront
if(mFlags.contains(reg))
wRegName = "!" + wRegName;
// we change the value (so highlight it)
mRegisterUpdates.insert(reg);
// tell everything the compiler
DbgValToString(wRegName.toUtf8().constData(), value);
// force repaint
emit refresh();
}
}
void RegistersView::debugStateChangedSlot(DBGSTATE state)
{
if(state == stopped)
{
updateRegistersSlot();
}
}
void RegistersView::repaint()
{
this->viewport()->repaint();
}
int_t RegistersView::registerValue(const REGDUMP* regd, const REGISTER_NAME reg)
{
// this is probably the most efficient general method to access the values of the struct
if(reg == CAX) return regd->cax;
if(reg == CBX) return regd->cbx;
if(reg == CCX) return regd->ccx;
if(reg == CDX) return regd->cdx;
if(reg == CSI) return regd->csi;
if(reg == CDI) return regd->cdi;
if(reg == CBP) return regd->cbp;
if(reg == CSP) return regd->csp;
if(reg == CIP) return regd->cip;
if(reg == EFLAGS) return regd->eflags;
#ifdef _WIN64
if(reg == R8) return regd->r8;
if(reg == R9) return regd->r9;
if(reg == R10) return regd->r10;
if(reg == R11) return regd->r11;
if(reg == R12) return regd->r12;
if(reg == R13) return regd->r13;
if(reg == R14) return regd->r14;
if(reg == R15) return regd->r15;
#endif
// CF,PF,AF,ZF,SF,TF,IF,DF,OF
if(reg == CF) return regd->flags.c;
if(reg == PF) return regd->flags.p;
if(reg == AF) return regd->flags.a;
if(reg == ZF) return regd->flags.z;
if(reg == SF) return regd->flags.s;
if(reg == TF) return regd->flags.t;
if(reg == IF) return regd->flags.i;
if(reg == DF) return regd->flags.d;
if(reg == OF) return regd->flags.o;
// GS,FS,ES,DS,CS,SS
if(reg == GS) return regd->gs;
if(reg == FS) return regd->fs;
if(reg == ES) return regd->es;
if(reg == DS) return regd->ds;
if(reg == CS) return regd->cs;
if(reg == SS) return regd->ss;
if(reg == DR0) return regd->dr0;
if(reg == DR1) return regd->dr1;
if(reg == DR2) return regd->dr2;
if(reg == DR3) return regd->dr3;
if(reg == DR6) return regd->dr6;
if(reg == DR7) return regd->dr7;
return 0;
}
void RegistersView::setRegisters(REGDUMP* reg)
{
// tests if new-register-value == old-register-value holds
if(mCip != reg->cip) //CIP changed
{
wCipRegDumpStruct = wRegDumpStruct;
mRegisterUpdates.clear();
mCip = reg->cip;
}
QMap<REGISTER_NAME, QString>::const_iterator it = mRegisterMapping.begin();
// iterate all ids (CAX, CBX, ...)
while(it != mRegisterMapping.end())
{
// does a register-value change happens?
if(registerValue(reg, it.key()) != registerValue(&wCipRegDumpStruct, it.key()))
mRegisterUpdates.insert(it.key());
else if(mRegisterUpdates.contains(it.key())) //registers are equal
mRegisterUpdates.remove(it.key());
it++;
}
// now we can save the values
wRegDumpStruct = (*reg);
if(mCip != reg->cip)
wCipRegDumpStruct = wRegDumpStruct;
// force repaint
emit refresh();
}