1
0
Fork 0

Some minor cpu info box enhancements (#1583)

This commit is contained in:
ThunderCls 2017-05-09 13:27:34 -04:00 committed by Duncan Ogilvie
parent ad2835248b
commit bb0f582c9d
11 changed files with 223 additions and 11 deletions

View File

@ -247,6 +247,7 @@ void CPUDisassembly::setupRightClickContextMenu()
copyMenu->addAction(makeAction(DIcon("copy_selection_no_bytes.png"), tr("Selection to File (No Bytes)"), SLOT(copySelectionToFileNoBytesSlot())));
copyMenu->addAction(makeShortcutAction(DIcon("copy_address.png"), tr("&Address"), SLOT(copyAddressSlot()), "ActionCopyAddress"));
copyMenu->addAction(makeShortcutAction(DIcon("copy_address.png"), tr("&RVA"), SLOT(copyRvaSlot()), "ActionCopyRva"));
copyMenu->addAction(makeAction(DIcon("fileoffset.png"), tr("&File Offset"), SLOT(copyFileOffsetSlot())));
copyMenu->addAction(makeAction(DIcon("copy_disassembly.png"), tr("Disassembly"), SLOT(copyDisassemblySlot())));
copyMenu->addAction(makeAction(DIcon("data-copy.png"), tr("&Data..."), SLOT(copyDataSlot())));
@ -1718,6 +1719,27 @@ void CPUDisassembly::copyRvaSlot()
Bridge::CopyToClipboard(clipboard);
}
void CPUDisassembly::copyFileOffsetSlot()
{
QString clipboard = "";
prepareDataRange(getSelectionStart(), getSelectionEnd(), [&](int i, const Instruction_t & inst)
{
if(i)
clipboard += "\r\n";
duint addr = rvaToVa(inst.rva);
duint offset = DbgFunctions()->VaToFileOffset(addr);
if(offset)
clipboard += ToHexString(offset);
else
{
SimpleErrorBox(this, tr("Error!"), tr("Selection not in a file..."));
return false;
}
return true;
});
Bridge::CopyToClipboard(clipboard);
}
void CPUDisassembly::copyDisassemblySlot()
{
QString clipboardHtml = QString("<div style=\"font-family: %1; font-size: %2px\">").arg(font().family()).arg(getRowHeight());

View File

@ -89,6 +89,7 @@ public slots:
void copySelectionToFileNoBytesSlot();
void copyAddressSlot();
void copyRvaSlot();
void copyFileOffsetSlot();
void copyDisassemblySlot();
void copyDataSlot();
void labelCopySlot();

View File

@ -56,7 +56,12 @@ void CPUDump::setupContextMenu()
wCopyMenu->addAction(mCopyRva, [this](QMenu*)
{
return DbgFunctions()->ModBaseFromAddr(rvaToVa(getInitialSelection())) != 0;
});
wCopyMenu->addAction(makeShortcutAction(DIcon("fileoffset.png"), tr("&File Offset"), SLOT(copyFileOffsetSlot()), "ActionCopyFileOffset"), [this](QMenu*)
{
return DbgFunctions()->VaToFileOffset(rvaToVa(getInitialSelection())) != 0;
});
mMenuBuilder->addMenu(makeMenu(DIcon("copy.png"), tr("&Copy")), wCopyMenu);
mMenuBuilder->addAction(makeShortcutAction(DIcon("eraser.png"), tr("&Restore selection"), SLOT(undoSelectionSlot()), "ActionUndoSelection"), [this](QMenu*)
@ -1478,6 +1483,19 @@ void CPUDump::findPattern()
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());

View File

@ -90,6 +90,7 @@ public slots:
void binaryPasteIgnoreSizeSlot();
void binarySaveToFileSlot();
void findPattern();
void copyFileOffsetSlot();
void undoSelectionSlot();
void followStackSlot();
void findReferencesSlot();

View File

@ -1,5 +1,6 @@
#include "CPUInfoBox.h"
#include "Configuration.h"
#include "WordEditDialog.h"
#include "Bridge.h"
CPUInfoBox::CPUInfoBox(StdTable* parent) : StdTable(parent)
@ -8,16 +9,18 @@ CPUInfoBox::CPUInfoBox(StdTable* parent) : StdTable(parent)
enableMultiSelection(false);
setShowHeader(false);
addColumnAt(0, "", true);
setRowCount(3);
setRowCount(4);
setCellContent(0, 0, "");
setCellContent(1, 0, "");
setCellContent(2, 0, "");
setCellContent(3, 0, "");
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
horizontalScrollBar()->setStyleSheet(ConfigHScrollBarStyle());
int height = getHeight();
setMinimumHeight(height);
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(dbgStateChanged(DBGSTATE)));
connect(Bridge::getBridge(), SIGNAL(addInfoLine(QString)), this, SLOT(addInfoLine(QString)));
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
@ -39,12 +42,12 @@ void CPUInfoBox::setupContextMenu()
int CPUInfoBox::getHeight()
{
return ((getRowHeight() + 1) * 3);
return ((getRowHeight() + 1) * 4);
}
void CPUInfoBox::setInfoLine(int line, QString text)
{
if(line < 0 || line > 2)
if(line < 0 || line > 3)
return;
setCellContent(line, 0, text);
@ -53,7 +56,7 @@ void CPUInfoBox::setInfoLine(int line, QString text)
QString CPUInfoBox::getInfoLine(int line)
{
if(line < 0 || line > 2)
if(line < 0 || line > 3)
return QString();
return getCellContent(line, 0);
@ -69,11 +72,12 @@ void CPUInfoBox::addInfoLine(const QString & infoLine)
void CPUInfoBox::clear()
{
// Set all 3 lines to empty strings
setRowCount(3);
// Set all 4 lines to empty strings
setRowCount(4);
setInfoLine(0, "");
setInfoLine(1, "");
setInfoLine(2, "");
setInfoLine(3, "");
}
static QString escapeCh(QChar ch)
@ -145,10 +149,11 @@ void CPUInfoBox::disasmSelectionChanged(dsint parVA)
if(!DbgIsDebugging() || !DbgMemIsValidReadPtr(parVA))
return;
// Rather than using clear() or setInfoLine(), only reset the first two cells to reduce flicker
setRowCount(3);
// Rather than using clear() or setInfoLine(), only reset the first three cells to reduce flicker
setRowCount(4);
setCellContent(0, 0, "");
setCellContent(1, 0, "");
setCellContent(2, 0, "");
DISASM_INSTR instr;
memset(&instr, 0, sizeof(instr));
@ -244,6 +249,71 @@ void CPUInfoBox::disasmSelectionChanged(dsint parVA)
if(getInfoLine(0) == getInfoLine(1)) //check for duplicate info line
setInfoLine(1, "");
// check references details
// code extracted from ExtraInfo plugin by torusrxxx
XREF_INFO xrefInfo;
xrefInfo.refcount = 0;
xrefInfo.references = nullptr;
if(DbgXrefGet(parVA, &xrefInfo) && xrefInfo.refcount > 0)
{
QString output;
std::vector<XREF_RECORD*> data;
for(duint i = 0; i < xrefInfo.refcount; i++)
data.push_back(&xrefInfo.references[i]);
std::sort(data.begin(), data.end(), [](const XREF_RECORD *A, const XREF_RECORD *B){
return ((A->type < B->type) || (A->addr < B->addr));
});
int t = XREF_NONE;
duint i;
for(i = 0; i < xrefInfo.refcount && i < 10; i++)
{
if(t != data[i]->type)
{
switch(data[i]->type)
{
case XREF_JMP:
output += tr("Jump from ");
break;
case XREF_CALL:
output += tr("Call from ");
break;
default:
output += tr("Reference from ");
break;
}
t = data[i]->type;
}
char clabel[MAX_LABEL_SIZE] = "";
DbgGetLabelAt(data[i]->addr, SEG_DEFAULT, clabel);
if(*clabel)
output += QString(clabel);
else
{
duint start;
if(DbgFunctionGet(data[i]->addr, &start, nullptr) && DbgGetLabelAt(start, SEG_DEFAULT, clabel) && start != data[i]->addr)
output += QString("%1+%2").arg(clabel).arg(ToHexString(data[i]->addr - start));
else
output += QString("%1").arg(ToHexString(data[i]->addr));
}
if(i != xrefInfo.refcount - 1)
output += ", ";
}
data.clear();
if(xrefInfo.refcount > 10)
output += "...";
setInfoLine(2, output);
}
// Set last line
//
// Format: SECTION:VA MODULE:$RVA :#FILE_OFFSET FUNCTION, Accessed %u times
@ -293,7 +363,7 @@ void CPUInfoBox::disasmSelectionChanged(dsint parVA)
info += ", " + tr("Accessed %n time(s)", nullptr, tracedCount);
}
setInfoLine(2, info);
setInfoLine(3, info);
DbgSelChanged(GUI_DISASSEMBLY, parVA);
}
@ -316,6 +386,82 @@ void CPUInfoBox::followActionSlot()
DbgCmdExec(QString("AddWatch \"[%1]\"").arg(action->objectName().mid(6)).toUtf8().constData());
}
void CPUInfoBox::modifySlot()
{
QAction* action = qobject_cast<QAction*>(sender());
if(action)
{
duint addrVal = 0;
DbgFunctions()->ValFromString(action->objectName().toUtf8().constData(), &addrVal);
WordEditDialog wEditDialog(this);
dsint value = 0;
DbgMemRead(addrVal, &value, sizeof(dsint));
wEditDialog.setup(tr("Modify Value"), value, sizeof(dsint));
if(wEditDialog.exec() != QDialog::Accepted)
return;
value = wEditDialog.getVal();
DbgMemWrite(addrVal, &value, sizeof(dsint));
GuiUpdateAllViews();
}
}
void CPUInfoBox::findReferencesSlot()
{
DbgCmdExec(QString("findref ") + QString().number(curAddr, 16).toUtf8().constData());
emit displayReferencesWidget();
}
void CPUInfoBox::addModifyValueMenuItem(QMenu* menu, QString name, duint value)
{
foreach(QAction* action, menu->actions()) //check for duplicate action
if(action->text() == name)
return;
QAction* newAction = new QAction(name, menu);
menu->addAction(newAction);
newAction->setObjectName(ToPtrString(value));
connect(newAction, SIGNAL(triggered()), this, SLOT(modifySlot()));
}
void CPUInfoBox::setupModifyValueMenu(QMenu* menu, duint wVA)
{
menu->setIcon(DIcon("modify.png"));
//add follow actions
DISASM_INSTR instr;
DbgDisasmAt(wVA, &instr);
for(int i = 0; i < instr.argcount; i++)
{
const DISASM_ARG arg = instr.arg[i];
if(arg.type == arg_memory)
{
QString segment = "";
#ifdef _WIN64
if(arg.segment == SEG_GS)
segment = "gs:";
#else //x32
if(arg.segment == SEG_FS)
segment = "fs:";
#endif //_WIN64
if(DbgMemIsValidReadPtr(arg.value))
addModifyValueMenuItem(menu, tr("&Address: ") + segment + QString(arg.mnemonic).toUpper().trimmed(), arg.value);
if(arg.value != arg.constant)
{
QString constant = QString("%1").arg(ToHexString(arg.constant));
if(DbgMemIsValidReadPtr(arg.constant))
addModifyValueMenuItem(menu, tr("&Constant: ") + constant, arg.constant);
}
if(DbgMemIsValidReadPtr(arg.memvalue))
addModifyValueMenuItem(menu, tr("&Value: ") + segment + "[" + QString(arg.mnemonic).toUpper().trimmed() + "]", arg.memvalue);
}
else
{
if(DbgMemIsValidReadPtr(arg.value))
addModifyValueMenuItem(menu, "&Value: [" + QString(arg.mnemonic).toUpper().trimmed() + "]", arg.value);
}
}
}
/**
* @brief CPUInfoBox::addFollowMenuItem Add a follow action to the menu
* @param menu The menu to which the follow action adds
@ -328,7 +474,6 @@ void CPUInfoBox::addFollowMenuItem(QMenu* menu, QString name, duint value)
if(action->text() == name)
return;
QAction* newAction = new QAction(name, menu);
newAction->setFont(QFont("Courier New", 8));
menu->addAction(newAction);
newAction->setObjectName(QString("DUMP|") + ToPtrString(value));
connect(newAction, SIGNAL(triggered()), this, SLOT(followActionSlot()));
@ -393,7 +538,6 @@ void CPUInfoBox::addWatchMenuItem(QMenu* menu, QString name, duint value)
if(action->text() == name)
return;
QAction* newAction = new QAction(name, menu);
newAction->setFont(QFont("Courier New", 8));
menu->addAction(newAction);
newAction->setObjectName(QString("WATCH|") + ToPtrString(value));
connect(newAction, SIGNAL(triggered()), this, SLOT(followActionSlot()));
@ -497,9 +641,15 @@ void CPUInfoBox::contextMenuSlot(QPoint pos)
QMenu wFollowMenu(tr("&Follow in Dump"), this);
setupFollowMenu(&wFollowMenu, curAddr);
wMenu.addMenu(&wFollowMenu);
QMenu wModifyValueMenu(tr("&Modify Value"), this);
setupModifyValueMenu(&wModifyValueMenu, curAddr);
if(!wModifyValueMenu.isEmpty())
wMenu.addMenu(&wModifyValueMenu);
QMenu wWatchMenu(tr("&Watch"), this);
setupWatchMenu(&wWatchMenu, curAddr);
wMenu.addMenu(&wWatchMenu);
if(!getInfoLine(2).isEmpty())
wMenu.addAction(makeAction(DIcon("find.png"), tr("&Show References"), SLOT(findReferencesSlot())));
QMenu wCopyMenu(tr("&Copy"), this);
setupCopyMenu(&wCopyMenu);
if(DbgIsDebugging())

View File

@ -3,6 +3,8 @@
#include "StdTable.h"
class WordEditDialog;
class CPUInfoBox : public StdTable
{
Q_OBJECT
@ -11,6 +13,8 @@ public:
int getHeight();
void addFollowMenuItem(QMenu* menu, QString name, duint value);
void setupFollowMenu(QMenu* menu, duint wVA);
void addModifyValueMenuItem(QMenu* menu, QString name, duint value);
void setupModifyValueMenu(QMenu* menu, duint wVA);
void addWatchMenuItem(QMenu* menu, QString name, duint value);
void setupWatchMenu(QMenu* menu, duint wVA);
int followInDump(dsint wVA);
@ -20,12 +24,17 @@ public slots:
void dbgStateChanged(DBGSTATE state);
void contextMenuSlot(QPoint pos);
void followActionSlot();
void modifySlot();
void findReferencesSlot();
void copyAddress();
void copyRva();
void copyOffset();
void doubleClickedSlot();
void addInfoLine(const QString & infoLine);
signals:
void displayReferencesWidget();
private:
dsint curAddr;
dsint curRva;

View File

@ -168,6 +168,11 @@ CPUMultiDump* CPUWidget::getDumpWidget()
return mDump;
}
CPUInfoBox* CPUWidget::getInfoBoxWidget()
{
return mInfo;
}
CPUStack* CPUWidget::getStackWidget()
{
return mStack;

View File

@ -37,6 +37,7 @@ public:
CPUDisassembly* getDisasmWidget();
CPUMultiDump* getDumpWidget();
CPUStack* getStackWidget();
CPUInfoBox* getInfoBoxWidget();
protected:
CPUSideBar* mSideBar;

View File

@ -51,6 +51,7 @@
#include "SimpleTraceDialog.h"
#include "CPUArgumentWidget.h"
#include "MRUList.h"
#include "CPUInfoBox.h"
QString MainWindow::windowTitle = "";
@ -338,6 +339,8 @@ MainWindow::MainWindow(QWidget* parent)
connect(mCpuWidget->getStackWidget(), SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mCpuWidget->getInfoBoxWidget(), SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
connect(mTabWidget, SIGNAL(tabMovedTabWidget(int, int)), this, SLOT(tabMovedSlot(int, int)));
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcuts()));

View File

@ -33,6 +33,7 @@ class SettingsDialog;
class DisassemblerGraphView;
class SimpleTraceDialog;
class MRUList;
class CPUInfoBox;
namespace Ui
{

View File

@ -565,6 +565,7 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
defaultShortcuts.insert("ActionModifyValue", Shortcut({tr("Actions"), tr("Modify value")}, "Space"));
defaultShortcuts.insert("ActionWatchDwordQword", Shortcut({tr("Actions"), tr("Watch DWORD/QWORD")}));
defaultShortcuts.insert("ActionDataCopy", Shortcut({tr("Actions"), tr("Data Copy")}));
defaultShortcuts.insert("ActionCopyFileOffset", Shortcut({tr("Actions"), tr("Copy File Offset")}));
Shortcuts = defaultShortcuts;