Local variables view improved (#1560)
This commit is contained in:
parent
16f6158477
commit
2312ba0460
|
@ -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");
|
||||
|
|
|
@ -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, ¤t, 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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue