mirror of
https://github.com/x64dbg/x64dbg.git
synced 2024-11-26 22:30:22 +00:00
Merge pull request #3405 from torusrxxx/patch000000fb
Use 32-bit trace index to save memory
This commit is contained in:
commit
d8cf398b41
@ -1,6 +1,5 @@
|
||||
#include "TraceBrowser.h"
|
||||
#include "TraceWidget.h"
|
||||
#include "TraceFileReader.h"
|
||||
#include "TraceFileSearch.h"
|
||||
#include "RichTextPainter.h"
|
||||
#include "main.h"
|
||||
@ -52,7 +51,7 @@ TraceBrowser::TraceBrowser(TraceFileReader* traceFile, TraceWidget* parent) : Ab
|
||||
connect(Bridge::getBridge(), SIGNAL(gotoTraceIndex(duint)), this, SLOT(gotoIndexSlot(duint)));
|
||||
|
||||
connect(Config(), SIGNAL(tokenizerConfigUpdated()), this, SLOT(tokenizerConfigUpdatedSlot()));
|
||||
connect(this, SIGNAL(selectionChanged(unsigned long long)), this, SLOT(selectionChangedSlot(unsigned long long)));
|
||||
connect(this, SIGNAL(selectionChanged(TRACEINDEX)), this, SLOT(selectionChangedSlot(TRACEINDEX)));
|
||||
connect(Bridge::getBridge(), SIGNAL(close()), this, SLOT(closeFileSlot()));
|
||||
connect(getTraceFile(), SIGNAL(parseFinished()), this, SLOT(parseFinishedSlot()));
|
||||
}
|
||||
@ -753,7 +752,7 @@ NotDebuggingLabel:
|
||||
}
|
||||
}
|
||||
|
||||
ZydisTokenizer::InstructionToken TraceBrowser::memoryTokens(unsigned long long atIndex)
|
||||
ZydisTokenizer::InstructionToken TraceBrowser::memoryTokens(TRACEINDEX atIndex)
|
||||
{
|
||||
duint MemoryAddress[MAX_MEMORY_OPERANDS];
|
||||
duint MemoryOldContent[MAX_MEMORY_OPERANDS];
|
||||
@ -773,13 +772,12 @@ ZydisTokenizer::InstructionToken TraceBrowser::memoryTokens(unsigned long long a
|
||||
ZydisTokenizer::TokenizeTraceMemory(MemoryAddress[i], MemoryOldContent[i], MemoryNewContent[i], tokens);
|
||||
}
|
||||
|
||||
|
||||
fakeInstruction.tokens.insert(fakeInstruction.tokens.begin(), tokens.begin(), tokens.end());
|
||||
}
|
||||
return fakeInstruction;
|
||||
return fakeInstruction;
|
||||
}
|
||||
|
||||
ZydisTokenizer::InstructionToken TraceBrowser::registersTokens(unsigned long long atIndex)
|
||||
ZydisTokenizer::InstructionToken TraceBrowser::registersTokens(TRACEINDEX atIndex)
|
||||
{
|
||||
ZydisTokenizer::InstructionToken fakeInstruction = ZydisTokenizer::InstructionToken();
|
||||
REGDUMP now = getTraceFile()->Registers(atIndex);
|
||||
@ -859,6 +857,12 @@ void TraceBrowser::setupRightClickContextMenu()
|
||||
|
||||
mMenuBuilder->addMenu(makeMenu(DIcon("copy"), tr("&Copy")), copyMenu);
|
||||
|
||||
mMenuBuilder->addMenu(makeMenu(DIcon("dump"), tr("&Follow in Dump")), [this](QMenu * menu)
|
||||
{
|
||||
mParent->setupFollowMenu(menu);
|
||||
return true;
|
||||
});
|
||||
|
||||
mCommonActions->build(mMenuBuilder, CommonActions::ActionDisasm | CommonActions::ActionBreakpoint | CommonActions::ActionLabel | CommonActions::ActionComment | CommonActions::ActionBookmark);
|
||||
mMenuBuilder->addAction(makeShortcutAction(DIcon("highlight"), tr("&Highlighting mode"), SLOT(enableHighlightingModeSlot()), "ActionHighlightingMode"), mTraceFileNotNull);
|
||||
mMenuBuilder->addAction(makeShortcutAction(DIcon("helpmnemonic"), tr("Help on mnemonic"), SLOT(mnemonicHelpSlot()), "ActionHelpOnMnemonic"), mTraceFileNotNull);
|
||||
@ -900,7 +904,7 @@ void TraceBrowser::setupRightClickContextMenu()
|
||||
duint MemoryNewContent[MAX_MEMORY_OPERANDS];
|
||||
bool MemoryIsValid[MAX_MEMORY_OPERANDS];
|
||||
int MemoryOperandsCount;
|
||||
unsigned long long index;
|
||||
TRACEINDEX index;
|
||||
|
||||
if(!isFileOpened())
|
||||
return false;
|
||||
@ -1164,7 +1168,7 @@ void TraceBrowser::keyPressEvent(QKeyEvent* event)
|
||||
AbstractTableView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void TraceBrowser::selectionChangedSlot(unsigned long long selection)
|
||||
void TraceBrowser::selectionChangedSlot(TRACEINDEX selection)
|
||||
{
|
||||
if(mTraceSyncCpu && isFileOpened())
|
||||
{
|
||||
@ -1360,7 +1364,7 @@ void TraceBrowser::mnemonicHelpSlot()
|
||||
emit displayLogWidget();
|
||||
}
|
||||
|
||||
void TraceBrowser::disasm(unsigned long long index, bool history)
|
||||
void TraceBrowser::disasm(TRACEINDEX index, bool history)
|
||||
{
|
||||
setSingleSelection(index);
|
||||
makeVisible(index);
|
||||
@ -1375,7 +1379,7 @@ void TraceBrowser::disasmByAddress(duint address, bool history)
|
||||
if(!mParent->loadDumpFully())
|
||||
return;
|
||||
auto references = getTraceFile()->getDump()->getReferences(address, address);
|
||||
unsigned long long index;
|
||||
TRACEINDEX index;
|
||||
bool found = false;
|
||||
if(references.empty())
|
||||
{
|
||||
@ -1513,7 +1517,7 @@ void TraceBrowser::pushSelectionInto(bool copyBytes, QTextStream & stream, QText
|
||||
const int memoryLen = getColumnWidth(Memory) / getCharWidth() - 1;
|
||||
if(htmlStream)
|
||||
*htmlStream << QString("<table style=\"border-width:0px;border-color:#000000;font-family:%1;font-size:%2px;\">").arg(font().family()).arg(getRowHeight());
|
||||
for(unsigned long long i = getSelectionStart(); i <= getSelectionEnd(); i++)
|
||||
for(TRACEINDEX i = getSelectionStart(); i <= getSelectionEnd(); i++)
|
||||
{
|
||||
if(i != getSelectionStart())
|
||||
stream << "\r\n";
|
||||
@ -1741,7 +1745,7 @@ void TraceBrowser::copyRvaSlot()
|
||||
if(getTraceFile() == nullptr)
|
||||
return;
|
||||
|
||||
for(unsigned long long i = getSelectionStart(); i <= getSelectionEnd(); i++)
|
||||
for(TRACEINDEX i = getSelectionStart(); i <= getSelectionEnd(); i++)
|
||||
{
|
||||
duint cip = getTraceFile()->Registers(i).regcontext.cip;
|
||||
duint base = DbgFunctions()->ModBaseFromAddr(cip);
|
||||
@ -1766,7 +1770,7 @@ void TraceBrowser::copyFileOffsetSlot()
|
||||
if(getTraceFile() == nullptr)
|
||||
return;
|
||||
|
||||
for(unsigned long long i = getSelectionStart(); i <= getSelectionEnd(); i++)
|
||||
for(TRACEINDEX i = getSelectionStart(); i <= getSelectionEnd(); i++)
|
||||
{
|
||||
duint cip = getTraceFile()->Registers(i).regcontext.cip;
|
||||
cip = DbgFunctions()->VaToFileOffset(cip);
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include "AbstractTableView.h"
|
||||
#include "VaHistory.h"
|
||||
#include "QZydis.h"
|
||||
#include "TraceFileReader.h"
|
||||
|
||||
class TraceFileReader;
|
||||
class TraceWidget;
|
||||
class BreakpointMenu;
|
||||
class CommonActions;
|
||||
@ -59,8 +59,8 @@ private:
|
||||
void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
ZydisTokenizer::InstructionToken memoryTokens(unsigned long long atIndex);
|
||||
ZydisTokenizer::InstructionToken registersTokens(unsigned long long atIndex);
|
||||
ZydisTokenizer::InstructionToken memoryTokens(TRACEINDEX atIndex);
|
||||
ZydisTokenizer::InstructionToken registersTokens(TRACEINDEX atIndex);
|
||||
VaHistory mHistory;
|
||||
MenuBuilder* mMenuBuilder;
|
||||
CommonActions* mCommonActions;
|
||||
@ -146,7 +146,7 @@ private:
|
||||
|
||||
signals:
|
||||
void displayLogWidget();
|
||||
void selectionChanged(unsigned long long selection);
|
||||
void selectionChanged(TRACEINDEX selection);
|
||||
void xrefSignal(duint addr);
|
||||
void closeFile();
|
||||
|
||||
@ -159,7 +159,7 @@ public slots:
|
||||
void closeDeleteSlot();
|
||||
void parseFinishedSlot();
|
||||
void tokenizerConfigUpdatedSlot();
|
||||
void selectionChangedSlot(unsigned long long selection);
|
||||
void selectionChangedSlot(TRACEINDEX selection);
|
||||
|
||||
void gotoSlot();
|
||||
void gotoIndexSlot();
|
||||
@ -192,7 +192,7 @@ public slots:
|
||||
|
||||
private:
|
||||
// Go to by index
|
||||
void disasm(unsigned long long index, bool history = true);
|
||||
void disasm(TRACEINDEX index, bool history = true);
|
||||
// Go to by address, display the Xref dialog if multiple indicies are found
|
||||
void disasmByAddress(duint address, bool history = true);
|
||||
TraceWidget* mParent;
|
||||
|
@ -1,11 +1,9 @@
|
||||
#include "TraceDump.h"
|
||||
#include "TraceWidget.h"
|
||||
#include "TraceFileReader.h"
|
||||
#include "TraceFileDump.h"
|
||||
#include <QMessageBox>
|
||||
#include <QClipboard>
|
||||
#include <QFileDialog>
|
||||
#include <QToolTip>
|
||||
#include "TraceDump.h"
|
||||
#include "TraceWidget.h"
|
||||
#include "Configuration.h"
|
||||
#include "Bridge.h"
|
||||
#include "HexEditDialog.h"
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
TraceFileDump::TraceFileDump()
|
||||
{
|
||||
maxIndex = 0ull;
|
||||
maxIndex = static_cast<TRACEINDEX>(0);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ TraceFileDump::~TraceFileDump()
|
||||
|
||||
void TraceFileDump::clear()
|
||||
{
|
||||
maxIndex = 0ull;
|
||||
maxIndex = static_cast<TRACEINDEX>(0);
|
||||
dump.clear();
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ bool TraceFileDump::isValidReadPtr(duint address) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void TraceFileDump::getBytes(duint addr, duint size, unsigned long long index, void* buffer) const
|
||||
void TraceFileDump::getBytes(duint addr, duint size, TRACEINDEX index, void* buffer) const
|
||||
{
|
||||
if(!isEnabled())
|
||||
return;
|
||||
@ -135,12 +135,12 @@ void TraceFileDump::getBytes(duint addr, duint size, unsigned long long index, v
|
||||
}
|
||||
|
||||
// find references to the memory address
|
||||
std::vector<unsigned long long> TraceFileDump::getReferences(duint startAddr, duint endAddr) const
|
||||
std::vector<TRACEINDEX> TraceFileDump::getReferences(duint startAddr, duint endAddr) const
|
||||
{
|
||||
if(!isEnabled())
|
||||
return {};
|
||||
|
||||
std::vector<unsigned long long> index;
|
||||
std::vector<TRACEINDEX> index;
|
||||
if(endAddr < startAddr)
|
||||
std::swap(endAddr, startAddr);
|
||||
// find references to the memory address
|
||||
@ -154,7 +154,7 @@ std::vector<unsigned long long> TraceFileDump::getReferences(duint startAddr, du
|
||||
return index;
|
||||
// rearrange the array and remove duplicates
|
||||
std::sort(index.begin(), index.end());
|
||||
std::vector<unsigned long long> result;
|
||||
std::vector<TRACEINDEX> result;
|
||||
result.push_back(index[0]);
|
||||
for(size_t i = 1; i < index.size(); i++)
|
||||
{
|
||||
@ -236,12 +236,12 @@ TraceFileDumpMemoryPage::TraceFileDumpMemoryPage(TraceFileDump* dump, QObject* p
|
||||
this->dump = dump;
|
||||
}
|
||||
|
||||
void TraceFileDumpMemoryPage::setSelectedIndex(unsigned long long index)
|
||||
void TraceFileDumpMemoryPage::setSelectedIndex(TRACEINDEX index)
|
||||
{
|
||||
if(dump)
|
||||
selectedIndex = std::min(index, dump->getMaxIndex());
|
||||
else
|
||||
selectedIndex = 0ull;
|
||||
selectedIndex = static_cast<TRACEINDEX>(0);
|
||||
}
|
||||
|
||||
bool TraceFileDumpMemoryPage::isAvailable() const
|
||||
@ -249,7 +249,7 @@ bool TraceFileDumpMemoryPage::isAvailable() const
|
||||
return !!this->dump;
|
||||
}
|
||||
|
||||
unsigned long long TraceFileDumpMemoryPage::getSelectedIndex() const
|
||||
TRACEINDEX TraceFileDumpMemoryPage::getSelectedIndex() const
|
||||
{
|
||||
return selectedIndex;
|
||||
}
|
||||
|
@ -5,13 +5,15 @@
|
||||
#include <QMutex>
|
||||
#include "MemoryPage.h"
|
||||
|
||||
typedef DWORD TRACEINDEX;
|
||||
|
||||
class TraceFileDump
|
||||
{
|
||||
public:
|
||||
struct Key
|
||||
{
|
||||
duint addr;
|
||||
unsigned long long index;
|
||||
TRACEINDEX index;
|
||||
friend bool operator <(const Key & a, const Key & b)
|
||||
{
|
||||
// order is inverted, highest address is less! We want to use lower_bound() to find last memory access index.
|
||||
@ -39,8 +41,8 @@ public:
|
||||
}
|
||||
// Read a byte at "addr" at the moment given in "index"
|
||||
bool isValidReadPtr(duint addr) const;
|
||||
void getBytes(duint addr, duint size, unsigned long long index, void* buffer) const;
|
||||
std::vector<unsigned long long> getReferences(duint startAddr, duint endAddr) const;
|
||||
void getBytes(duint addr, duint size, TRACEINDEX index, void* buffer) const;
|
||||
std::vector<TRACEINDEX> getReferences(duint startAddr, duint endAddr) const;
|
||||
// Insert a memory access record
|
||||
//void addMemAccess(duint addr, DumpRecord record);
|
||||
void addMemAccess(duint addr, const void* oldData, const void* newData, size_t size);
|
||||
@ -48,7 +50,7 @@ public:
|
||||
{
|
||||
maxIndex++;
|
||||
}
|
||||
inline unsigned long long getMaxIndex()
|
||||
inline TRACEINDEX getMaxIndex()
|
||||
{
|
||||
return maxIndex;
|
||||
}
|
||||
@ -58,7 +60,7 @@ public:
|
||||
private:
|
||||
std::map<Key, DumpRecord> dump;
|
||||
// maxIndex is the last index included here. As the debuggee steps there will be new data coming.
|
||||
unsigned long long maxIndex;
|
||||
TRACEINDEX maxIndex;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
@ -69,10 +71,10 @@ public:
|
||||
TraceFileDumpMemoryPage(TraceFileDump* dump, QObject* parent = nullptr);
|
||||
virtual bool read(void* parDest, dsint parRVA, duint parSize) const override;
|
||||
virtual bool write(const void* parDest, dsint parRVA, duint parSize) override;
|
||||
void setSelectedIndex(unsigned long long index);
|
||||
unsigned long long getSelectedIndex() const;
|
||||
void setSelectedIndex(TRACEINDEX index);
|
||||
TRACEINDEX getSelectedIndex() const;
|
||||
bool isAvailable() const;
|
||||
private:
|
||||
TraceFileDump* dump;
|
||||
unsigned long long selectedIndex = 0ull;
|
||||
TRACEINDEX selectedIndex = static_cast<TRACEINDEX>(0);
|
||||
};
|
||||
|
@ -121,7 +121,7 @@ bool TraceFileReader::isError(QString & reason) const
|
||||
//}
|
||||
|
||||
// Return the count of instructions
|
||||
unsigned long long TraceFileReader::Length() const
|
||||
TRACEINDEX TraceFileReader::Length() const
|
||||
{
|
||||
return length;
|
||||
}
|
||||
@ -136,7 +136,7 @@ TraceFileDump* TraceFileReader::getDump()
|
||||
return &dump;
|
||||
}
|
||||
|
||||
QString TraceFileReader::getIndexText(unsigned long long index) const
|
||||
QString TraceFileReader::getIndexText(TRACEINDEX index) const
|
||||
{
|
||||
QString indexString;
|
||||
indexString = QString::number(index, 16).toUpper();
|
||||
@ -171,9 +171,9 @@ QString TraceFileReader::FileName() const
|
||||
}
|
||||
|
||||
// Return the registers context at a given index
|
||||
REGDUMP TraceFileReader::Registers(unsigned long long index)
|
||||
REGDUMP TraceFileReader::Registers(TRACEINDEX index)
|
||||
{
|
||||
unsigned long long base;
|
||||
TRACEINDEX base;
|
||||
TraceFilePage* page = getPage(index, &base);
|
||||
if(page == nullptr)
|
||||
{
|
||||
@ -186,9 +186,9 @@ REGDUMP TraceFileReader::Registers(unsigned long long index)
|
||||
}
|
||||
|
||||
// Return the opcode at a given index. buffer must be 16 bytes long.
|
||||
void TraceFileReader::OpCode(unsigned long long index, unsigned char* buffer, int* opcodeSize)
|
||||
void TraceFileReader::OpCode(TRACEINDEX index, unsigned char* buffer, int* opcodeSize)
|
||||
{
|
||||
unsigned long long base;
|
||||
TRACEINDEX base;
|
||||
TraceFilePage* page = getPage(index, &base);
|
||||
if(page == nullptr)
|
||||
{
|
||||
@ -201,18 +201,18 @@ void TraceFileReader::OpCode(unsigned long long index, unsigned char* buffer, in
|
||||
}
|
||||
|
||||
// Return the disassembled instruction at a given index.
|
||||
const Instruction_t & TraceFileReader::Instruction(unsigned long long index)
|
||||
const Instruction_t & TraceFileReader::Instruction(TRACEINDEX index)
|
||||
{
|
||||
unsigned long long base;
|
||||
TRACEINDEX base;
|
||||
TraceFilePage* page = getPage(index, &base);
|
||||
// The caller must guarantee page is not null, most likely they have already called some other getters.
|
||||
return page->Instruction(index - base, *mDisasm);
|
||||
}
|
||||
|
||||
// Return the thread id at a given index
|
||||
DWORD TraceFileReader::ThreadId(unsigned long long index)
|
||||
DWORD TraceFileReader::ThreadId(TRACEINDEX index)
|
||||
{
|
||||
unsigned long long base;
|
||||
TRACEINDEX base;
|
||||
TraceFilePage* page = getPage(index, &base);
|
||||
if(page == nullptr)
|
||||
return 0;
|
||||
@ -221,9 +221,9 @@ DWORD TraceFileReader::ThreadId(unsigned long long index)
|
||||
}
|
||||
|
||||
// Return the number of recorded memory accesses at a given index
|
||||
int TraceFileReader::MemoryAccessCount(unsigned long long index)
|
||||
int TraceFileReader::MemoryAccessCount(TRACEINDEX index)
|
||||
{
|
||||
unsigned long long base;
|
||||
TRACEINDEX base;
|
||||
TraceFilePage* page = getPage(index, &base);
|
||||
if(page == nullptr)
|
||||
return 0;
|
||||
@ -232,9 +232,9 @@ int TraceFileReader::MemoryAccessCount(unsigned long long index)
|
||||
}
|
||||
|
||||
// Return the memory access info at a given index
|
||||
void TraceFileReader::MemoryAccessInfo(unsigned long long index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid)
|
||||
void TraceFileReader::MemoryAccessInfo(TRACEINDEX index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid)
|
||||
{
|
||||
unsigned long long base;
|
||||
TRACEINDEX base;
|
||||
TraceFilePage* page = getPage(index, &base);
|
||||
if(page == nullptr)
|
||||
return;
|
||||
@ -266,7 +266,7 @@ static size_t getMaxCachedPages()
|
||||
}
|
||||
|
||||
// Used internally to get the page for the given index and read from disk if necessary
|
||||
TraceFilePage* TraceFileReader::getPage(unsigned long long index, unsigned long long* base)
|
||||
TraceFilePage* TraceFileReader::getPage(TRACEINDEX index, TRACEINDEX* base)
|
||||
{
|
||||
// Try to access the most recently used page
|
||||
if(lastAccessedPage)
|
||||
@ -484,8 +484,8 @@ static bool readBlock(QFile & traceFile)
|
||||
void TraceFileParser::run()
|
||||
{
|
||||
TraceFileReader* that = dynamic_cast<TraceFileReader*>(parent());
|
||||
unsigned long long index = 0;
|
||||
unsigned long long lastIndex = 0;
|
||||
TRACEINDEX index = 0;
|
||||
TRACEINDEX lastIndex = 0;
|
||||
if(that == NULL)
|
||||
{
|
||||
return; //Error
|
||||
@ -543,8 +543,8 @@ void TraceFileParser::run()
|
||||
// Remove last page from memory and read from disk again to show updates
|
||||
void TraceFileReader::purgeLastPage()
|
||||
{
|
||||
unsigned long long index = 0;
|
||||
unsigned long long lastIndex = 0;
|
||||
TRACEINDEX index = 0;
|
||||
TRACEINDEX lastIndex = 0;
|
||||
bool isBlockExist = false;
|
||||
const bool previousEmpty = Length() == 0;
|
||||
if(length > 0)
|
||||
@ -601,7 +601,7 @@ void TraceFileReader::purgeLastPage()
|
||||
}
|
||||
|
||||
// Extract memory access information of given index into dump object
|
||||
void TraceFileReader::buildDump(unsigned long long index)
|
||||
void TraceFileReader::buildDump(TRACEINDEX index)
|
||||
{
|
||||
unsigned char opcode[MAX_DISASM_BUFFER];
|
||||
int opcodeSize;
|
||||
@ -707,7 +707,7 @@ void TraceFileReader::buildDump(unsigned long long index)
|
||||
}
|
||||
|
||||
// Build dump index to the given index
|
||||
void TraceFileReader::buildDumpTo(unsigned long long index)
|
||||
void TraceFileReader::buildDumpTo(TRACEINDEX index)
|
||||
{
|
||||
auto start = dump.getMaxIndex(); // Don't re-add existing dump
|
||||
for(auto i = start + 1; i <= index; i++)
|
||||
@ -717,13 +717,13 @@ void TraceFileReader::buildDumpTo(unsigned long long index)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned long long> TraceFileReader::getReferences(duint startAddr, duint endAddr) const
|
||||
std::vector<TRACEINDEX> TraceFileReader::getReferences(duint startAddr, duint endAddr) const
|
||||
{
|
||||
return dump.getReferences(startAddr, endAddr);
|
||||
}
|
||||
|
||||
//TraceFilePage
|
||||
TraceFilePage::TraceFilePage(TraceFileReader* parent, unsigned long long fileOffset, unsigned long long maxLength)
|
||||
TraceFilePage::TraceFilePage(TraceFileReader* parent, unsigned long long fileOffset, TRACEINDEX maxLength)
|
||||
{
|
||||
DWORD lastThreadId = 0;
|
||||
union
|
||||
@ -837,28 +837,28 @@ TraceFilePage::TraceFilePage(TraceFileReader* parent, unsigned long long fileOff
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long long TraceFilePage::Length() const
|
||||
TRACEINDEX TraceFilePage::Length() const
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
const REGDUMP & TraceFilePage::Registers(unsigned long long index) const
|
||||
const REGDUMP & TraceFilePage::Registers(TRACEINDEX index) const
|
||||
{
|
||||
return mRegisters.at(index);
|
||||
}
|
||||
|
||||
void TraceFilePage::OpCode(unsigned long long index, unsigned char* buffer, int* opcodeSize) const
|
||||
void TraceFilePage::OpCode(TRACEINDEX index, unsigned char* buffer, int* opcodeSize) const
|
||||
{
|
||||
*opcodeSize = this->opcodeSize.at(index);
|
||||
memcpy(buffer, opcodes.constData() + opcodeOffset.at(index), *opcodeSize);
|
||||
}
|
||||
|
||||
const Instruction_t & TraceFilePage::Instruction(unsigned long long index, QZydis & mDisasm)
|
||||
const Instruction_t & TraceFilePage::Instruction(TRACEINDEX index, QZydis & mDisasm)
|
||||
{
|
||||
if(instructions.size() == 0)
|
||||
{
|
||||
instructions.reserve(length);
|
||||
for(unsigned long long i = 0; i < length; i++)
|
||||
for(TRACEINDEX i = 0; i < length; i++)
|
||||
{
|
||||
instructions.emplace_back(mDisasm.DisassembleAt((const byte_t*)opcodes.constData() + opcodeOffset.at(i), opcodeSize.at(i), 0, Registers(i).regcontext.cip, false));
|
||||
}
|
||||
@ -866,12 +866,12 @@ const Instruction_t & TraceFilePage::Instruction(unsigned long long index, QZydi
|
||||
return instructions.at(index);
|
||||
}
|
||||
|
||||
DWORD TraceFilePage::ThreadId(unsigned long long index) const
|
||||
DWORD TraceFilePage::ThreadId(TRACEINDEX index) const
|
||||
{
|
||||
return threadId.at(index);
|
||||
}
|
||||
|
||||
int TraceFilePage::MemoryAccessCount(unsigned long long index) const
|
||||
int TraceFilePage::MemoryAccessCount(TRACEINDEX index) const
|
||||
{
|
||||
size_t a = memoryOperandOffset.at(index);
|
||||
if(index == length - 1)
|
||||
@ -880,7 +880,7 @@ int TraceFilePage::MemoryAccessCount(unsigned long long index) const
|
||||
return (int)(memoryOperandOffset.at(index + 1) - a);
|
||||
}
|
||||
|
||||
void TraceFilePage::MemoryAccessInfo(unsigned long long index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid) const
|
||||
void TraceFilePage::MemoryAccessInfo(TRACEINDEX index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid) const
|
||||
{
|
||||
auto count = MemoryAccessCount(index);
|
||||
auto base = memoryOperandOffset.at(index);
|
||||
|
@ -25,20 +25,20 @@ public:
|
||||
bool isError(QString & reason) const;
|
||||
//int Progress() const; // TODO: Trace view should start showing its first instructions as soon as they are loaded
|
||||
|
||||
QString getIndexText(unsigned long long index) const;
|
||||
QString getIndexText(TRACEINDEX index) const;
|
||||
|
||||
unsigned long long Length() const;
|
||||
TRACEINDEX Length() const;
|
||||
uint64_t FileSize() const;
|
||||
|
||||
REGDUMP Registers(unsigned long long index);
|
||||
void OpCode(unsigned long long index, unsigned char* buffer, int* opcodeSize);
|
||||
const Instruction_t & Instruction(unsigned long long index);
|
||||
REGDUMP Registers(TRACEINDEX index);
|
||||
void OpCode(TRACEINDEX index, unsigned char* buffer, int* opcodeSize);
|
||||
const Instruction_t & Instruction(TRACEINDEX index);
|
||||
// Get thread ID
|
||||
DWORD ThreadId(unsigned long long index);
|
||||
DWORD ThreadId(TRACEINDEX index);
|
||||
// Get number of memory accesses
|
||||
int MemoryAccessCount(unsigned long long index);
|
||||
int MemoryAccessCount(TRACEINDEX index);
|
||||
// Get memory access information. Size of these buffers are MAX_MEMORY_OPERANDS.
|
||||
void MemoryAccessInfo(unsigned long long index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid);
|
||||
void MemoryAccessInfo(TRACEINDEX index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid);
|
||||
// Get hash of EXE
|
||||
duint HashValue() const;
|
||||
const QString & ExePath() const;
|
||||
@ -46,8 +46,8 @@ public:
|
||||
|
||||
void purgeLastPage();
|
||||
|
||||
void buildDumpTo(unsigned long long index);
|
||||
std::vector<unsigned long long> getReferences(duint startAddr, duint endAddr) const;
|
||||
void buildDumpTo(TRACEINDEX index);
|
||||
std::vector<TRACEINDEX> getReferences(duint startAddr, duint endAddr) const;
|
||||
TraceFileDump* getDump();
|
||||
|
||||
signals:
|
||||
@ -60,7 +60,7 @@ private slots:
|
||||
void tokenizerUpdatedSlot();
|
||||
|
||||
private:
|
||||
typedef std::pair<unsigned long long, unsigned long long> Range;
|
||||
typedef std::pair<TRACEINDEX, TRACEINDEX> Range;
|
||||
struct RangeCompare //from addrinfo.h
|
||||
{
|
||||
bool operator()(const Range & a, const Range & b) const //a before b?
|
||||
@ -71,7 +71,7 @@ private:
|
||||
|
||||
QFile traceFile;
|
||||
qint64 fileSize = 0;
|
||||
unsigned long long length = 0;
|
||||
TRACEINDEX length = 0;
|
||||
duint hashValue = 0;
|
||||
QString EXEPath;
|
||||
std::vector<std::pair<unsigned long long, Range>> fileIndex; //index;<file offset;length>
|
||||
@ -79,15 +79,15 @@ private:
|
||||
bool error = true;
|
||||
QString errorMessage;
|
||||
TraceFilePage* lastAccessedPage = nullptr;
|
||||
unsigned long long lastAccessedIndexOffset = 0;
|
||||
TRACEINDEX lastAccessedIndexOffset = 0;
|
||||
friend class TraceFileParser;
|
||||
friend class TraceFilePage;
|
||||
|
||||
TraceFileParser* parser = nullptr;
|
||||
std::map<Range, TraceFilePage, RangeCompare> pages;
|
||||
TraceFilePage* getPage(unsigned long long index, unsigned long long* base);
|
||||
TraceFilePage* getPage(TRACEINDEX index, TRACEINDEX* base);
|
||||
TraceFileDump dump;
|
||||
void buildDump(unsigned long long index);
|
||||
void buildDump(TRACEINDEX index);
|
||||
|
||||
QZydis* mDisasm;
|
||||
};
|
||||
|
@ -16,14 +16,14 @@ class TraceFileParser : public QThread
|
||||
class TraceFilePage
|
||||
{
|
||||
public:
|
||||
TraceFilePage(TraceFileReader* parent, unsigned long long fileOffset, unsigned long long maxLength);
|
||||
unsigned long long Length() const;
|
||||
const REGDUMP & Registers(unsigned long long index) const;
|
||||
void OpCode(unsigned long long index, unsigned char* buffer, int* opcodeSize) const;
|
||||
const Instruction_t & Instruction(unsigned long long index, QZydis & mDisasm);
|
||||
DWORD ThreadId(unsigned long long index) const;
|
||||
int MemoryAccessCount(unsigned long long index) const;
|
||||
void MemoryAccessInfo(unsigned long long index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid) const;
|
||||
TraceFilePage(TraceFileReader* parent, unsigned long long fileOffset, TRACEINDEX maxLength);
|
||||
TRACEINDEX Length() const;
|
||||
const REGDUMP & Registers(TRACEINDEX index) const;
|
||||
void OpCode(TRACEINDEX index, unsigned char* buffer, int* opcodeSize) const;
|
||||
const Instruction_t & Instruction(TRACEINDEX index, QZydis & mDisasm);
|
||||
DWORD ThreadId(TRACEINDEX index) const;
|
||||
int MemoryAccessCount(TRACEINDEX index) const;
|
||||
void MemoryAccessInfo(TRACEINDEX index, duint* address, duint* oldMemory, duint* newMemory, bool* isValid) const;
|
||||
|
||||
FILETIME lastAccessed; //system user time
|
||||
|
||||
@ -43,5 +43,5 @@ private:
|
||||
std::vector<duint> oldMemory;
|
||||
std::vector<duint> newMemory;
|
||||
std::vector<DWORD> threadId;
|
||||
unsigned long long length;
|
||||
TRACEINDEX length;
|
||||
};
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "TraceWidget.h"
|
||||
#include "TraceDump.h"
|
||||
#include "TraceBrowser.h"
|
||||
#include "TraceFileReader.h"
|
||||
#include "CPUInfoBox.h"
|
||||
#include "zydis_wrapper.h"
|
||||
|
||||
@ -36,7 +35,7 @@ TraceInfoBox::~TraceInfoBox()
|
||||
|
||||
}
|
||||
|
||||
void TraceInfoBox::update(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers)
|
||||
void TraceInfoBox::update(TRACEINDEX selection, TraceFileReader* traceFile, const REGDUMP & registers)
|
||||
{
|
||||
duint infoline = 0;
|
||||
Zydis zydis;
|
||||
@ -234,111 +233,12 @@ int TraceInfoBox::getHeight()
|
||||
return ((getRowHeight() + 1) * 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TraceInfoBox::addFollowMenuItem Add a follow action to the menu
|
||||
* @param menu The menu to which the follow action adds
|
||||
* @param name The user-friendly name of the action
|
||||
* @param value The VA of the address
|
||||
*/
|
||||
void TraceInfoBox::addFollowMenuItem(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(followActionSlot()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TraceInfoBox::setupFollowMenu Set up a follow menu.
|
||||
* @param menu The menu to create
|
||||
* @param va The selected VA
|
||||
*/
|
||||
void TraceInfoBox::setupFollowMenu(QMenu* menu, duint va)
|
||||
{
|
||||
TraceFileReader* traceFile = mParent->getTraceFile();
|
||||
const TraceFileDump* traceDump = traceFile->getDump();
|
||||
if(!traceDump->isEnabled())
|
||||
return;
|
||||
//most basic follow action
|
||||
addFollowMenuItem(menu, tr("&Selected Address"), va);
|
||||
|
||||
//add follow actions
|
||||
duint selection = mParent->getTraceBrowser()->getInitialSelection();
|
||||
Zydis zydis;
|
||||
unsigned char opcode[16];
|
||||
int opsize;
|
||||
traceFile->OpCode(selection, opcode, &opsize);
|
||||
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);
|
||||
REGDUMP registers = traceFile->Registers(selection);
|
||||
if(zydis.Disassemble(mCurAddr, opcode, opsize))
|
||||
{
|
||||
for(uint8_t opindex = 0; opindex < zydis.OpCount(); opindex++)
|
||||
{
|
||||
size_t value = zydis.ResolveOpValue(opindex, [®isters](ZydisRegister reg)
|
||||
{
|
||||
return resolveZydisRegister(registers, reg);
|
||||
});
|
||||
|
||||
if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
{
|
||||
if(zydis[opindex].size == sizeof(void*) * 8)
|
||||
{
|
||||
if(traceDump->isValidReadPtr(value))
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Address: ") + QString::fromStdString(zydis.OperandText(opindex)), value);
|
||||
}
|
||||
for(uint8_t memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
if(traceDump->isValidReadPtr(MemoryOldContent[memaccessindex]))
|
||||
{
|
||||
if(MemoryOldContent[memaccessindex] != MemoryNewContent[memaccessindex])
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Old value: ") + ToPtrString(MemoryOldContent[memaccessindex]), MemoryOldContent[memaccessindex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Value: ") + ToPtrString(MemoryOldContent[memaccessindex]), MemoryOldContent[memaccessindex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(traceDump->isValidReadPtr(MemoryNewContent[memaccessindex]))
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&New value: ") + ToPtrString(MemoryNewContent[memaccessindex]), MemoryNewContent[memaccessindex]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
{
|
||||
if(traceDump->isValidReadPtr(value))
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Constant: ") + QString::fromStdString(zydis.OperandText(opindex)), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TraceInfoBox::contextMenuSlot(QPoint pos)
|
||||
{
|
||||
QMenu menu(this); //create context menu
|
||||
QMenu followMenu(tr("&Follow in Dump"), this);
|
||||
followMenu.setIcon(DIcon("dump"));
|
||||
setupFollowMenu(&followMenu, mCurAddr);
|
||||
mParent->setupFollowMenu(&followMenu);
|
||||
menu.addMenu(&followMenu);
|
||||
QMenu copyMenu(tr("&Copy"), this);
|
||||
setupCopyMenu(©Menu);
|
||||
@ -346,21 +246,6 @@ void TraceInfoBox::contextMenuSlot(QPoint pos)
|
||||
menu.exec(mapToGlobal(pos)); //execute context menu
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TraceInfoBox::followActionSlot Called when follow action is clicked
|
||||
*/
|
||||
void TraceInfoBox::followActionSlot()
|
||||
{
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
duint data;
|
||||
#ifdef _WIN64
|
||||
data = action->objectName().toULongLong(nullptr, 16);
|
||||
#else
|
||||
data = action->objectName().toULong(nullptr, 16);
|
||||
#endif //_WIN64
|
||||
mParent->getTraceDump()->printDumpAt(data, true, true, true);
|
||||
}
|
||||
|
||||
void TraceInfoBox::setupShortcuts()
|
||||
{
|
||||
mCopyLineAction->setShortcut(ConfigShortcut("ActionCopyLine"));
|
||||
|
@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "StdTable.h"
|
||||
#include "TraceFileReader.h"
|
||||
|
||||
class TraceWidget;
|
||||
class TraceFileReader;
|
||||
|
||||
class TraceInfoBox : public StdTable
|
||||
{
|
||||
@ -11,16 +11,13 @@ class TraceInfoBox : public StdTable
|
||||
public:
|
||||
TraceInfoBox(TraceWidget* parent);
|
||||
int getHeight();
|
||||
void setupFollowMenu(QMenu* menu, duint va);
|
||||
void addFollowMenuItem(QMenu* menu, QString name, duint value);
|
||||
~TraceInfoBox();
|
||||
|
||||
void update(unsigned long long selection, TraceFileReader* traceFile, const REGDUMP & registers);
|
||||
void update(TRACEINDEX selection, TraceFileReader* traceFile, const REGDUMP & registers);
|
||||
void clear();
|
||||
|
||||
public slots:
|
||||
void contextMenuSlot(QPoint pos);
|
||||
void followActionSlot();
|
||||
|
||||
private:
|
||||
void setupContextMenu();
|
||||
|
@ -1,18 +1,24 @@
|
||||
#include <QMouseEvent>
|
||||
#include "TraceRegisters.h"
|
||||
#include "TraceWidget.h"
|
||||
#include "TraceDump.h"
|
||||
#include "Configuration.h"
|
||||
#include "EditFloatRegister.h"
|
||||
#include "StringUtil.h"
|
||||
#include "MiscUtil.h"
|
||||
|
||||
TraceRegisters::TraceRegisters(QWidget* parent) : RegistersView(parent)
|
||||
TraceRegisters::TraceRegisters(TraceWidget* parent) : RegistersView(parent)
|
||||
{
|
||||
mParent = parent;
|
||||
wCM_CopySIMDRegister = setupAction(DIcon("copy"), tr("Copy floating point value"));
|
||||
connect(wCM_CopySIMDRegister, SIGNAL(triggered()), this, SLOT(onCopySIMDRegister()));
|
||||
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayCustomContextMenuSlot(QPoint)));
|
||||
|
||||
wCM_SetCurrentRegister = setupAction(tr("Set as current value"));
|
||||
connect(wCM_SetCurrentRegister, SIGNAL(triggered()), this, SLOT(onSetCurrentRegister()));
|
||||
|
||||
wCM_FollowInDump = new QAction(DIcon("dump"), tr("Follow in Dump"), this);
|
||||
connect(wCM_FollowInDump, SIGNAL(triggered()), this, SLOT(onFollowInDump()));
|
||||
}
|
||||
|
||||
void TraceRegisters::setRegisters(REGDUMP* registers)
|
||||
@ -35,6 +41,10 @@ void TraceRegisters::displayCustomContextMenuSlot(QPoint pos)
|
||||
|
||||
if(mSelected != UNKNOWN)
|
||||
{
|
||||
if(mCANSTOREADDRESS.contains(mSelected))
|
||||
{
|
||||
menu.addAction(wCM_FollowInDump);
|
||||
}
|
||||
menu.addAction(wCM_CopyToClipboard);
|
||||
if(mFPUx87_80BITSDISPLAY.contains(mSelected))
|
||||
{
|
||||
@ -163,3 +173,13 @@ void TraceRegisters::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
onCopySIMDRegister();
|
||||
// double clicked on GPR: nothing to do (copy?)
|
||||
}
|
||||
|
||||
void TraceRegisters::onFollowInDump()
|
||||
{
|
||||
// First check if the dump is loaded
|
||||
if(!mParent->getTraceFile()->getDump()->isEnabled())
|
||||
if(!mParent->loadDump()) // Try to load the dump
|
||||
return;
|
||||
duint value = *((const duint*)registerValue(&mRegDumpStruct, mSelected));
|
||||
mParent->getTraceDump()->printDumpAt(value, true, true, true);
|
||||
}
|
||||
|
@ -2,11 +2,13 @@
|
||||
|
||||
#include "RegistersView.h"
|
||||
|
||||
class TraceWidget;
|
||||
|
||||
class TraceRegisters : public RegistersView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TraceRegisters(QWidget* parent = nullptr);
|
||||
TraceRegisters(TraceWidget* parent = nullptr);
|
||||
|
||||
void setRegisters(REGDUMP* registers);
|
||||
void setActive(bool isActive);
|
||||
@ -15,11 +17,14 @@ public slots:
|
||||
virtual void displayCustomContextMenuSlot(QPoint pos);
|
||||
void onCopySIMDRegister();
|
||||
void onSetCurrentRegister();
|
||||
void onFollowInDump();
|
||||
|
||||
protected:
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
|
||||
private:
|
||||
TraceWidget* mParent;
|
||||
QAction* wCM_CopySIMDRegister;
|
||||
QAction* wCM_SetCurrentRegister;
|
||||
QAction* wCM_FollowInDump;
|
||||
};
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include "TraceWidget.h"
|
||||
#include "TraceStack.h"
|
||||
#include "TraceDump.h"
|
||||
#include "TraceFileReader.h"
|
||||
#include "TraceFileDump.h"
|
||||
#include "TraceBrowser.h"
|
||||
#include "CPUDump.h"
|
||||
#include <QClipboard>
|
||||
|
@ -60,7 +60,7 @@ TraceWidget::TraceWidget(Architecture* architecture, const QString & fileName, Q
|
||||
QPushButton* button_changeview = new QPushButton("", this);
|
||||
button_changeview->setStyleSheet("Text-align:left;padding: 4px;padding-left: 10px;");
|
||||
connect(button_changeview, SIGNAL(clicked()), mGeneralRegs, SLOT(onChangeFPUViewAction()));
|
||||
connect(mTraceBrowser, SIGNAL(selectionChanged(unsigned long long)), this, SLOT(traceSelectionChanged(unsigned long long)));
|
||||
connect(mTraceBrowser, SIGNAL(selectionChanged(TRACEINDEX)), this, SLOT(traceSelectionChanged(TRACEINDEX)));
|
||||
connect(mTraceBrowser, SIGNAL(displayLogWidget()), this, SLOT(displayLogWidgetSlot()));
|
||||
connect(mTraceFile, SIGNAL(parseFinished()), this, SLOT(parseFinishedSlot()));
|
||||
connect(mTraceBrowser, SIGNAL(closeFile()), this, SLOT(closeFileSlot()));
|
||||
@ -116,7 +116,7 @@ TraceWidget::~TraceWidget()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TraceWidget::traceSelectionChanged(unsigned long long selection)
|
||||
void TraceWidget::traceSelectionChanged(TRACEINDEX selection)
|
||||
{
|
||||
REGDUMP registers;
|
||||
if(mTraceFile != nullptr)
|
||||
@ -253,7 +253,7 @@ bool TraceWidget::loadDumpFully()
|
||||
return true;
|
||||
}
|
||||
|
||||
void TraceWidget::setupDumpInitialAddresses(unsigned long long selection)
|
||||
void TraceWidget::setupDumpInitialAddresses(TRACEINDEX selection)
|
||||
{
|
||||
// Setting the initial address of dump view
|
||||
duint initialAddress;
|
||||
@ -277,3 +277,123 @@ void TraceWidget::setupDumpInitialAddresses(unsigned long long selection)
|
||||
// Setting the initial address of stack view
|
||||
mStack->printDumpAt(mTraceFile->Registers(selection).regcontext.csp, false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TraceWidget::addFollowMenuItem Add a follow action to the menu
|
||||
* @param menu The menu to which the follow action adds
|
||||
* @param name The user-friendly name of the action
|
||||
* @param value The VA of the address
|
||||
*/
|
||||
void TraceWidget::addFollowMenuItem(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(followActionSlot()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TraceWidget::setupFollowMenu Set up a follow menu.
|
||||
* @param menu The menu to create
|
||||
* @param va The selected VA
|
||||
*/
|
||||
void TraceWidget::setupFollowMenu(QMenu* menu)
|
||||
{
|
||||
const TraceFileDump* traceDump = mTraceFile->getDump();
|
||||
if(!traceDump->isEnabled())
|
||||
{
|
||||
QAction* newAction = new QAction(tr("Load dump"), menu);
|
||||
connect(newAction, SIGNAL(triggered()), this, SLOT(loadDump()));
|
||||
menu->addAction(newAction);
|
||||
return;
|
||||
}
|
||||
|
||||
//add follow actions
|
||||
TRACEINDEX selection = getTraceBrowser()->getInitialSelection();
|
||||
REGDUMP registers = mTraceFile->Registers(selection);
|
||||
duint va = registers.regcontext.cip;
|
||||
Zydis zydis;
|
||||
unsigned char opcode[16];
|
||||
int opsize;
|
||||
mTraceFile->OpCode(selection, opcode, &opsize);
|
||||
duint MemoryAddress[MAX_MEMORY_OPERANDS];
|
||||
duint MemoryOldContent[MAX_MEMORY_OPERANDS];
|
||||
duint MemoryNewContent[MAX_MEMORY_OPERANDS];
|
||||
bool MemoryIsValid[MAX_MEMORY_OPERANDS];
|
||||
int MemoryOperandsCount;
|
||||
MemoryOperandsCount = mTraceFile->MemoryAccessCount(selection);
|
||||
if(MemoryOperandsCount > 0)
|
||||
mTraceFile->MemoryAccessInfo(selection, MemoryAddress, MemoryOldContent, MemoryNewContent, MemoryIsValid);
|
||||
|
||||
//most basic follow action
|
||||
addFollowMenuItem(menu, tr("&Selected Address"), va);
|
||||
if(zydis.Disassemble(va, opcode, opsize))
|
||||
{
|
||||
for(uint8_t opindex = 0; opindex < zydis.OpCount(); opindex++)
|
||||
{
|
||||
size_t value = zydis.ResolveOpValue(opindex, [®isters](ZydisRegister reg)
|
||||
{
|
||||
return resolveZydisRegister(registers, reg);
|
||||
});
|
||||
|
||||
if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
{
|
||||
if(zydis[opindex].size == sizeof(void*) * 8)
|
||||
{
|
||||
if(traceDump->isValidReadPtr(value))
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Address: ") + QString::fromStdString(zydis.OperandText(opindex)), value);
|
||||
}
|
||||
for(uint8_t memaccessindex = 0; memaccessindex < MemoryOperandsCount; memaccessindex++)
|
||||
{
|
||||
if(MemoryAddress[memaccessindex] == value)
|
||||
{
|
||||
if(traceDump->isValidReadPtr(MemoryOldContent[memaccessindex]))
|
||||
{
|
||||
if(MemoryOldContent[memaccessindex] != MemoryNewContent[memaccessindex])
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Old value: ") + ToPtrString(MemoryOldContent[memaccessindex]), MemoryOldContent[memaccessindex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Value: ") + ToPtrString(MemoryOldContent[memaccessindex]), MemoryOldContent[memaccessindex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(traceDump->isValidReadPtr(MemoryNewContent[memaccessindex]))
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&New value: ") + ToPtrString(MemoryNewContent[memaccessindex]), MemoryNewContent[memaccessindex]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(zydis[opindex].type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
{
|
||||
if(traceDump->isValidReadPtr(value))
|
||||
{
|
||||
addFollowMenuItem(menu, tr("&Constant: ") + QString::fromStdString(zydis.OperandText(opindex)), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TraceWidget::followActionSlot Called when follow action is clicked
|
||||
*/
|
||||
void TraceWidget::followActionSlot()
|
||||
{
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
duint data;
|
||||
#ifdef _WIN64
|
||||
data = action->objectName().toULongLong(nullptr, 16);
|
||||
#else
|
||||
data = action->objectName().toULong(nullptr, 16);
|
||||
#endif //_WIN64
|
||||
mDump->printDumpAt(data, true, true, true);
|
||||
}
|
||||
|
@ -2,18 +2,17 @@
|
||||
|
||||
#include <QWidget>
|
||||
#include "Bridge.h"
|
||||
#include "TraceFileReader.h"
|
||||
|
||||
class QVBoxLayout;
|
||||
class QPushButton;
|
||||
class CPUWidget;
|
||||
class TraceRegisters;
|
||||
class TraceBrowser;
|
||||
class TraceFileReader;
|
||||
class TraceFileDumpMemoryPage;
|
||||
class TraceInfoBox;
|
||||
class TraceDump;
|
||||
class TraceStack;
|
||||
class TraceFileReader;
|
||||
class TraceXrefBrowseDialog;
|
||||
|
||||
namespace Ui
|
||||
@ -47,6 +46,7 @@ public:
|
||||
};
|
||||
// Enable trace dump and load it fully before searching. Return false if the user cancels.
|
||||
bool loadDumpFully();
|
||||
void setupFollowMenu(QMenu* menu);
|
||||
public slots:
|
||||
// Enable trace dump in order to use these features. Return false if the user cancels.
|
||||
bool loadDump();
|
||||
@ -57,10 +57,11 @@ signals:
|
||||
|
||||
protected slots:
|
||||
void displayLogWidgetSlot();
|
||||
void traceSelectionChanged(unsigned long long selection);
|
||||
void traceSelectionChanged(TRACEINDEX selection);
|
||||
void parseFinishedSlot();
|
||||
void closeFileSlot();
|
||||
void xrefSlot(duint addr);
|
||||
void followActionSlot();
|
||||
|
||||
protected:
|
||||
TraceFileReader* mTraceFile;
|
||||
@ -77,5 +78,6 @@ protected:
|
||||
|
||||
private:
|
||||
Ui::TraceWidget* ui;
|
||||
void setupDumpInitialAddresses(unsigned long long selection);
|
||||
void setupDumpInitialAddresses(TRACEINDEX selection);
|
||||
void addFollowMenuItem(QMenu* menu, QString name, duint value);
|
||||
};
|
||||
|
@ -55,7 +55,7 @@ void TraceXrefBrowseDialog::setup(duint index, duint address, TraceFileReader* t
|
||||
}
|
||||
|
||||
setWindowTitle(QString(tr("xrefs at <%1>")).arg(GetFunctionSymbol(address)));
|
||||
for(duint i = 0; i < mXrefInfo.size(); i++)
|
||||
for(size_t i = 0; i < mXrefInfo.size(); i++)
|
||||
{
|
||||
Zydis zydis;
|
||||
QString disasm;
|
||||
|
@ -4,15 +4,13 @@
|
||||
#include "ActionHelpers.h"
|
||||
#include <QDialog>
|
||||
#include <QListWidgetItem>
|
||||
#include "TraceFileReader.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class XrefBrowseDialog;
|
||||
}
|
||||
|
||||
class TraceFileReader;
|
||||
class TraceFileDump;
|
||||
|
||||
class TraceXrefBrowseDialog : public QDialog, public ActionHelper<TraceXrefBrowseDialog>
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -43,7 +41,7 @@ private:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long long index;
|
||||
TRACEINDEX index;
|
||||
duint addr;
|
||||
} TRACE_XREF_RECORD;
|
||||
std::vector<TRACE_XREF_RECORD> mXrefInfo;
|
||||
|
Loading…
Reference in New Issue
Block a user