784 lines
28 KiB
C++
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();
|
|
|
|
}
|