210 lines
6.8 KiB
C++
210 lines
6.8 KiB
C++
#include "CPUInfoBox.h"
|
|
|
|
CPUInfoBox::CPUInfoBox(StdTable* parent) : StdTable(parent)
|
|
{
|
|
enableMultiSelection(false);
|
|
setShowHeader(false);
|
|
addColumnAt(0, "", true);
|
|
setRowCount(3);
|
|
setCellContent(0, 0, "");
|
|
setCellContent(1, 0, "");
|
|
setCellContent(2, 0, "");
|
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
int height = getHeight();
|
|
setMaximumHeight(height);
|
|
setMinimumHeight(height);
|
|
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(dbgStateChanged(DBGSTATE)));
|
|
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
|
|
}
|
|
|
|
int CPUInfoBox::getHeight()
|
|
{
|
|
return (getRowHeight() + 1) * 3;
|
|
}
|
|
|
|
void CPUInfoBox::setInfoLine(int line, QString text)
|
|
{
|
|
if(line < 0 || line > 2)
|
|
return;
|
|
setCellContent(line, 0, text);
|
|
reloadData();
|
|
}
|
|
|
|
void CPUInfoBox::clear()
|
|
{
|
|
setInfoLine(0, "");
|
|
setInfoLine(1, "");
|
|
setInfoLine(2, "");
|
|
}
|
|
|
|
QString CPUInfoBox::getSymbolicName(int_t addr)
|
|
{
|
|
char labelText[MAX_LABEL_SIZE] = "";
|
|
char moduleText[MAX_MODULE_SIZE] = "";
|
|
bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, labelText);
|
|
bool bHasModule = (DbgGetModuleAt(addr, moduleText) && !QString(labelText).startsWith("JMP.&"));
|
|
QString addrText;
|
|
addrText = QString("%1").arg(addr & (uint_t) - 1, 0, 16, QChar('0')).toUpper();
|
|
QString finalText;
|
|
if(bHasLabel && bHasModule) //<module.label>
|
|
finalText = QString("<%1.%2>").arg(moduleText).arg(labelText);
|
|
else if(bHasModule) //module.addr
|
|
finalText = QString("%1.%2").arg(moduleText).arg(addrText);
|
|
else if(bHasLabel) //<label>
|
|
finalText = QString("<%1>").arg(labelText);
|
|
else
|
|
finalText = addrText;
|
|
return finalText;
|
|
}
|
|
|
|
void CPUInfoBox::disasmSelectionChanged(int_t parVA)
|
|
{
|
|
curAddr = parVA;
|
|
if(!DbgIsDebugging() || !DbgMemIsValidReadPtr(parVA))
|
|
return;
|
|
clear();
|
|
|
|
DISASM_INSTR instr;
|
|
DbgDisasmAt(parVA, &instr);
|
|
BASIC_INSTRUCTION_INFO basicinfo;
|
|
DbgDisasmFastAt(parVA, &basicinfo);
|
|
for(int i = 0, j = 0; i < instr.argcount && j < 2; i++)
|
|
{
|
|
DISASM_ARG arg = instr.arg[i];
|
|
if(arg.type == arg_memory)
|
|
{
|
|
QString sizeName = "";
|
|
int memsize = basicinfo.memory.size;
|
|
switch(memsize)
|
|
{
|
|
case size_byte:
|
|
sizeName = "byte ";
|
|
break;
|
|
case size_word:
|
|
sizeName = "word ";
|
|
break;
|
|
case size_dword:
|
|
sizeName = "dword ";
|
|
break;
|
|
case size_qword:
|
|
sizeName = "qword ";
|
|
break;
|
|
}
|
|
|
|
if(!DbgMemIsValidReadPtr(arg.value))
|
|
setInfoLine(j, sizeName + "[" + QString(arg.mnemonic) + "]=???");
|
|
else
|
|
{
|
|
QString addrText;
|
|
if(memsize == sizeof(int_t))
|
|
addrText = getSymbolicName(arg.memvalue);
|
|
else
|
|
addrText = QString("%1").arg(arg.memvalue, memsize * 2, 16, QChar('0')).toUpper();
|
|
setInfoLine(j, sizeName + "[" + QString(arg.mnemonic) + "]=" + addrText);
|
|
}
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
QString mnemonic(arg.mnemonic);
|
|
bool ok;
|
|
mnemonic.toULongLong(&ok, 16);
|
|
if(ok) //skip numbers
|
|
continue;
|
|
setInfoLine(j, mnemonic + "=" + getSymbolicName(arg.value));
|
|
j++;
|
|
}
|
|
}
|
|
|
|
//set last line
|
|
QString info;
|
|
char mod[MAX_MODULE_SIZE] = "";
|
|
if(DbgFunctions()->ModNameFromAddr(parVA, mod, true))
|
|
{
|
|
int_t modbase = DbgFunctions()->ModBaseFromAddr(parVA);
|
|
if(modbase)
|
|
info = QString(mod) + "[" + QString("%1").arg(parVA - modbase, 0, 16, QChar('0')).toUpper() + "] | ";
|
|
else
|
|
info = QString(mod) + " | ";
|
|
}
|
|
char section[10] = "";
|
|
if(DbgFunctions()->SectionFromAddr(parVA, section))
|
|
info += "\"" + QString(section) + "\":";
|
|
info += QString("%1").arg(parVA, sizeof(int_t) * 2, 16, QChar('0')).toUpper();
|
|
char label[MAX_LABEL_SIZE] = "";
|
|
if(DbgGetLabelAt(parVA, SEG_DEFAULT, label))
|
|
info += " <" + QString(label) + ">";
|
|
setInfoLine(2, info);
|
|
}
|
|
|
|
void CPUInfoBox::dbgStateChanged(DBGSTATE state)
|
|
{
|
|
if(state == stopped)
|
|
clear();
|
|
}
|
|
|
|
void CPUInfoBox::followActionSlot()
|
|
{
|
|
QAction* action = qobject_cast<QAction*>(sender());
|
|
if(action && action->objectName().startsWith("DUMP|"))
|
|
DbgCmdExec(QString().sprintf("dump \"%s\"", action->objectName().mid(5).toUtf8().constData()).toUtf8().constData());
|
|
}
|
|
|
|
void CPUInfoBox::addFollowMenuItem(QMenu* menu, QString name, int_t value)
|
|
{
|
|
QAction* newAction = new QAction(name, this);
|
|
newAction->setFont(QFont("Courier New", 8));
|
|
menu->addAction(newAction);
|
|
newAction->setObjectName(QString("DUMP|") + QString("%1").arg(value, sizeof(int_t) * 2, 16, QChar('0')).toUpper());
|
|
connect(newAction, SIGNAL(triggered()), this, SLOT(followActionSlot()));
|
|
}
|
|
|
|
void CPUInfoBox::setupFollowMenu(QMenu* menu, int_t wVA)
|
|
{
|
|
//most basic follow action
|
|
addFollowMenuItem(menu, "&Selection", wVA);
|
|
|
|
//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)
|
|
{
|
|
if(DbgMemIsValidReadPtr(arg.value))
|
|
addFollowMenuItem(menu, "&Address: " + QString(arg.mnemonic).toUpper().trimmed(), arg.value);
|
|
if(arg.value != arg.constant)
|
|
{
|
|
QString constant = QString("%1").arg(arg.constant, 1, 16, QChar('0')).toUpper();
|
|
if(DbgMemIsValidReadPtr(arg.constant))
|
|
addFollowMenuItem(menu, "&Constant: " + constant, arg.value);
|
|
}
|
|
if(DbgMemIsValidReadPtr(arg.memvalue))
|
|
addFollowMenuItem(menu, "&Value: [" + QString(arg.mnemonic) + "]", arg.value);
|
|
}
|
|
else
|
|
{
|
|
if(DbgMemIsValidReadPtr(arg.value))
|
|
addFollowMenuItem(menu, QString(arg.mnemonic).toUpper().trimmed(), arg.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CPUInfoBox::contextMenuSlot(QPoint pos)
|
|
{
|
|
QMenu* wMenu = new QMenu(this); //create context menu
|
|
QMenu* wFollowMenu = new QMenu("&Follow in Dump", this);
|
|
setupFollowMenu(wFollowMenu, curAddr);
|
|
wMenu->addMenu(wFollowMenu);
|
|
QMenu wCopyMenu("&Copy", this);
|
|
setupCopyMenu(&wCopyMenu);
|
|
if(wCopyMenu.actions().length())
|
|
{
|
|
wMenu->addSeparator();
|
|
wMenu->addMenu(&wCopyMenu);
|
|
}
|
|
wMenu->exec(mapToGlobal(pos)); //execute context menu
|
|
}
|