1
0
Fork 0

Local variables view improved (#1560)

This commit is contained in:
Torusrxxx 2017-04-21 09:06:14 +00:00 committed by Duncan Ogilvie
parent 16f6158477
commit 2312ba0460
3 changed files with 162 additions and 26 deletions

View File

@ -37,7 +37,7 @@ CPUMultiDump::CPUMultiDump(CPUDisassembly* disas, int nbCpuDumpTabs, QWidget* pa
mWatch->loadColumnFromConfig("Watch1");
mLocalVars = new LocalVarsView(this);
this->addTabEx(mLocalVars, DIcon("localvars.png"), tr("Locals"), "LocalVar");
this->addTabEx(mLocalVars, DIcon("localvars.png"), tr("Locals"), "Locals");
mStructWidget = new StructWidget(this);
this->addTabEx(mStructWidget, mStructWidget->windowIcon(), mStructWidget->windowTitle(), "Struct");

View File

@ -4,9 +4,23 @@
#include "MiscUtil.h"
#include "WordEditDialog.h"
// Gets the address from an expression like "[EBP-7c]"
static bool getAddress(QString addrText, duint & output)
{
if(!(addrText.startsWith("[") && addrText.endsWith("]")))
return false; //Unable to get address of the expression
addrText.truncate(addrText.size() - 1);
addrText = addrText.right(addrText.size() - 1);
QByteArray utf8 = addrText.toUtf8();
if(!DbgIsValidExpression(utf8.constData()))
return false;
output = DbgValFromString(utf8.constData());
return true;
}
LocalVarsView::LocalVarsView(CPUMultiDump* parent) : StdTable(parent)
{
currentFunc = 0;
configUpdatedSlot();
int charWidth = getCharWidth();
addColumnAt(8 + 20 * charWidth, tr("Name"), false);
@ -16,6 +30,7 @@ LocalVarsView::LocalVarsView(CPUMultiDump* parent) : StdTable(parent)
setupContextMenu();
connect(Bridge::getBridge(), SIGNAL(updateWatch()), this, SLOT(updateSlot()));
connect(Config(), SIGNAL(tokenizerConfigUpdated()), this, SLOT(configUpdatedSlot()));
connect(this, SIGNAL(doubleClickedSignal()), this, SLOT(editSlot()));
}
@ -25,7 +40,54 @@ void LocalVarsView::setupContextMenu()
{
return DbgIsDebugging();
});
mMenu->addAction(makeAction(DIcon("dump.png"), tr("&Follow in Dump"), SLOT(followDumpSlot())), [this](QMenu*)
{
return getCellContent(getInitialSelection(), 2) != tr("[Error]");
});
mMenu->addAction(makeAction(DIcon("dump.png"), ArchValue(tr("Follow DWORD in Dump"), tr("Follow QWORD in Dump")), SLOT(followWordInDumpSlot())), [this](QMenu*)
{
duint start;
if(getAddress(getCellContent(getInitialSelection(), 1), start))
{
DbgMemRead(start, &start, sizeof(start));
return DbgMemIsValidReadPtr(start);
}
else
return false;
});
mMenu->addAction(makeShortcutAction(DIcon("stack.png"), tr("Follow in Stack"), SLOT(followStackSlot()), "ActionFollowStack"), [this](QMenu*)
{
duint start;
if(getAddress(getCellContent(getInitialSelection(), 1), start))
return (DbgMemIsValidReadPtr(start) && DbgMemFindBaseAddr(start, 0) == DbgMemFindBaseAddr(DbgValFromString("csp"), 0));
else
return false;
});
mMenu->addAction(makeAction(DIcon("stack.png"), ArchValue(tr("Follow DWORD in Stack"), tr("Follow QWORD in Stack")), SLOT(followWordInStackSlot())), [this](QMenu*)
{
duint start;
if(getAddress(getCellContent(getInitialSelection(), 1), start))
{
DbgMemRead(start, &start, sizeof(start));
return (DbgMemIsValidReadPtr(start) && DbgMemFindBaseAddr(start, 0) == DbgMemFindBaseAddr(DbgValFromString("csp"), 0));
}
else
return false;
});
mMenu->addAction(makeShortcutAction(DIcon("memmap_find_address_page.png"), tr("Follow in Memory Map"), SLOT(followMemMapSlot()), "ActionFollowMemMap"), [this](QMenu*)
{
return getCellContent(getInitialSelection(), 2) != tr("[Error]");
});
mMenu->addAction(makeShortcutAction(DIcon("modify.png"), tr("&Modify Value"), SLOT(editSlot()), "ActionModifyValue"), [this](QMenu*)
{
return getCellContent(getInitialSelection(), 2) != tr("[Error]");
});
mMenu->addSeparator();
mMenu->addAction(makeAction(tr("&Rename"), SLOT(renameSlot())));
MenuBuilder* copyMenu = new MenuBuilder(this);
setupCopyMenu(copyMenu);
mMenu->addMenu(makeMenu(DIcon("copy.png"), tr("&Copy")), copyMenu);
mMenu->addSeparator();
MenuBuilder* mBaseRegisters = new MenuBuilder(this);
#ifdef _WIN64
baseRegisters[0] = new QAction("RAX", this);
@ -71,6 +133,18 @@ void LocalVarsView::setupContextMenu()
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
}
void LocalVarsView::mousePressEvent(QMouseEvent* event)
{
if(event->buttons() == Qt::MiddleButton && getRowCount() > 0)
{
duint addr;
if(getAddress(getCellContent(getInitialSelection(), 1), addr))
Bridge::CopyToClipboard(ToPtrString(addr));
}
else
StdTable::mousePressEvent(event);
}
void LocalVarsView::contextMenuSlot(const QPoint & pos)
{
QMenu wMenu(this);
@ -84,6 +158,13 @@ void LocalVarsView::baseChangedSlot()
updateSlot();
}
void LocalVarsView::configUpdatedSlot()
{
currentFunc = 0;
HexPrefixValues = Config()->getBool("Disassembler", "0xPrefixValues");
MemorySpaces = Config()->getBool("Disassembler", "MemorySpaces");
}
void LocalVarsView::updateSlot()
{
if(!DbgIsDebugging())
@ -114,8 +195,14 @@ void LocalVarsView::updateSlot()
duint address = start;
while(address < end)
{
ENCODETYPE codeType = DbgGetEncodeTypeAt(address, 1);
if(codeType != enc_code && codeType != enc_unknown) //Skip data bytes
{
address += DbgGetEncodeSizeAt(address, 1);
continue;
}
dis.Disassemble(address, buffer + address - start, end + 16 - address);
if(dis.IsNop())
if(dis.IsNop()) //Skip junk instructions
{
address += dis.Size();
continue;
@ -163,34 +250,41 @@ void LocalVarsView::updateSlot()
{
QString expr;
QString name;
if(j < 0)
{
expr = QString("%1").arg(-j, 0, 16);
if(HexPrefixValues)
expr = "0x" + expr;
if(!MemorySpaces)
expr = "-" + expr;
else
expr = " - " + expr;
}
else
{
expr = QString("%1").arg(j, 0, 16);
if(HexPrefixValues)
expr = "0x" + expr;
if(!MemorySpaces)
expr = "+" + expr;
else
expr = " + " + expr;
}
expr = QString("[%1%2]").arg(baseRegisters[i]->text()).arg(expr);
if(i == 4) //CBP
{
if(j < 0)
{
expr = QString("-0x%1").arg(-j, 0, 16);
name = tr("Local%1").arg(-j / sizeof(dsint)); //EBP-C:Local3
}
else
{
expr = QString("+0x%1").arg(j, 0, 16);
name = tr("Arg%1").arg(j / sizeof(dsint) - 1); //EBP+C:Arg2
}
expr = QString(ArchValue("[EBP%1]", "[RBP%1]")).arg(expr);
}
else
{
if(j < 0)
{
expr = QString("-0x%1").arg(-j, 0, 16);
name = QString("_%1_%2").arg(-j, 0, 16); //ECX-C: _ECX_C
}
name = QString("_%2_%1").arg(-j, 0, 16); //ECX-C: _ECX_C
else
{
expr = QString("+0x%1").arg(j, 0, 16);
name = QString("%2_%1").arg(j, 0, 16); //ECX+C: ECX_C
}
name = name.arg(baseRegisters[i]->text());
expr = QString("[%1%2]").arg(baseRegisters[i]->text()).arg(expr);
}
setCellContent(rows, 0, name);
setCellContent(rows, 1, expr);
@ -240,14 +334,9 @@ void LocalVarsView::editSlot()
if(getRowCount() <= 0)
return;
QString expr = getCellContent(getInitialSelection(), 1);
if(!(expr.startsWith("[") && expr.endsWith("]")))
return; //Unable to get address of the expression
expr.truncate(expr.size() - 1);
expr = expr.right(expr.size() - 1);
QByteArray utf8 = expr.toUtf8();
if(!DbgIsValidExpression(utf8.constData()))
duint addr;
if(!getAddress(expr, addr))
return;
duint addr = DbgValFromString(utf8.constData());
WordEditDialog editor(this);
duint current = 0;
if(!DbgMemRead(addr, &current, sizeof(duint)))
@ -260,3 +349,38 @@ void LocalVarsView::editSlot()
emit updateSlot();
}
}
void LocalVarsView::followDumpSlot()
{
duint addr;
if(getAddress(getCellContent(getInitialSelection(), 1), addr))
DbgCmdExec(QString("dump %1").arg(ToPtrString(addr)).toUtf8().constData());
}
void LocalVarsView::followStackSlot()
{
duint addr;
if(getAddress(getCellContent(getInitialSelection(), 1), addr))
DbgCmdExec(QString("sdump %1").arg(ToPtrString(addr)).toUtf8().constData());
}
void LocalVarsView::followMemMapSlot()
{
duint addr;
if(getAddress(getCellContent(getInitialSelection(), 1), addr))
DbgCmdExec(QString("memmapdump %1").arg(ToPtrString(addr)).toUtf8().constData());
}
void LocalVarsView::followWordInDumpSlot()
{
duint addr;
if(getAddress(getCellContent(getInitialSelection(), 1), addr))
DbgCmdExec(QString("dump [%1]").arg(ToPtrString(addr)).toUtf8().constData());
}
void LocalVarsView::followWordInStackSlot()
{
duint addr;
if(getAddress(getCellContent(getInitialSelection(), 1), addr))
DbgCmdExec(QString("sdump [%1]").arg(ToPtrString(addr)).toUtf8().constData());
}

View File

@ -12,15 +12,27 @@ public:
public slots:
void contextMenuSlot(const QPoint & pos);
void updateSlot();
void mousePressEvent(QMouseEvent* event);
void followDumpSlot();
void followStackSlot();
void followMemMapSlot();
void followWordInDumpSlot();
void followWordInStackSlot();
void baseChangedSlot();
void renameSlot();
void updateSlot();
void configUpdatedSlot();
void editSlot();
private:
duint currentFunc;
void setupContextMenu();
MenuBuilder* mMenu;
bool HexPrefixValues;
bool MemorySpaces;
#ifdef _WIN64
QAction* baseRegisters[16];
#else //x86