commit
d084dc48a5
|
@ -112,6 +112,8 @@ void CPUWidget::saveWindowSettings()
|
|||
saveSplitter(ui->mVSplitter, "mVSplitter");
|
||||
saveSplitter(ui->mTopHSplitter, "mTopHSplitter");
|
||||
saveSplitter(ui->mTopLeftVSplitter, "mTopLeftVSplitter");
|
||||
if(disasMode == 1 && mDisasmSidebarSplitterStatus.size() > 0) // restore correct sidebar state
|
||||
ui->mTopLeftUpperHSplitter->restoreState(mDisasmSidebarSplitterStatus);
|
||||
saveSplitter(ui->mTopLeftUpperHSplitter, "mTopLeftUpperHSplitter");
|
||||
saveSplitter(ui->mTopRightVSplitter, "mTopRightVSplitter");
|
||||
saveSplitter(ui->mBotHSplitter, "mBotHSplitter");
|
||||
|
@ -169,6 +171,7 @@ void CPUWidget::setDisasmFocus()
|
|||
mGraph->hide();
|
||||
mDisas->show();
|
||||
mSideBar->show();
|
||||
ui->mTopLeftUpperHSplitter->restoreState(mDisasmSidebarSplitterStatus);
|
||||
disasMode = 0;
|
||||
connect(mDisas, SIGNAL(selectionChanged(dsint)), mInfo, SLOT(disasmSelectionChanged(dsint)));
|
||||
disconnect(mGraph, SIGNAL(selectionChanged(dsint)), mInfo, SLOT(disasmSelectionChanged(dsint)));
|
||||
|
@ -184,9 +187,12 @@ void CPUWidget::setGraphFocus()
|
|||
{
|
||||
if(disasMode == 0)
|
||||
{
|
||||
mDisasmSidebarSplitterStatus = ui->mTopLeftUpperHSplitter->saveState();
|
||||
mDisas->hide();
|
||||
mSideBar->hide();
|
||||
mGraph->show();
|
||||
// Hide the sidebar area
|
||||
ui->mTopLeftUpperHSplitter->setSizes(QList<int>({0, 100}));
|
||||
disasMode = 1;
|
||||
disconnect(mDisas, SIGNAL(selectionChanged(dsint)), mInfo, SLOT(disasmSelectionChanged(dsint)));
|
||||
connect(mGraph, SIGNAL(selectionChanged(dsint)), mInfo, SLOT(disasmSelectionChanged(dsint)));
|
||||
|
@ -235,6 +241,8 @@ void CPUWidget::detachGraph()
|
|||
|
||||
mDisas->show();
|
||||
mSideBar->show();
|
||||
// restore the sidebar splitter so that the sidebar is visible
|
||||
ui->mTopLeftUpperHSplitter->restoreState(mDisasmSidebarSplitterStatus);
|
||||
connect(mDisas, SIGNAL(selectionChanged(dsint)), mInfo, SLOT(disasmSelectionChanged(dsint)));
|
||||
connect(mGraph, SIGNAL(selectionChanged(dsint)), mInfo, SLOT(disasmSelectionChanged(dsint)));
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ protected:
|
|||
|
||||
private:
|
||||
Ui::CPUWidget* ui;
|
||||
QByteArray mDisasmSidebarSplitterStatus;
|
||||
|
||||
private slots:
|
||||
void splitterMoved(int pos, int index);
|
||||
|
|
|
@ -17,117 +17,130 @@
|
|||
<iconset resource="../../resource.qrc">
|
||||
<normaloff>:/icons/images/patch.png</normaloff>:/icons/images/patch.png</iconset>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layoutModules">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupModules">
|
||||
<property name="title">
|
||||
<string>&Modules</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QListWidget" name="listModules">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="layoutModules">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnImport">
|
||||
<property name="text">
|
||||
<string>&Import</string>
|
||||
<widget class="QGroupBox" name="groupModules">
|
||||
<property name="title">
|
||||
<string>&Modules</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QListWidget" name="listModules">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnExport">
|
||||
<property name="text">
|
||||
<string>&Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnImport">
|
||||
<property name="text">
|
||||
<string>&Import</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnExport">
|
||||
<property name="text">
|
||||
<string>&Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layoutPatches">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupPatches">
|
||||
<property name="title">
|
||||
<string>P&atches</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QListWidget" name="listPatches">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="layoutPatches">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSelectAll">
|
||||
<property name="text">
|
||||
<string>&Select All</string>
|
||||
<widget class="QGroupBox" name="groupPatches">
|
||||
<property name="title">
|
||||
<string>P&atches</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QListWidget" name="listPatches">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDeselectAll">
|
||||
<property name="text">
|
||||
<string>&Deselect All</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSelectAll">
|
||||
<property name="text">
|
||||
<string>&Select All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDeselectAll">
|
||||
<property name="text">
|
||||
<string>&Deselect All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRestoreSelected">
|
||||
<property name="text">
|
||||
<string>&Restore Selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRestoreSelected">
|
||||
<property name="text">
|
||||
<string>&Restore Selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPickGroups">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pick &Groups</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPatchFile">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Patch File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPickGroups">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pick &Groups</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPatchFile">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Patch File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -135,12 +148,6 @@
|
|||
<tabstop>listModules</tabstop>
|
||||
<tabstop>btnImport</tabstop>
|
||||
<tabstop>btnExport</tabstop>
|
||||
<tabstop>listPatches</tabstop>
|
||||
<tabstop>btnSelectAll</tabstop>
|
||||
<tabstop>btnDeselectAll</tabstop>
|
||||
<tabstop>btnRestoreSelected</tabstop>
|
||||
<tabstop>btnPickGroups</tabstop>
|
||||
<tabstop>btnPatchFile</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../resource.qrc"/>
|
||||
|
|
|
@ -635,28 +635,43 @@ void SymbolView::moduleEntryFollow()
|
|||
|
||||
void SymbolView::moduleCopyPath()
|
||||
{
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(mModuleList->mCurList->getInitialSelection(), ColBase).toUtf8().constData());
|
||||
char szModPath[MAX_PATH] = "";
|
||||
if(DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath)))
|
||||
Bridge::CopyToClipboard(szModPath);
|
||||
QString modulePaths;
|
||||
auto selection = mModuleList->mCurList->getSelection();
|
||||
for(auto i : selection)
|
||||
{
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(i, ColBase).toUtf8().constData());
|
||||
char szModPath[MAX_PATH] = "";
|
||||
if(!DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath)))
|
||||
memcpy(szModPath, "???", 4);
|
||||
if(!modulePaths.isEmpty())
|
||||
modulePaths.append("\r\n");
|
||||
modulePaths.append(szModPath);
|
||||
}
|
||||
Bridge::CopyToClipboard(modulePaths);
|
||||
}
|
||||
|
||||
void SymbolView::moduleBrowse()
|
||||
{
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(mModuleList->mCurList->getInitialSelection(), ColBase).toUtf8().constData());
|
||||
char szModPath[MAX_PATH] = "";
|
||||
if(DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath)))
|
||||
auto selection = mModuleList->mCurList->getSelection();
|
||||
for(auto i : selection)
|
||||
{
|
||||
QStringList arguments;
|
||||
arguments << QString("/select,");
|
||||
arguments << QString(szModPath);
|
||||
QProcess::startDetached(QString("%1/explorer.exe").arg(QProcessEnvironment::systemEnvironment().value("windir")), arguments);
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(i, ColBase).toUtf8().constData());
|
||||
char szModPath[MAX_PATH] = "";
|
||||
if(DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath)))
|
||||
{
|
||||
QStringList arguments;
|
||||
arguments << QString("/select,");
|
||||
arguments << QString(szModPath);
|
||||
QProcess::startDetached(QString("%1/explorer.exe").arg(QProcessEnvironment::systemEnvironment().value("windir")), arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolView::moduleDownloadSymbols()
|
||||
{
|
||||
DbgCmdExec(QString("symdownload \"%0\"").arg(mModuleList->mCurList->getCellContent(mModuleList->mCurList->getInitialSelection(), ColModule)));
|
||||
auto selection = mModuleList->mCurList->getSelection();
|
||||
for(auto i : selection)
|
||||
DbgCmdExec(QString("symdownload \"%0\"").arg(mModuleList->mCurList->getCellContent(i, ColModule)));
|
||||
}
|
||||
|
||||
void SymbolView::moduleDownloadAllSymbols()
|
||||
|
@ -691,7 +706,11 @@ void SymbolView::moduleFree()
|
|||
question.toUtf8().constData(),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if(reply == QMessageBox::Yes)
|
||||
DbgCmdExec(QString("freelib %1").arg(mModuleList->mCurList->getCellContent(mModuleList->mCurList->getInitialSelection(), ColBase)));
|
||||
{
|
||||
auto selection = mModuleList->mCurList->getSelection();
|
||||
for(auto module : selection)
|
||||
DbgCmdExec(QString("freelib %1").arg(mModuleList->mCurList->getCellContent(module, ColBase)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -742,42 +761,53 @@ void SymbolView::toggleBookmark()
|
|||
|
||||
if(!mSymbolList->mCurList->getRowCount())
|
||||
return;
|
||||
QString addrText = mSymbolList->mCurList->getCellContent(mSymbolList->mCurList->getInitialSelection(), 0);
|
||||
duint wVA;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
|
||||
return;
|
||||
if(!DbgMemIsValidReadPtr(wVA))
|
||||
return;
|
||||
|
||||
bool result;
|
||||
if(DbgGetBookmarkAt(wVA))
|
||||
result = DbgSetBookmarkAt(wVA, false);
|
||||
else
|
||||
result = DbgSetBookmarkAt(wVA, true);
|
||||
if(!result)
|
||||
auto selection = mSymbolList->mCurList->getSelection();
|
||||
for(auto index : selection)
|
||||
{
|
||||
QMessageBox msg(QMessageBox::Critical, tr("Error!"), tr("DbgSetBookmarkAt failed!"));
|
||||
msg.setWindowIcon(DIcon("compile-error.png"));
|
||||
msg.setParent(this, Qt::Dialog);
|
||||
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
msg.exec();
|
||||
QString addrText = mSymbolList->mCurList->getCellContent(index, 0);
|
||||
duint wVA;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
|
||||
return;
|
||||
if(!DbgMemIsValidReadPtr(wVA))
|
||||
return;
|
||||
|
||||
bool result;
|
||||
if(DbgGetBookmarkAt(wVA))
|
||||
result = DbgSetBookmarkAt(wVA, false);
|
||||
else
|
||||
result = DbgSetBookmarkAt(wVA, true);
|
||||
if(!result)
|
||||
{
|
||||
QMessageBox msg(QMessageBox::Critical, tr("Error!"), tr("DbgSetBookmarkAt failed!"));
|
||||
msg.setWindowIcon(DIcon("compile-error.png"));
|
||||
msg.setParent(this, Qt::Dialog);
|
||||
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
msg.exec();
|
||||
}
|
||||
}
|
||||
GuiUpdateAllViews();
|
||||
}
|
||||
|
||||
void SymbolView::moduleSetSystem()
|
||||
{
|
||||
int i = mModuleList->mCurList->getInitialSelection();
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(i, ColBase).toUtf8().constData());
|
||||
DbgFunctions()->ModSetParty(modbase, mod_system);
|
||||
auto selection = mModuleList->mCurList->getSelection();
|
||||
for(auto i : selection)
|
||||
{
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(i, ColBase).toUtf8().constData());
|
||||
DbgFunctions()->ModSetParty(modbase, mod_system);
|
||||
}
|
||||
DbgFunctions()->RefreshModuleList();
|
||||
}
|
||||
|
||||
void SymbolView::moduleSetUser()
|
||||
{
|
||||
int i = mModuleList->mCurList->getInitialSelection();
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(i, ColBase).toUtf8().constData());
|
||||
DbgFunctions()->ModSetParty(modbase, mod_user);
|
||||
auto selection = mModuleList->mCurList->getSelection();
|
||||
for(auto i : selection)
|
||||
{
|
||||
duint modbase = DbgValFromString(mModuleList->mCurList->getCellContent(i, ColBase).toUtf8().constData());
|
||||
DbgFunctions()->ModSetParty(modbase, mod_user);
|
||||
}
|
||||
DbgFunctions()->RefreshModuleList();
|
||||
}
|
||||
|
||||
|
@ -792,27 +822,18 @@ void SymbolView::moduleSetParty()
|
|||
{
|
||||
bool ok;
|
||||
party = mLineEditeditText.toInt(&ok);
|
||||
int i = mModuleList->mCurList->getInitialSelection();
|
||||
if(ok)
|
||||
{
|
||||
DbgFunctions()->ModSetParty(modbase, (MODULEPARTY)party);
|
||||
/* TODO: refresh module list
|
||||
switch(party)
|
||||
auto selection = mModuleList->mCurList->getSelection();
|
||||
for(auto index : selection)
|
||||
{
|
||||
case 0:
|
||||
mModuleList->mCurList->setCellContent(i, 2, tr("User"));
|
||||
break;
|
||||
case 1:
|
||||
mModuleList->mCurList->setCellContent(i, 2, tr("System"));
|
||||
break;
|
||||
default:
|
||||
mModuleList->mCurList->setCellContent(i, 2, tr("Party: %1").arg(party));
|
||||
break;
|
||||
modbase = DbgValFromString(mModuleList->mCurList->getCellContent(index, ColBase).toUtf8().constData());
|
||||
DbgFunctions()->ModSetParty(modbase, (MODULEPARTY)party);
|
||||
}
|
||||
mModuleList->mCurList->reloadData();*/
|
||||
}
|
||||
else
|
||||
SimpleErrorBox(this, tr("Error"), tr("The party number can only be 0 or 1"));
|
||||
DbgFunctions()->RefreshModuleList();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,363 @@
|
|||
#include "TraceInfoBox.h"
|
||||
#include "TraceWidget.h"
|
||||
#include "TraceFileReader.h"
|
||||
#include "CPUInfoBox.h"
|
||||
#include "zydis_wrapper.h"
|
||||
|
||||
TraceInfoBox::TraceInfoBox(TraceWidget* parent) : StdTable(parent)
|
||||
{
|
||||
addColumnAt(0, "", true);
|
||||
setShowHeader(false);
|
||||
clean();
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setMinimumHeight((getRowHeight() + 1) * 4);
|
||||
|
||||
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
|
||||
|
||||
// Deselect any row (visual reasons only)
|
||||
setSingleSelection(-1);
|
||||
}
|
||||
|
||||
TraceInfoBox::~TraceInfoBox()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TraceInfoBox::clean()
|
||||
{
|
||||
setRowCount(4);
|
||||
for(int i = 0; i < 4; i++)
|
||||
setCellContent(i, 0, QString());
|
||||
}
|
||||
|
||||
void TraceInfoBox::update(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers)
|
||||
{
|
||||
int infoline = 0;
|
||||
Zydis zydis;
|
||||
unsigned char opcode[16];
|
||||
QString line;
|
||||
int opsize;
|
||||
traceFile->OpCode(selection, opcode, &opsize);
|
||||
clean();
|
||||
auto resolveRegValue = [®isters](ZydisRegister regname)
|
||||
{
|
||||
switch(regname)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
case ZYDIS_REGISTER_RAX:
|
||||
return registers.regcontext.cax;
|
||||
case ZYDIS_REGISTER_RCX:
|
||||
return registers.regcontext.ccx;
|
||||
case ZYDIS_REGISTER_RDX:
|
||||
return registers.regcontext.cdx;
|
||||
case ZYDIS_REGISTER_RBX:
|
||||
return registers.regcontext.cbx;
|
||||
case ZYDIS_REGISTER_RSP:
|
||||
return registers.regcontext.csp;
|
||||
case ZYDIS_REGISTER_RBP:
|
||||
return registers.regcontext.cbp;
|
||||
case ZYDIS_REGISTER_RSI:
|
||||
return registers.regcontext.csi;
|
||||
case ZYDIS_REGISTER_RDI:
|
||||
return registers.regcontext.cdi;
|
||||
case ZYDIS_REGISTER_R8:
|
||||
return registers.regcontext.r8;
|
||||
case ZYDIS_REGISTER_R9:
|
||||
return registers.regcontext.r9;
|
||||
case ZYDIS_REGISTER_R10:
|
||||
return registers.regcontext.r10;
|
||||
case ZYDIS_REGISTER_R11:
|
||||
return registers.regcontext.r11;
|
||||
case ZYDIS_REGISTER_R12:
|
||||
return registers.regcontext.r12;
|
||||
case ZYDIS_REGISTER_R13:
|
||||
return registers.regcontext.r13;
|
||||
case ZYDIS_REGISTER_R14:
|
||||
return registers.regcontext.r14;
|
||||
case ZYDIS_REGISTER_R15:
|
||||
return registers.regcontext.r15;
|
||||
case ZYDIS_REGISTER_R8D:
|
||||
return registers.regcontext.r8 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R9D:
|
||||
return registers.regcontext.r9 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R10D:
|
||||
return registers.regcontext.r10 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R11D:
|
||||
return registers.regcontext.r11 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R12D:
|
||||
return registers.regcontext.r12 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R13D:
|
||||
return registers.regcontext.r13 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R15D:
|
||||
return registers.regcontext.r15 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R8W:
|
||||
return registers.regcontext.r8 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R9W:
|
||||
return registers.regcontext.r9 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R10W:
|
||||
return registers.regcontext.r10 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R11W:
|
||||
return registers.regcontext.r11 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R12W:
|
||||
return registers.regcontext.r12 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R13W:
|
||||
return registers.regcontext.r13 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R15W:
|
||||
return registers.regcontext.r15 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R8B:
|
||||
return registers.regcontext.r8 & 0xFF;
|
||||
case ZYDIS_REGISTER_R9B:
|
||||
return registers.regcontext.r9 & 0xFF;
|
||||
case ZYDIS_REGISTER_R10B:
|
||||
return registers.regcontext.r10 & 0xFF;
|
||||
case ZYDIS_REGISTER_R11B:
|
||||
return registers.regcontext.r11 & 0xFF;
|
||||
case ZYDIS_REGISTER_R12B:
|
||||
return registers.regcontext.r12 & 0xFF;
|
||||
case ZYDIS_REGISTER_R13B:
|
||||
return registers.regcontext.r13 & 0xFF;
|
||||
case ZYDIS_REGISTER_R15B:
|
||||
return registers.regcontext.r15 & 0xFF;
|
||||
#endif //_WIN64
|
||||
case ZYDIS_REGISTER_EAX:
|
||||
return registers.regcontext.cax & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_ECX:
|
||||
return registers.regcontext.ccx & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EDX:
|
||||
return registers.regcontext.cdx & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EBX:
|
||||
return registers.regcontext.cbx & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_ESP:
|
||||
return registers.regcontext.csp & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EBP:
|
||||
return registers.regcontext.cbp & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_ESI:
|
||||
return registers.regcontext.csi & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EDI:
|
||||
return registers.regcontext.cdi & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_AX:
|
||||
return registers.regcontext.cax & 0xFFFF;
|
||||
case ZYDIS_REGISTER_CX:
|
||||
return registers.regcontext.ccx & 0xFFFF;
|
||||
case ZYDIS_REGISTER_DX:
|
||||
return registers.regcontext.cdx & 0xFFFF;
|
||||
case ZYDIS_REGISTER_BX:
|
||||
return registers.regcontext.cbx & 0xFFFF;
|
||||
case ZYDIS_REGISTER_SP:
|
||||
return registers.regcontext.csp & 0xFFFF;
|
||||
case ZYDIS_REGISTER_BP:
|
||||
return registers.regcontext.cbp & 0xFFFF;
|
||||
case ZYDIS_REGISTER_SI:
|
||||
return registers.regcontext.csi & 0xFFFF;
|
||||
case ZYDIS_REGISTER_DI:
|
||||
return registers.regcontext.cdi & 0xFFFF;
|
||||
case ZYDIS_REGISTER_AL:
|
||||
return registers.regcontext.cax & 0xFF;
|
||||
case ZYDIS_REGISTER_CL:
|
||||
return registers.regcontext.ccx & 0xFF;
|
||||
case ZYDIS_REGISTER_DL:
|
||||
return registers.regcontext.cdx & 0xFF;
|
||||
case ZYDIS_REGISTER_BL:
|
||||
return registers.regcontext.cbx & 0xFF;
|
||||
case ZYDIS_REGISTER_AH:
|
||||
return (registers.regcontext.cax & 0xFF00) >> 8;
|
||||
case ZYDIS_REGISTER_CH:
|
||||
return (registers.regcontext.ccx & 0xFF00) >> 8;
|
||||
case ZYDIS_REGISTER_DH:
|
||||
return (registers.regcontext.cdx & 0xFF00) >> 8;
|
||||
case ZYDIS_REGISTER_BH:
|
||||
return (registers.regcontext.cbx & 0xFF00) >> 8;
|
||||
default:
|
||||
return static_cast<ULONG_PTR>(0);
|
||||
}
|
||||
};
|
||||
duint MemoryAddress[MAX_MEMORY_OPERANDS];
|
||||
duint MemoryOldContent[MAX_MEMORY_OPERANDS];
|
||||
duint MemoryNewContent[MAX_MEMORY_OPERANDS];
|
||||
bool MemoryIsValid[MAX_MEMORY_OPERANDS];
|
||||
int MemoryOperandsCount;
|
||||
MemoryOperandsCount = traceFile->MemoryAccessCount(selection);
|
||||
if(MemoryOperandsCount > 0)
|
||||
traceFile->MemoryAccessInfo(selection, MemoryAddress, MemoryOldContent, MemoryNewContent, MemoryIsValid);
|
||||
if(zydis.Disassemble(registers.regcontext.cip, opcode, opsize))
|
||||
{
|
||||
int opindex;
|
||||
int memaccessindex;
|
||||
//Jumps
|
||||
if(zydis.IsBranchType(Zydis::BTCondJmp))
|
||||
{
|
||||
if(zydis.IsBranchGoingToExecute(registers.regcontext.eflags, registers.regcontext.ccx))
|
||||
{
|
||||
line = tr("Jump is taken");
|
||||
}
|
||||
else
|
||||
{
|
||||
line = tr("Jump is not taken");
|
||||
}
|
||||
setCellContent(infoline, 0, line);
|
||||
infoline++;
|
||||
}
|
||||
//Operands
|
||||
QString registerLine, memoryLine;
|
||||
for(opindex = 0; opindex < zydis.OpCount(); opindex++)
|
||||
{
|
||||
size_t value = zydis.ResolveOpValue(opindex, resolveRegValue);
|
||||
if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
{
|
||||
if(!memoryLine.isEmpty())
|
||||
memoryLine += ", ";
|
||||
const char* memsize = zydis.MemSizeName(zydis[opindex].size / 8);
|
||||
if(memsize != nullptr)
|
||||
{
|
||||
memoryLine += memsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
memoryLine += QString("m%1").arg(zydis[opindex].size / 8);
|
||||
}
|
||||
memoryLine += " ptr ";
|
||||
memoryLine += zydis.RegName(zydis[opindex].mem.segment);
|
||||
memoryLine += ":[";
|
||||
memoryLine += ToPtrString(value);
|
||||
memoryLine += "]";
|
||||
if(zydis[opindex].size == 64 && zydis.getVectorElementType(opindex) == Zydis::VETFloat64)
|
||||
{
|
||||
// Double precision
|
||||
#ifdef _WIN64
|
||||
//TODO: Untested
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
memoryLine += "= ";
|
||||
memoryLine += ToDoubleString(&MemoryOldContent[memaccessindex]);
|
||||
memoryLine += " -> ";
|
||||
memoryLine += ToDoubleString(&MemoryNewContent[memaccessindex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// On 32-bit platform it is saved as 2 memory accesses.
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount - 1; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value && MemoryAddress[memaccessindex + 1] == value + 4)
|
||||
{
|
||||
double dblval;
|
||||
memoryLine += "= ";
|
||||
memcpy(&dblval, &MemoryOldContent[memaccessindex], 4);
|
||||
memcpy(((char*)&dblval) + 4, &MemoryOldContent[memaccessindex + 1], 4);
|
||||
memoryLine += ToDoubleString(&dblval);
|
||||
memoryLine += " -> ";
|
||||
memcpy(&dblval, &MemoryNewContent[memaccessindex], 4);
|
||||
memcpy(((char*)&dblval) + 4, &MemoryNewContent[memaccessindex + 1], 4);
|
||||
memoryLine += ToDoubleString(&dblval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(zydis[opindex].size == 32 && zydis.getVectorElementType(opindex) == Zydis::VETFloat32)
|
||||
{
|
||||
// Single precision
|
||||
//TODO: Untested
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
memoryLine += "= ";
|
||||
memoryLine += ToFloatString(&MemoryOldContent[memaccessindex]);
|
||||
memoryLine += " -> ";
|
||||
memoryLine += ToFloatString(&MemoryNewContent[memaccessindex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(zydis[opindex].size <= sizeof(void*) * 8)
|
||||
{
|
||||
// Handle the most common case (ptr-sized)
|
||||
duint mask;
|
||||
if(zydis[opindex].size < sizeof(void*) * 8)
|
||||
mask = (1 << zydis[opindex].size) - 1;
|
||||
else
|
||||
mask = ~(duint)0;
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
memoryLine += "=";
|
||||
memoryLine += ToHexString(MemoryOldContent[memaccessindex] & mask);
|
||||
memoryLine += " -> ";
|
||||
memoryLine += ToHexString(MemoryNewContent[memaccessindex] & mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_REGISTER)
|
||||
{
|
||||
const auto registerName = zydis[opindex].reg.value;
|
||||
if(!registerLine.isEmpty())
|
||||
registerLine += ", ";
|
||||
registerLine += zydis.RegName(registerName);
|
||||
registerLine += " = ";
|
||||
// Special treatment for FPU registers
|
||||
if(registerName >= ZYDIS_REGISTER_ST0 && registerName <= ZYDIS_REGISTER_ST7)
|
||||
{
|
||||
// x87 FPU
|
||||
registerLine += ToLongDoubleString(®isters.x87FPURegisters[(registers.x87StatusWordFields.TOP + registerName - ZYDIS_REGISTER_ST0) & 7].data);
|
||||
}
|
||||
else if(registerName >= ZYDIS_REGISTER_XMM0 && registerName <= ArchValue(ZYDIS_REGISTER_XMM7, ZYDIS_REGISTER_XMM15))
|
||||
{
|
||||
registerLine += CPUInfoBox::formatSSEOperand(QByteArray((const char*)®isters.regcontext.XmmRegisters[registerName - ZYDIS_REGISTER_XMM0], 16), zydis.getVectorElementType(opindex));
|
||||
}
|
||||
else if(registerName >= ZYDIS_REGISTER_YMM0 && registerName <= ArchValue(ZYDIS_REGISTER_YMM7, ZYDIS_REGISTER_YMM15))
|
||||
{
|
||||
//TODO: Untested
|
||||
registerLine += CPUInfoBox::formatSSEOperand(QByteArray((const char*)®isters.regcontext.YmmRegisters[registerName - ZYDIS_REGISTER_XMM0], 32), zydis.getVectorElementType(opindex));
|
||||
}
|
||||
else
|
||||
{
|
||||
// GPR
|
||||
registerLine += ToPtrString(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!registerLine.isEmpty())
|
||||
{
|
||||
setCellContent(infoline, 0, registerLine);
|
||||
infoline++;
|
||||
}
|
||||
if(!memoryLine.isEmpty())
|
||||
{
|
||||
setCellContent(infoline, 0, memoryLine);
|
||||
infoline++;
|
||||
}
|
||||
DWORD tid;
|
||||
tid = traceFile->ThreadId(selection);
|
||||
line = QString("ThreadID: %1").arg(ConfigBool("Gui", "PidTidInHex") ? ToHexString(tid) : QString::number(tid));
|
||||
setCellContent(3, 0, line);
|
||||
}
|
||||
reloadData();
|
||||
}
|
||||
|
||||
void TraceInfoBox::setupContextMenu()
|
||||
{
|
||||
mCopyLineAction = makeAction(tr("Copy Line"), SLOT(copyLineSlot()));
|
||||
setupShortcuts();
|
||||
}
|
||||
|
||||
void TraceInfoBox::contextMenuSlot(QPoint pos)
|
||||
{
|
||||
QMenu wMenu(this); //create context menu
|
||||
QMenu wCopyMenu(tr("&Copy"), this);
|
||||
setupCopyMenu(&wCopyMenu);
|
||||
wMenu.addMenu(&wCopyMenu);
|
||||
wMenu.exec(mapToGlobal(pos)); //execute context menu
|
||||
}
|
||||
|
||||
void TraceInfoBox::setupShortcuts()
|
||||
{
|
||||
mCopyLineAction->setShortcut(ConfigShortcut("ActionCopyLine"));
|
||||
addAction(mCopyLineAction);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef TRACEINFOBOX_H
|
||||
#define TRACEINFOBOX_H
|
||||
#include "StdTable.h"
|
||||
|
||||
class TraceWidget;
|
||||
class TraceFileReader;
|
||||
|
||||
class TraceInfoBox : public StdTable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TraceInfoBox(TraceWidget* parent);
|
||||
~TraceInfoBox();
|
||||
|
||||
void update(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers);
|
||||
|
||||
public slots:
|
||||
void contextMenuSlot(QPoint pos);
|
||||
|
||||
private:
|
||||
void setupContextMenu();
|
||||
void setupShortcuts();
|
||||
void clean();
|
||||
|
||||
QAction* mCopyLineAction;
|
||||
};
|
||||
|
||||
#endif //TRACEINFOBOX_H
|
|
@ -1,6 +1,7 @@
|
|||
#include "TraceWidget.h"
|
||||
#include "ui_TraceWidget.h"
|
||||
#include "TraceBrowser.h"
|
||||
#include "TraceInfoBox.h"
|
||||
#include "TraceFileReader.h"
|
||||
#include "TraceRegisters.h"
|
||||
#include "StdTable.h"
|
||||
|
@ -14,7 +15,7 @@ TraceWidget::TraceWidget(QWidget* parent) :
|
|||
|
||||
mTraceWidget = new TraceBrowser(this);
|
||||
mOverview = new StdTable(this);
|
||||
mInfo = new StdTable(this);
|
||||
mInfo = new TraceInfoBox(this);
|
||||
mGeneralRegs = new TraceRegisters(this);
|
||||
//disasm
|
||||
ui->mTopLeftUpperRightFrameLayout->addWidget(mTraceWidget);
|
||||
|
@ -47,15 +48,6 @@ TraceWidget::TraceWidget(QWidget* parent) :
|
|||
ui->mTopHSplitter->setSizes(QList<int>({1000, 1}));
|
||||
ui->mTopLeftVSplitter->setSizes(QList<int>({1000, 1}));
|
||||
|
||||
mInfo->addColumnAt(0, "", true);
|
||||
mInfo->setShowHeader(false);
|
||||
mInfo->setRowCount(4);
|
||||
mInfo->setCellContent(0, 0, QString());
|
||||
mInfo->setCellContent(1, 0, QString());
|
||||
mInfo->setCellContent(2, 0, QString());
|
||||
mInfo->setCellContent(3, 0, QString());
|
||||
mInfo->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
mInfo->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
//overview
|
||||
ui->mTopRightLowerFrameLayout->addWidget(mOverview);
|
||||
|
||||
|
@ -85,7 +77,7 @@ void TraceWidget::traceSelectionChanged(unsigned long long selection)
|
|||
if(selection < traceFile->Length())
|
||||
{
|
||||
registers = traceFile->Registers(selection);
|
||||
updateInfobox(selection, traceFile, registers);
|
||||
mInfo->update(selection, traceFile, registers);
|
||||
}
|
||||
else
|
||||
memset(®isters, 0, sizeof(registers));
|
||||
|
@ -102,317 +94,3 @@ TraceBrowser* TraceWidget::getTraceBrowser()
|
|||
{
|
||||
return mTraceWidget;
|
||||
}
|
||||
|
||||
void TraceWidget::updateInfobox(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers)
|
||||
{
|
||||
int infoline = 0;
|
||||
Zydis zydis;
|
||||
unsigned char opcode[16];
|
||||
QString line;
|
||||
int opsize;
|
||||
traceFile->OpCode(selection, opcode, &opsize);
|
||||
mInfo->setRowCount(4);
|
||||
mInfo->setCellContent(0, 0, QString());
|
||||
mInfo->setCellContent(1, 0, QString());
|
||||
mInfo->setCellContent(2, 0, QString());
|
||||
mInfo->setCellContent(3, 0, QString());
|
||||
auto resolveRegValue = [®isters](ZydisRegister regname)
|
||||
{
|
||||
switch(regname)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
case ZYDIS_REGISTER_RAX:
|
||||
return registers.regcontext.cax;
|
||||
case ZYDIS_REGISTER_RCX:
|
||||
return registers.regcontext.ccx;
|
||||
case ZYDIS_REGISTER_RDX:
|
||||
return registers.regcontext.cdx;
|
||||
case ZYDIS_REGISTER_RBX:
|
||||
return registers.regcontext.cbx;
|
||||
case ZYDIS_REGISTER_RSP:
|
||||
return registers.regcontext.csp;
|
||||
case ZYDIS_REGISTER_RBP:
|
||||
return registers.regcontext.cbp;
|
||||
case ZYDIS_REGISTER_RSI:
|
||||
return registers.regcontext.csi;
|
||||
case ZYDIS_REGISTER_RDI:
|
||||
return registers.regcontext.cdi;
|
||||
case ZYDIS_REGISTER_R8:
|
||||
return registers.regcontext.r8;
|
||||
case ZYDIS_REGISTER_R9:
|
||||
return registers.regcontext.r9;
|
||||
case ZYDIS_REGISTER_R10:
|
||||
return registers.regcontext.r10;
|
||||
case ZYDIS_REGISTER_R11:
|
||||
return registers.regcontext.r11;
|
||||
case ZYDIS_REGISTER_R12:
|
||||
return registers.regcontext.r12;
|
||||
case ZYDIS_REGISTER_R13:
|
||||
return registers.regcontext.r13;
|
||||
case ZYDIS_REGISTER_R14:
|
||||
return registers.regcontext.r14;
|
||||
case ZYDIS_REGISTER_R15:
|
||||
return registers.regcontext.r15;
|
||||
case ZYDIS_REGISTER_R8D:
|
||||
return registers.regcontext.r8 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R9D:
|
||||
return registers.regcontext.r9 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R10D:
|
||||
return registers.regcontext.r10 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R11D:
|
||||
return registers.regcontext.r11 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R12D:
|
||||
return registers.regcontext.r12 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R13D:
|
||||
return registers.regcontext.r13 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R15D:
|
||||
return registers.regcontext.r15 & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_R8W:
|
||||
return registers.regcontext.r8 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R9W:
|
||||
return registers.regcontext.r9 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R10W:
|
||||
return registers.regcontext.r10 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R11W:
|
||||
return registers.regcontext.r11 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R12W:
|
||||
return registers.regcontext.r12 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R13W:
|
||||
return registers.regcontext.r13 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R15W:
|
||||
return registers.regcontext.r15 & 0xFFFF;
|
||||
case ZYDIS_REGISTER_R8B:
|
||||
return registers.regcontext.r8 & 0xFF;
|
||||
case ZYDIS_REGISTER_R9B:
|
||||
return registers.regcontext.r9 & 0xFF;
|
||||
case ZYDIS_REGISTER_R10B:
|
||||
return registers.regcontext.r10 & 0xFF;
|
||||
case ZYDIS_REGISTER_R11B:
|
||||
return registers.regcontext.r11 & 0xFF;
|
||||
case ZYDIS_REGISTER_R12B:
|
||||
return registers.regcontext.r12 & 0xFF;
|
||||
case ZYDIS_REGISTER_R13B:
|
||||
return registers.regcontext.r13 & 0xFF;
|
||||
case ZYDIS_REGISTER_R15B:
|
||||
return registers.regcontext.r15 & 0xFF;
|
||||
#endif //_WIN64
|
||||
case ZYDIS_REGISTER_EAX:
|
||||
return registers.regcontext.cax & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_ECX:
|
||||
return registers.regcontext.ccx & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EDX:
|
||||
return registers.regcontext.cdx & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EBX:
|
||||
return registers.regcontext.cbx & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_ESP:
|
||||
return registers.regcontext.csp & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EBP:
|
||||
return registers.regcontext.cbp & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_ESI:
|
||||
return registers.regcontext.csi & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_EDI:
|
||||
return registers.regcontext.cdi & 0xFFFFFFFF;
|
||||
case ZYDIS_REGISTER_AX:
|
||||
return registers.regcontext.cax & 0xFFFF;
|
||||
case ZYDIS_REGISTER_CX:
|
||||
return registers.regcontext.ccx & 0xFFFF;
|
||||
case ZYDIS_REGISTER_DX:
|
||||
return registers.regcontext.cdx & 0xFFFF;
|
||||
case ZYDIS_REGISTER_BX:
|
||||
return registers.regcontext.cbx & 0xFFFF;
|
||||
case ZYDIS_REGISTER_SP:
|
||||
return registers.regcontext.csp & 0xFFFF;
|
||||
case ZYDIS_REGISTER_BP:
|
||||
return registers.regcontext.cbp & 0xFFFF;
|
||||
case ZYDIS_REGISTER_SI:
|
||||
return registers.regcontext.csi & 0xFFFF;
|
||||
case ZYDIS_REGISTER_DI:
|
||||
return registers.regcontext.cdi & 0xFFFF;
|
||||
case ZYDIS_REGISTER_AL:
|
||||
return registers.regcontext.cax & 0xFF;
|
||||
case ZYDIS_REGISTER_CL:
|
||||
return registers.regcontext.ccx & 0xFF;
|
||||
case ZYDIS_REGISTER_DL:
|
||||
return registers.regcontext.cdx & 0xFF;
|
||||
case ZYDIS_REGISTER_BL:
|
||||
return registers.regcontext.cbx & 0xFF;
|
||||
case ZYDIS_REGISTER_AH:
|
||||
return (registers.regcontext.cax & 0xFF00) >> 8;
|
||||
case ZYDIS_REGISTER_CH:
|
||||
return (registers.regcontext.ccx & 0xFF00) >> 8;
|
||||
case ZYDIS_REGISTER_DH:
|
||||
return (registers.regcontext.cdx & 0xFF00) >> 8;
|
||||
case ZYDIS_REGISTER_BH:
|
||||
return (registers.regcontext.cbx & 0xFF00) >> 8;
|
||||
default:
|
||||
return static_cast<ULONG_PTR>(0);
|
||||
}
|
||||
};
|
||||
duint MemoryAddress[MAX_MEMORY_OPERANDS];
|
||||
duint MemoryOldContent[MAX_MEMORY_OPERANDS];
|
||||
duint MemoryNewContent[MAX_MEMORY_OPERANDS];
|
||||
bool MemoryIsValid[MAX_MEMORY_OPERANDS];
|
||||
int MemoryOperandsCount;
|
||||
MemoryOperandsCount = traceFile->MemoryAccessCount(selection);
|
||||
if(MemoryOperandsCount > 0)
|
||||
traceFile->MemoryAccessInfo(selection, MemoryAddress, MemoryOldContent, MemoryNewContent, MemoryIsValid);
|
||||
if(zydis.Disassemble(registers.regcontext.cip, opcode, opsize))
|
||||
{
|
||||
int opindex;
|
||||
int memaccessindex;
|
||||
//Jumps
|
||||
if(zydis.IsBranchType(Zydis::BTCondJmp))
|
||||
{
|
||||
if(zydis.IsBranchGoingToExecute(registers.regcontext.eflags, registers.regcontext.ccx))
|
||||
{
|
||||
line = tr("Jump is taken");
|
||||
}
|
||||
else
|
||||
{
|
||||
line = tr("Jump is not taken");
|
||||
}
|
||||
mInfo->setCellContent(infoline, 0, line);
|
||||
infoline++;
|
||||
}
|
||||
//Operands
|
||||
QString registerLine, memoryLine;
|
||||
for(opindex = 0; opindex < zydis.OpCount(); opindex++)
|
||||
{
|
||||
size_t value = zydis.ResolveOpValue(opindex, resolveRegValue);
|
||||
if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
{
|
||||
if(!memoryLine.isEmpty())
|
||||
memoryLine += ", ";
|
||||
const char* memsize = zydis.MemSizeName(zydis[opindex].size / 8);
|
||||
if(memsize != nullptr)
|
||||
{
|
||||
memoryLine += memsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
memoryLine += QString("m%1").arg(zydis[opindex].size / 8);
|
||||
}
|
||||
memoryLine += " ptr ";
|
||||
memoryLine += zydis.RegName(zydis[opindex].mem.segment);
|
||||
memoryLine += ":[";
|
||||
memoryLine += ToPtrString(value);
|
||||
memoryLine += "]";
|
||||
if(zydis[opindex].size == 64 && zydis.getVectorElementType(opindex) == Zydis::VETFloat64)
|
||||
{
|
||||
// Double precision
|
||||
#ifdef _WIN64
|
||||
//TODO: Untested
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
memoryLine += "= ";
|
||||
memoryLine += ToDoubleString(&MemoryOldContent[memaccessindex]);
|
||||
memoryLine += " -> ";
|
||||
memoryLine += ToDoubleString(&MemoryNewContent[memaccessindex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// On 32-bit platform it is saved as 2 memory accesses.
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount - 1; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value && MemoryAddress[memaccessindex + 1] == value + 4)
|
||||
{
|
||||
double dblval;
|
||||
memoryLine += "= ";
|
||||
memcpy(&dblval, &MemoryOldContent[memaccessindex], 4);
|
||||
memcpy(((char*)&dblval) + 4, &MemoryOldContent[memaccessindex + 1], 4);
|
||||
memoryLine += ToDoubleString(&dblval);
|
||||
memoryLine += " -> ";
|
||||
memcpy(&dblval, &MemoryNewContent[memaccessindex], 4);
|
||||
memcpy(((char*)&dblval) + 4, &MemoryNewContent[memaccessindex + 1], 4);
|
||||
memoryLine += ToDoubleString(&dblval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif //_WIN64
|
||||
}
|
||||
else if(zydis[opindex].size == 32 && zydis.getVectorElementType(opindex) == Zydis::VETFloat32)
|
||||
{
|
||||
// Single precision
|
||||
//TODO: Untested
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
memoryLine += "= ";
|
||||
memoryLine += ToFloatString(&MemoryOldContent[memaccessindex]);
|
||||
memoryLine += " -> ";
|
||||
memoryLine += ToFloatString(&MemoryNewContent[memaccessindex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(zydis[opindex].size <= sizeof(void*) * 8)
|
||||
{
|
||||
// Handle the most common case (ptr-sized)
|
||||
duint mask;
|
||||
if(zydis[opindex].size < sizeof(void*) * 8)
|
||||
mask = (1 << zydis[opindex].size) - 1;
|
||||
else
|
||||
mask = ~(duint)0;
|
||||
for(memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
memoryLine += "=";
|
||||
memoryLine += ToHexString(MemoryOldContent[memaccessindex] & mask);
|
||||
memoryLine += " -> ";
|
||||
memoryLine += ToHexString(MemoryNewContent[memaccessindex] & mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_REGISTER)
|
||||
{
|
||||
const auto registerName = zydis[opindex].reg.value;
|
||||
if(!registerLine.isEmpty())
|
||||
registerLine += ", ";
|
||||
registerLine += zydis.RegName(registerName);
|
||||
registerLine += " = ";
|
||||
// Special treatment for FPU registers
|
||||
if(registerName >= ZYDIS_REGISTER_ST0 && registerName <= ZYDIS_REGISTER_ST7)
|
||||
{
|
||||
// x87 FPU
|
||||
registerLine += ToLongDoubleString(®isters.x87FPURegisters[(registers.x87StatusWordFields.TOP + registerName - ZYDIS_REGISTER_ST0) & 7].data);
|
||||
}
|
||||
else if(registerName >= ZYDIS_REGISTER_XMM0 && registerName <= ArchValue(ZYDIS_REGISTER_XMM7, ZYDIS_REGISTER_XMM15))
|
||||
{
|
||||
registerLine += CPUInfoBox::formatSSEOperand(QByteArray((const char*)®isters.regcontext.XmmRegisters[registerName - ZYDIS_REGISTER_XMM0], 16), zydis.getVectorElementType(opindex));
|
||||
}
|
||||
else if(registerName >= ZYDIS_REGISTER_YMM0 && registerName <= ArchValue(ZYDIS_REGISTER_YMM7, ZYDIS_REGISTER_YMM15))
|
||||
{
|
||||
//TODO: Untested
|
||||
registerLine += CPUInfoBox::formatSSEOperand(QByteArray((const char*)®isters.regcontext.YmmRegisters[registerName - ZYDIS_REGISTER_XMM0], 32), zydis.getVectorElementType(opindex));
|
||||
}
|
||||
else
|
||||
{
|
||||
// GPR
|
||||
registerLine += ToPtrString(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!registerLine.isEmpty())
|
||||
{
|
||||
mInfo->setCellContent(infoline, 0, registerLine);
|
||||
infoline++;
|
||||
}
|
||||
if(!memoryLine.isEmpty())
|
||||
{
|
||||
mInfo->setCellContent(infoline, 0, memoryLine);
|
||||
infoline++;
|
||||
}
|
||||
DWORD tid;
|
||||
tid = traceFile->ThreadId(selection);
|
||||
line = QString("ThreadID: %1").arg(ConfigBool("Gui", "PidTidInHex") ? ToHexString(tid) : QString::number(tid));
|
||||
mInfo->setCellContent(3, 0, line);
|
||||
}
|
||||
mInfo->reloadData();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ class CPUWidget;
|
|||
class TraceRegisters;
|
||||
class TraceBrowser;
|
||||
class TraceFileReader;
|
||||
class TraceInfoBox;
|
||||
class StdTable;
|
||||
|
||||
namespace Ui
|
||||
|
@ -32,12 +33,10 @@ protected slots:
|
|||
|
||||
protected:
|
||||
TraceBrowser* mTraceWidget;
|
||||
TraceInfoBox* mInfo;
|
||||
TraceRegisters* mGeneralRegs;
|
||||
StdTable* mInfo;
|
||||
StdTable* mOverview;
|
||||
|
||||
void updateInfobox(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers);
|
||||
|
||||
private:
|
||||
Ui::TraceWidget* ui;
|
||||
};
|
||||
|
|
|
@ -79,6 +79,7 @@ SOURCES += \
|
|||
Src/Gui/CPURegistersView.cpp \
|
||||
Src/Gui/SystemBreakpointScriptDialog.cpp \
|
||||
Src/Imports.cpp \
|
||||
Src/Tracer/TraceInfoBox.cpp \
|
||||
Src/Tracer/TraceRegisters.cpp \
|
||||
Src/Tracer/TraceWidget.cpp \
|
||||
Src/Utils/CommonActions.cpp \
|
||||
|
@ -199,6 +200,7 @@ HEADERS += \
|
|||
Src/BasicView/StdIconTable.h \
|
||||
Src/Gui/CPURegistersView.h \
|
||||
Src/Gui/SystemBreakpointScriptDialog.h \
|
||||
Src/Tracer/TraceInfoBox.h \
|
||||
Src/Tracer/TraceRegisters.h \
|
||||
Src/Tracer/TraceWidget.h \
|
||||
Src/Utils/CommonActions.h \
|
||||
|
|
|
@ -229,7 +229,8 @@ SOURCES += \
|
|||
gui/Src/Gui/CPURegistersView.cpp \
|
||||
gui/Src/Tracer/TraceRegisters.cpp \
|
||||
gui/Src/Tracer/TraceWidget.cpp \
|
||||
gui/Src/Gui/SystemBreakpointScriptDialog.cpp
|
||||
gui/Src/Gui/SystemBreakpointScriptDialog.cpp \
|
||||
gui/Src/Tracer/TraceInfoBox.cpp
|
||||
|
||||
HEADERS += \
|
||||
gui/Src/Exports.h \
|
||||
|
@ -470,7 +471,8 @@ HEADERS += \
|
|||
gui/Src/Gui/CPURegistersView.h \
|
||||
gui/Src/Tracer/TraceRegisters.h \
|
||||
gui/Src/Tracer/TraceWidget.h \
|
||||
gui/Src/Gui/SystemBreakpointScriptDialog.h
|
||||
gui/Src/Gui/SystemBreakpointScriptDialog.h \
|
||||
gui/Src/Tracer/TraceInfoBox.h
|
||||
|
||||
FORMS += \
|
||||
gui/Src/Gui/AppearanceDialog.ui \
|
||||
|
|
Loading…
Reference in New Issue