Some minor cpu info box enhancements (#1583)
This commit is contained in:
parent
ad2835248b
commit
bb0f582c9d
|
@ -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());
|
||||
|
|
|
@ -89,6 +89,7 @@ public slots:
|
|||
void copySelectionToFileNoBytesSlot();
|
||||
void copyAddressSlot();
|
||||
void copyRvaSlot();
|
||||
void copyFileOffsetSlot();
|
||||
void copyDisassemblySlot();
|
||||
void copyDataSlot();
|
||||
void labelCopySlot();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -90,6 +90,7 @@ public slots:
|
|||
void binaryPasteIgnoreSizeSlot();
|
||||
void binarySaveToFileSlot();
|
||||
void findPattern();
|
||||
void copyFileOffsetSlot();
|
||||
void undoSelectionSlot();
|
||||
void followStackSlot();
|
||||
void findReferencesSlot();
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -168,6 +168,11 @@ CPUMultiDump* CPUWidget::getDumpWidget()
|
|||
return mDump;
|
||||
}
|
||||
|
||||
CPUInfoBox* CPUWidget::getInfoBoxWidget()
|
||||
{
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
CPUStack* CPUWidget::getStackWidget()
|
||||
{
|
||||
return mStack;
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
CPUDisassembly* getDisasmWidget();
|
||||
CPUMultiDump* getDumpWidget();
|
||||
CPUStack* getStackWidget();
|
||||
CPUInfoBox* getInfoBoxWidget();
|
||||
|
||||
protected:
|
||||
CPUSideBar* mSideBar;
|
||||
|
|
|
@ -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()));
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ class SettingsDialog;
|
|||
class DisassemblerGraphView;
|
||||
class SimpleTraceDialog;
|
||||
class MRUList;
|
||||
class CPUInfoBox;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue