1
0
Fork 0

graph history;follow children or parent in graph

This commit is contained in:
torusrxxx 2017-08-31 12:34:28 +08:00 committed by Duncan Ogilvie
parent bf43f7eb97
commit 09dd193d9f
11 changed files with 193 additions and 103 deletions

View File

@ -29,8 +29,6 @@ HexDump::HexDump(QWidget* parent)
mNonprintReplace = QChar('.'); //QChar(0x25CA);
mNullReplace = QChar('.'); //QChar(0x2022);
historyClear();
// Slots
connect(Bridge::getBridge(), SIGNAL(updateDump()), this, SLOT(updateDumpSlot()));
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChanged(DBGSTATE)));
@ -161,6 +159,16 @@ void HexDump::printDumpAt(dsint parVA)
printDumpAt(parVA, true);
}
void HexDump::gotoPreviousSlot()
{
printDumpAt(mHistory.historyPrev());
}
void HexDump::gotoNextSlot()
{
printDumpAt(mHistory.historyNext());
}
duint HexDump::rvaToVa(dsint rva)
{
return mMemPage->va(rva);
@ -247,57 +255,6 @@ QString HexDump::makeCopyText()
return std::move(result);
}
void HexDump::addVaToHistory(dsint parVa)
{
//truncate everything right from the current VA
if(mVaHistory.size() && mCurrentVa < mVaHistory.size() - 1) //mCurrentVa is not the last
mVaHistory.erase(mVaHistory.begin() + mCurrentVa + 1, mVaHistory.end());
//do not have 2x the same va in a row
if(!mVaHistory.size() || mVaHistory.last() != parVa)
{
mCurrentVa++;
mVaHistory.push_back(parVa);
}
}
bool HexDump::historyHasPrev()
{
if(!mCurrentVa || !mVaHistory.size()) //we are at the earliest history entry
return false;
return true;
}
bool HexDump::historyHasNext()
{
int size = mVaHistory.size();
if(!size || mCurrentVa >= mVaHistory.size() - 1) //we are at the newest history entry
return false;
return true;
}
void HexDump::historyPrev()
{
if(!historyHasPrev())
return;
mCurrentVa--;
printDumpAt(mVaHistory.at(mCurrentVa));
}
void HexDump::historyNext()
{
if(!historyHasNext())
return;
mCurrentVa++;
printDumpAt(mVaHistory.at(mCurrentVa));
}
void HexDump::historyClear()
{
mCurrentVa = -1;
mVaHistory.clear();
}
void HexDump::setupCopyMenu()
{
// Copy -> Data
@ -536,12 +493,12 @@ void HexDump::mouseReleaseEvent(QMouseEvent* event)
if((event->button() & Qt::BackButton) != 0)
{
wAccept = true;
historyPrev();
printDumpAt(mHistory.historyPrev());
}
else if((event->button() & Qt::ForwardButton) != 0)
{
wAccept = true;
historyNext();
printDumpAt(mHistory.historyNext());
}
if(wAccept == true)
@ -556,7 +513,7 @@ void HexDump::keyPressEvent(QKeyEvent* event)
if(DbgMemFindBaseAddr(rvaToVa(getTableOffsetRva()), nullptr) == DbgMemFindBaseAddr(offsetVa, nullptr))
{
printDumpAt(offsetVa);
addVaToHistory(offsetVa);
mHistory.addVaToHistory(offsetVa);
}
}
else if(event->key() == Qt::Key_Down && event->modifiers() == Qt::ControlModifier)
@ -565,7 +522,7 @@ void HexDump::keyPressEvent(QKeyEvent* event)
if(DbgMemFindBaseAddr(rvaToVa(getTableOffsetRva()), nullptr) == DbgMemFindBaseAddr(offsetVa, nullptr))
{
printDumpAt(offsetVa);
addVaToHistory(offsetVa);
mHistory.addVaToHistory(offsetVa);
}
}
else

View File

@ -4,6 +4,7 @@
#include "AbstractTableView.h"
#include "RichTextPainter.h"
#include "MemoryPage.h"
#include "VaHistory.h"
#include <QTextCodec>
class HexDump : public AbstractTableView
@ -146,15 +147,10 @@ public:
QString makeAddrText(duint va);
QString makeCopyText();
void addVaToHistory(dsint parVa);
bool historyHasPrev();
bool historyHasNext();
void historyPrev();
void historyNext();
void historyClear();
void setupCopyMenu();
VaHistory mHistory;
signals:
void selectionUpdated();
@ -165,6 +161,8 @@ public slots:
void copySelectionSlot();
void copyAddressSlot();
void copyRvaSlot();
void gotoPreviousSlot();
void gotoNextSlot();
private:
enum GuiState_t {NoState, MultiRowsSelectionState};
@ -179,9 +177,6 @@ private:
SelectionData_t mSelection;
GuiState_t mGuiState;
QList<dsint> mVaHistory;
int mCurrentVa;
QChar mNonprintReplace;
QChar mNullReplace;

View File

@ -188,13 +188,13 @@ void CPUDump::setupContextMenu()
return getSelectionStart() != 0;
});
wGotoMenu->addAction(makeShortcutAction(DIcon("bottom.png"), tr("End of Page"), SLOT(gotoEndSlot()), "ActionGotoEnd"));
wGotoMenu->addAction(makeShortcutAction(DIcon("previous.png"), tr("Previous"), SLOT(gotoPrevSlot()), "ActionGotoPrevious"), [this](QMenu*)
wGotoMenu->addAction(makeShortcutAction(DIcon("previous.png"), tr("Previous"), SLOT(gotoPreviousSlot()), "ActionGotoPrevious"), [this](QMenu*)
{
return historyHasPrev();
return mHistory.historyHasPrev();
});
wGotoMenu->addAction(makeShortcutAction(DIcon("next.png"), tr("Next"), SLOT(gotoNextSlot()), "ActionGotoNext"), [this](QMenu*)
{
return historyHasNext();
return mHistory.historyHasNext();
});
wGotoMenu->addAction(makeShortcutAction(DIcon("prevref.png"), tr("Previous Reference"), SLOT(gotoPreviousReferenceSlot()), "ActionGotoPreviousReference"), [](QMenu*)
{
@ -1630,16 +1630,6 @@ void CPUDump::allocMemorySlot()
}
}
void CPUDump::gotoNextSlot()
{
historyNext();
}
void CPUDump::gotoPrevSlot()
{
historyPrev();
}
void CPUDump::setView(ViewEnum_t view)
{
switch(view)

View File

@ -108,8 +108,6 @@ public slots:
void followInDumpNSlot();
void allocMemorySlot();
void gotoNextSlot();
void gotoPrevSlot();
void followInMemoryMapSlot();
private:

View File

@ -153,8 +153,8 @@ void CPUMultiDump::printDumpAtSlot(dsint parVa)
cpuDump = qobject_cast<CPUDump*>(widget(i));
if(cpuDump)
{
cpuDump->historyClear();
cpuDump->addVaToHistory(parVa);
cpuDump->mHistory.historyClear();
cpuDump->mHistory.addVaToHistory(parVa);
cpuDump->printDumpAt(parVa);
}
}
@ -165,7 +165,7 @@ void CPUMultiDump::printDumpAtSlot(dsint parVa)
{
SwitchToDumpWindow();
mCurrentCPUDump->printDumpAt(parVa);
mCurrentCPUDump->addVaToHistory(parVa);
mCurrentCPUDump->mHistory.addVaToHistory(parVa);
}
}
@ -179,7 +179,7 @@ void CPUMultiDump::printDumpAtNSlot(duint parVa, int index)
return;
setCurrentIndex(tabindex);
current->printDumpAt(parVa);
current->addVaToHistory(parVa);
current->mHistory.addVaToHistory(parVa);
}
void CPUMultiDump::selectionGetSlot(SELECTIONDATA* selectionData)

View File

@ -230,13 +230,13 @@ void CPUStack::setupContextMenu()
//Go to Previous
gotoMenu->addAction(makeShortcutAction(DIcon("previous.png"), tr("Go to Previous"), SLOT(gotoPreviousSlot()), "ActionGotoPrevious"), [this](QMenu*)
{
return historyHasPrev();
return mHistory.historyHasPrev();
});
//Go to Next
gotoMenu->addAction(makeShortcutAction(DIcon("next.png"), tr("Go to Next"), SLOT(gotoNextSlot()), "ActionGotoNext"), [this](QMenu*)
{
return historyHasNext();
return mHistory.historyHasNext();
});
mMenuBuilder->addMenu(makeMenu(DIcon("goto.png"), tr("&Go to")), gotoMenu);
@ -540,7 +540,7 @@ void CPUStack::mouseDoubleClickEvent(QMouseEvent* event)
void CPUStack::stackDumpAt(duint addr, duint csp)
{
if(DbgMemIsValidReadPtr(addr))
addVaToHistory(addr);
mHistory.addVaToHistory(addr);
mCsp = csp;
// Get the callstack
@ -659,16 +659,6 @@ void CPUStack::gotoExpressionSlot()
}
}
void CPUStack::gotoPreviousSlot()
{
historyPrev();
}
void CPUStack::gotoNextSlot()
{
historyNext();
}
void CPUStack::selectionGet(SELECTIONDATA* selection)
{
selection->start = rvaToVa(getSelectionStart());

View File

@ -34,8 +34,6 @@ public slots:
void gotoCspSlot();
void gotoCbpSlot();
void gotoExpressionSlot();
void gotoPreviousSlot();
void gotoNextSlot();
void gotoPreviousFrameSlot();
void gotoNextFrameSlot();
void gotoFrameBaseSlot();

View File

@ -26,6 +26,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget* parent)
syncOrigin(false),
forceCenter(false),
layoutType(LayoutType::Medium),
mHistoryLock(false),
mXrefDlg(nullptr)
{
this->status = "Loading...";
@ -633,7 +634,7 @@ void DisassemblerGraphView::mousePressEvent(QMouseEvent* event)
wMenu.exec(event->globalPos()); //execute context menu
}
}
else if(this->isMouseEventInBlock(event))
else if((event->button() == Qt::LeftButton || event->button() == Qt::RightButton) && this->isMouseEventInBlock(event))
{
//Check for click on a token and highlight it
Token token;
@ -695,6 +696,11 @@ void DisassemblerGraphView::mouseMoveEvent(QMouseEvent* event)
void DisassemblerGraphView::mouseReleaseEvent(QMouseEvent* event)
{
if(event->button() == Qt::ForwardButton)
gotoNextSlot();
else if(event->button() == Qt::BackButton)
gotoPreviousSlot();
if(event->button() != Qt::LeftButton)
return;
@ -1448,10 +1454,15 @@ void DisassemblerGraphView::show_cur_instr(bool force)
bool DisassemblerGraphView::navigate(duint addr)
{
//Add address to history
if(!mHistoryLock)
mHistory.addVaToHistory(addr);
//Check to see if address is within current function
for(auto & blockIt : this->blocks)
{
DisassemblerBlock & block = blockIt.second;
if(block.block.entry > addr) //optimize it
continue;
auto row = int(block.block.header_text.lines.size());
for(Instr & instr : block.block.instrs)
{
@ -1648,6 +1659,15 @@ void DisassemblerGraphView::updateGraphSlot()
this->viewport()->update();
}
void DisassemblerGraphView::addReferenceAction(QMenu* menu, duint addr)
{
QAction* action = new QAction(menu);
action->setData(ToPtrString(addr));
action->setText(getSymbolicName(addr));
connect(action, SIGNAL(triggered()), this, SLOT(followActionSlot()));
menu->addAction(action);
}
void DisassemblerGraphView::setupContextMenu()
{
mMenuBuilder = new MenuBuilder(this, [](QMenu*)
@ -1671,6 +1691,52 @@ void DisassemblerGraphView::setupContextMenu()
MenuBuilder* gotoMenu = new MenuBuilder(this);
gotoMenu->addAction(makeShortcutAction(DIcon("geolocation-goto.png"), tr("Expression"), SLOT(gotoExpressionSlot()), "ActionGotoExpression"));
gotoMenu->addAction(makeShortcutAction(DIcon("cbp.png"), tr("Origin"), SLOT(gotoOriginSlot()), "ActionGotoOrigin"));
gotoMenu->addAction(makeShortcutAction(DIcon("previous.png"), tr("Previous"), SLOT(gotoPreviousSlot()), "ActionGotoPrevious"), [this](QMenu*)
{
return mHistory.historyHasPrev();
});
gotoMenu->addAction(makeShortcutAction(DIcon("next.png"), tr("Next"), SLOT(gotoNextSlot()), "ActionGotoNext"), [this](QMenu*)
{
return mHistory.historyHasNext();
});
MenuBuilder* childrenAndParentMenu = new MenuBuilder(this, [this](QMenu * menu)
{
duint cursorpos = get_cursor_pos();
const DisassemblerBlock* currentBlock = nullptr;
const Instr* currentInstruction = nullptr;
for(const auto & i : blocks)
{
if(i.second.block.entry > cursorpos)
continue;
for(const Instr & inst : i.second.block.instrs)
{
if(inst.addr <= cursorpos && inst.addr + inst.opcode.size() > cursorpos)
{
currentBlock = &i.second;
currentInstruction = &inst;
break;
}
}
if(currentInstruction)
break;
}
if(currentInstruction)
{
for(const duint & i : currentBlock->incoming) // This list is incomplete
addReferenceAction(menu, i);
if(!currentBlock->block.terminal)
{
menu->addSeparator();
for(const duint & i : currentBlock->block.exits)
addReferenceAction(menu, i);
}
//to do: follow a constant
return true;
}
return false;
});
gotoMenu->addSeparator();
gotoMenu->addBuilder(childrenAndParentMenu);
mMenuBuilder->addMenu(makeMenu(DIcon("goto.png"), tr("Go to")), gotoMenu);
mMenuBuilder->addAction(makeShortcutAction(DIcon("xrefs.png"), tr("Xrefs..."), SLOT(xrefSlot()), "ActionXrefs"));
mMenuBuilder->addAction(makeShortcutAction(DIcon("snowman.png"), tr("Decompile"), SLOT(decompileSlot()), "ActionGraphDecompile"));
@ -1821,6 +1887,26 @@ void DisassemblerGraphView::gotoOriginSlot()
DbgCmdExec("graph cip, silent");
}
void DisassemblerGraphView::gotoPreviousSlot()
{
if(mHistory.historyHasPrev())
{
mHistoryLock = true;
DbgCmdExecDirect(QString("graph %1, silent").arg(ToPtrString(mHistory.historyPrev())).toUtf8().constData());
mHistoryLock = false;
}
}
void DisassemblerGraphView::gotoNextSlot()
{
if(mHistory.historyHasNext())
{
mHistoryLock = true;
DbgCmdExecDirect(QString("graph %1, silent").arg(ToPtrString(mHistory.historyNext())).toUtf8().constData());
mHistoryLock = false;
}
}
void DisassemblerGraphView::toggleSyncOriginSlot()
{
syncOrigin = !syncOrigin;
@ -1956,3 +2042,13 @@ void DisassemblerGraphView::decompileSlot()
emit displaySnowmanWidget();
DecompileRanges(Bridge::getBridge()->snowmanView, ranges.data(), ranges.size());
}
void DisassemblerGraphView::followActionSlot()
{
QAction* action = qobject_cast<QAction*>(sender());
if(action)
{
QString data = action->data().toString();
DbgCmdExecDirect(QString("graph %1, silent").arg(data).toUtf8().constData());
}
}

View File

@ -18,6 +18,7 @@
#include "RichTextPainter.h"
#include "QBeaEngine.h"
#include "ActionHelpers.h"
#include "VaHistory.h"
class MenuBuilder;
class CachedFontMetrics;
@ -245,6 +246,8 @@ public:
void fontChanged();
void setGraphLayout(LayoutType layout);
VaHistory mHistory;
signals:
void displaySnowmanWidget();
@ -265,7 +268,10 @@ public slots:
void disassembleAtSlot(dsint va, dsint cip);
void gotoExpressionSlot();
void gotoOriginSlot();
void gotoPreviousSlot();
void gotoNextSlot();
void toggleSyncOriginSlot();
void followActionSlot();
void refreshSlot();
void saveImageSlot();
void setCommentSlot();
@ -310,6 +316,7 @@ private:
duint mCip;
bool forceCenter;
bool saveGraph;
bool mHistoryLock; //Don't add a history while going to previous/next
LayoutType layoutType;
QAction* mToggleOverview;
@ -344,6 +351,8 @@ private:
QBeaEngine disasm;
GotoDialog* mGoto;
XrefBrowseDialog* mXrefDlg;
void addReferenceAction(QMenu* menu, duint addr);
};
#endif // DISASSEMBLERGRAPHVIEW_H

View File

@ -0,0 +1,56 @@
#ifndef VAHISTORY_H
#define VAHISTORY_H
#include "Bridge.h"
class VaHistory
{
public:
VaHistory() : mCurrentVa(-1) {}
void addVaToHistory(duint parVa)
{
//truncate everything right from the current VA
if(mVaHistory.size() && mCurrentVa < mVaHistory.size() - 1) //mCurrentVa is not the last
mVaHistory.erase(mVaHistory.begin() + mCurrentVa + 1, mVaHistory.end());
//do not have 2x the same va in a row
if(!mVaHistory.size() || mVaHistory.back() != parVa)
{
mCurrentVa++;
mVaHistory.push_back(parVa);
}
}
bool historyHasPrev()
{
return !(!mCurrentVa || !mVaHistory.size()); //we are at the earliest history entry
}
bool historyHasNext()
{
return !(!mVaHistory.size() || mCurrentVa >= mVaHistory.size() - 1); //we are at the newest history entry
}
duint historyPrev()
{
if(!historyHasPrev())
return 0;
mCurrentVa--;
return mVaHistory.at(mCurrentVa);
}
duint historyNext()
{
if(!historyHasNext())
return 0;
mCurrentVa++;
return mVaHistory.at(mCurrentVa);
}
void historyClear()
{
mCurrentVa = -1;
mVaHistory.clear();
}
private:
std::vector<duint> mVaHistory;
int mCurrentVa;
};
#endif //VAHISTORY_H

View File

@ -295,7 +295,8 @@ HEADERS += \
Src/Gui/MessagesBreakpoints.h \
Src/Gui/AboutDialog.h \
Src/Gui/BreakpointMenu.h \
Src/Gui/ComboBoxDialog.h
Src/Gui/ComboBoxDialog.h \
Src/Utils/VaHistory.h
FORMS += \