1
0
Fork 0

Replace BreakpointMenu with CommonActions, which now handles more commands

This commit is contained in:
torusrxxx 2020-10-19 12:11:09 +08:00 committed by Duncan Ogilvie
parent 7b5eb42b40
commit 79af7e656d
16 changed files with 541 additions and 451 deletions

View File

@ -1,220 +0,0 @@
#include "BreakpointMenu.h"
#include "MenuBuilder.h"
#include <QAction>
#include <QMessageBox>
#include "StringUtil.h"
#include "MiscUtil.h"
#include "Breakpoints.h"
BreakpointMenu::BreakpointMenu(QWidget* parent, ActionHelperFuncs funcs, GetSelectionFunc getSelection)
: QObject(parent), ActionHelperProxy(funcs), mGetSelection(getSelection)
{
}
void BreakpointMenu::build(MenuBuilder* builder)
{
QAction* toggleBreakpointAction = makeShortcutAction(DIcon("breakpoint_toggle.png"), tr("Toggle"), std::bind(&BreakpointMenu::toggleInt3BPActionSlot, this), "ActionToggleBreakpoint");
QAction* editSoftwareBreakpointAction = makeShortcutAction(DIcon("breakpoint_edit_alt.png"), tr("Edit"), std::bind(&BreakpointMenu::editSoftBpActionSlot, this), "ActionEditBreakpoint");
QAction* setHwBreakpointAction = makeShortcutAction(DIcon("breakpoint_execute.png"), tr("Set Hardware on Execution"), std::bind(&BreakpointMenu::toggleHwBpActionSlot, this), "ActionSetHwBpE");
QAction* removeHwBreakpointAction = makeShortcutAction(DIcon("breakpoint_remove.png"), tr("Remove Hardware"), std::bind(&BreakpointMenu::toggleHwBpActionSlot, this), "ActionRemoveHwBp");
QMenu* replaceSlotMenu = makeMenu(DIcon("breakpoint_execute.png"), tr("Set Hardware on Execution"));
// Replacement slot menu are only used when the breakpoints are full, so using "Unknown" as the placeholder. Might want to change this in case we display the menu when there are still free slots.
QAction* replaceSlot0Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot1.png"), tr("Replace Slot 0 (Unknown)"), std::bind(&BreakpointMenu::setHwBpOnSlot0ActionSlot, this));
QAction* replaceSlot1Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot2.png"), tr("Replace Slot 1 (Unknown)"), std::bind(&BreakpointMenu::setHwBpOnSlot1ActionSlot, this));
QAction* replaceSlot2Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot3.png"), tr("Replace Slot 2 (Unknown)"), std::bind(&BreakpointMenu::setHwBpOnSlot2ActionSlot, this));
QAction* replaceSlot3Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot4.png"), tr("Replace Slot 3 (Unknown)"), std::bind(&BreakpointMenu::setHwBpOnSlot3ActionSlot, this));
builder->addMenu(makeMenu(DIcon("breakpoint.png"), tr("Breakpoint")), [ = ](QMenu * menu)
{
auto selection = mGetSelection();
if(selection == 0)
return false;
BPXTYPE bpType = DbgGetBpxTypeAt(selection);
if((bpType & bp_normal) == bp_normal || (bpType & bp_hardware) == bp_hardware)
editSoftwareBreakpointAction->setText(tr("Edit"));
else
editSoftwareBreakpointAction->setText(tr("Set Conditional Breakpoint"));
menu->addAction(editSoftwareBreakpointAction);
menu->addAction(toggleBreakpointAction);
if((bpType & bp_hardware) == bp_hardware)
{
menu->addAction(removeHwBreakpointAction);
}
else
{
BPMAP bpList;
DbgGetBpList(bp_hardware, &bpList);
//get enabled hwbp count
int enabledCount = bpList.count;
for(int i = 0; i < bpList.count; i++)
if(!bpList.bp[i].enabled)
enabledCount--;
if(enabledCount < 4)
{
menu->addAction(setHwBreakpointAction);
}
else
{
for(int i = 0; i < bpList.count; i++)
{
if(bpList.bp[i].enabled)
{
switch(bpList.bp[i].slot)
{
case 0:
replaceSlot0Action->setText(tr("Replace Slot %1 (0x%2)").arg(1).arg(ToPtrString(bpList.bp[i].addr)));
break;
case 1:
replaceSlot1Action->setText(tr("Replace Slot %1 (0x%2)").arg(2).arg(ToPtrString(bpList.bp[i].addr)));
break;
case 2:
replaceSlot2Action->setText(tr("Replace Slot %1 (0x%2)").arg(3).arg(ToPtrString(bpList.bp[i].addr)));
break;
case 3:
replaceSlot3Action->setText(tr("Replace Slot %1 (0x%2)").arg(4).arg(ToPtrString(bpList.bp[i].addr)));
break;
default:
break;
}
}
}
menu->addMenu(replaceSlotMenu);
}
if(bpList.count)
BridgeFree(bpList.bp);
}
return true;
});
}
void BreakpointMenu::toggleInt3BPActionSlot()
{
if(!DbgIsDebugging())
return;
duint wVA = mGetSelection();
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
QString wCmd;
if((wBpType & bp_normal) == bp_normal)
{
wCmd = "bc " + ToPtrString(wVA);
}
else
{
if(DbgFunctions()->IsDepEnabled() && !DbgFunctions()->MemIsCodePage(wVA, false))
{
QMessageBox msgyn(QMessageBox::Warning, tr("Current address is not executable"),
tr("Setting software breakpoint here may result in crash. Do you really want to continue?"), QMessageBox::Yes | QMessageBox::No, (QWidget*)parent());
msgyn.setWindowIcon(DIcon("compile-warning.png"));
msgyn.setParent((QWidget*)parent(), Qt::Dialog);
msgyn.setWindowFlags(msgyn.windowFlags() & (~Qt::WindowContextHelpButtonHint));
if(msgyn.exec() == QMessageBox::No)
return;
}
wCmd = "bp " + ToPtrString(wVA);
}
DbgCmdExec(wCmd);
//emit Disassembly::repainted();
}
void BreakpointMenu::editSoftBpActionSlot()
{
auto selection = mGetSelection();
if(selection == 0)
return;
BPXTYPE bpType = DbgGetBpxTypeAt(selection);
if((bpType & bp_hardware) == bp_hardware)
Breakpoints::editBP(bp_hardware, ToHexString(selection), dynamic_cast<QWidget*>(parent()));
else if((bpType & bp_normal) == bp_normal)
Breakpoints::editBP(bp_normal, ToHexString(selection), dynamic_cast<QWidget*>(parent()));
else
{
DbgCmdExecDirect(QString("bp %1").arg(ToHexString(selection))); //Blocking call
if(!Breakpoints::editBP(bp_normal, ToHexString(selection), dynamic_cast<QWidget*>(parent())))
Breakpoints::removeBP(bp_normal, selection);
}
}
void BreakpointMenu::toggleHwBpActionSlot()
{
duint wVA = mGetSelection();
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
QString wCmd;
if((wBpType & bp_hardware) == bp_hardware)
{
wCmd = "bphwc " + ToPtrString(wVA);
}
else
{
wCmd = "bphws " + ToPtrString(wVA);
}
DbgCmdExec(wCmd);
}
void BreakpointMenu::setHwBpOnSlot0ActionSlot()
{
setHwBpAt(mGetSelection(), 0);
}
void BreakpointMenu::setHwBpOnSlot1ActionSlot()
{
setHwBpAt(mGetSelection(), 1);
}
void BreakpointMenu::setHwBpOnSlot2ActionSlot()
{
setHwBpAt(mGetSelection(), 2);
}
void BreakpointMenu::setHwBpOnSlot3ActionSlot()
{
setHwBpAt(mGetSelection(), 3);
}
void BreakpointMenu::setHwBpAt(duint va, int slot)
{
int wI = 0;
int wSlotIndex = -1;
BPMAP wBPList;
QString wCmd = "";
DbgGetBpList(bp_hardware, &wBPList);
// Find index of slot slot in the list
for(wI = 0; wI < wBPList.count; wI++)
{
if(wBPList.bp[wI].slot == (unsigned short)slot)
{
wSlotIndex = wI;
break;
}
}
if(wSlotIndex < 0) // Slot not used
{
wCmd = "bphws " + ToPtrString(va);
DbgCmdExec(wCmd);
}
else // Slot used
{
wCmd = "bphwc " + ToPtrString((duint)(wBPList.bp[wSlotIndex].addr));
DbgCmdExec(wCmd);
Sleep(200);
wCmd = "bphws " + ToPtrString(va);
DbgCmdExec(wCmd);
}
if(wBPList.count)
BridgeFree(wBPList.bp);
}

View File

@ -1,29 +0,0 @@
#pragma once
#include <QObject>
#include <functional>
#include "ActionHelpers.h"
#include "Imports.h"
class BreakpointMenu : public QObject, public ActionHelperProxy
{
Q_OBJECT
public:
using GetSelectionFunc = std::function<duint()>;
explicit BreakpointMenu(QWidget* parent, ActionHelperFuncs funcs, GetSelectionFunc getSelection);
void build(MenuBuilder* builder);
public slots:
void toggleInt3BPActionSlot();
void editSoftBpActionSlot();
void toggleHwBpActionSlot();
void setHwBpOnSlot0ActionSlot();
void setHwBpOnSlot1ActionSlot();
void setHwBpOnSlot2ActionSlot();
void setHwBpOnSlot3ActionSlot();
void setHwBpAt(duint va, int slot);
private:
GetSelectionFunc mGetSelection;
};

View File

@ -18,12 +18,11 @@
#include "HexEditDialog.h"
#include "AssembleDialog.h"
#include "StringUtil.h"
#include "Breakpoints.h"
#include "XrefBrowseDialog.h"
#include "SourceViewerManager.h"
#include "MiscUtil.h"
#include "MemoryPage.h"
#include "BreakpointMenu.h"
#include "CommonActions.h"
#include "BrowseDialog.h"
CPUDisassembly::CPUDisassembly(QWidget* parent, bool isMain) : Disassembly(parent, isMain)
@ -96,7 +95,7 @@ void CPUDisassembly::mouseDoubleClickEvent(QMouseEvent* event)
// (Opcodes) Set INT3 breakpoint
case 1:
mBreakpointMenu->toggleInt3BPActionSlot();
mCommonActions->toggleInt3BPActionSlot();
break;
// (Disassembly) Assemble dialog
@ -111,7 +110,7 @@ void CPUDisassembly::mouseDoubleClickEvent(QMouseEvent* event)
// (Comments) Set comment dialog
case 3:
setCommentSlot();
mCommonActions->setCommentSlot();
break;
// Undefined area
@ -308,11 +307,11 @@ void CPUDisassembly::setupRightClickContextMenu()
return DbgFunctions()->PatchInRange(start, end); //something patched in selected range
});
mBreakpointMenu = new BreakpointMenu(this, getActionHelperFuncs(), [this]()
mCommonActions = new CommonActions(this, getActionHelperFuncs(), [this]()
{
return rvaToVa(getInitialSelection());
});
mBreakpointMenu->build(mMenuBuilder);
mCommonActions->build(mMenuBuilder, CommonActions::ActionBreakpoint | CommonActions::ActionMemoryMap | CommonActions::ActionComment | CommonActions::ActionBookmark);
mMenuBuilder->addMenu(makeMenu(DIcon("dump.png"), tr("&Follow in Dump")), [this](QMenu * menu)
{
@ -326,7 +325,7 @@ void CPUDisassembly::setupRightClickContextMenu()
return menu->actions().length() != 0; //only add this menu if there is something to follow
});
mMenuBuilder->addAction(makeShortcutAction(DIcon("memmap_find_address_page.png"), tr("Follow in Memory Map"), SLOT(followInMemoryMapSlot()), "ActionFollowMemMap"));
//mMenuBuilder->addAction(makeShortcutAction(DIcon("memmap_find_address_page.png"), tr("Follow in Memory Map"), SLOT(followInMemoryMapSlot()), "ActionFollowMemMap"));
mMenuBuilder->addAction(makeShortcutAction(DIcon("source.png"), tr("Open Source File"), SLOT(openSourceSlot()), "ActionOpenSourceFile"), [this](QMenu*)
{
@ -406,8 +405,8 @@ void CPUDisassembly::setupRightClickContextMenu()
return true;
});
mMenuBuilder->addAction(makeShortcutAction(DIcon("comment.png"), tr("Comment"), SLOT(setCommentSlot()), "ActionSetComment"));
mMenuBuilder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), SLOT(setBookmarkSlot()), "ActionToggleBookmark"));
//mMenuBuilder->addAction(makeShortcutAction(DIcon("comment.png"), tr("Comment"), SLOT(setCommentSlot()), "ActionSetComment"));
//mMenuBuilder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), SLOT(setBookmarkSlot()), "ActionToggleBookmark"));
mMenuBuilder->addSeparator();
MenuBuilder* analysisMenu = new MenuBuilder(this);
@ -785,7 +784,7 @@ restart:
GuiUpdateAllViews();
}
void CPUDisassembly::setCommentSlot()
/*void CPUDisassembly::setCommentSlot()
{
if(!DbgIsDebugging())
return;
@ -843,7 +842,7 @@ void CPUDisassembly::setBookmarkSlot()
GuiUpdateAllViews();
}
*/
void CPUDisassembly::toggleFunctionSlot()
{
if(!DbgIsDebugging())
@ -2040,10 +2039,10 @@ bool CPUDisassembly::getTokenValueText(QString & text)
return true;
}
void CPUDisassembly::followInMemoryMapSlot()
{
DbgCmdExec(QString("memmapdump %1").arg(ToHexString(rvaToVa(getInitialSelection()))));
}
//void CPUDisassembly::followInMemoryMapSlot()
//{
// DbgCmdExec(QString("memmapdump %1").arg(ToHexString(rvaToVa(getInitialSelection()))));
//}
void CPUDisassembly::downloadCurrentSymbolsSlot()
{

View File

@ -2,12 +2,12 @@
#define CPUDISASSEMBLY_H
#include "Disassembly.h"
#include "BreakpointMenu.h"
// Needed forward declaration for parent container class
class CPUSideBar;
class GotoDialog;
class XrefBrowseDialog;
class CommonActions;
class CPUDisassembly : public Disassembly
{
@ -41,8 +41,8 @@ public slots:
void gotoOriginSlot();
void setLabelSlot();
void setLabelAddressSlot();
void setCommentSlot();
void setBookmarkSlot();
//void setCommentSlot();
//void setBookmarkSlot();
void toggleFunctionSlot();
void toggleArgumentSlot();
void addLoopSlot();
@ -110,7 +110,7 @@ public slots:
void createThreadSlot();
void copyTokenTextSlot();
void copyTokenValueSlot();
void followInMemoryMapSlot();
//void followInMemoryMapSlot();
void downloadCurrentSymbolsSlot();
protected:
@ -169,7 +169,7 @@ private:
MenuBuilder* mMenuBuilder;
MenuBuilder* mHighlightMenuBuilder;
bool mHighlightContextMenu = false;
BreakpointMenu* mBreakpointMenu;
CommonActions* mCommonActions;
};
#endif // CPUDISASSEMBLY_H

View File

@ -10,6 +10,7 @@
#include "CPUMultiDump.h"
#include "GotoDialog.h"
#include "CPUDisassembly.h"
#include "CommonActions.h"
#include "WordEditDialog.h"
#include "CodepageSelectionDialog.h"
#include "MiscUtil.h"
@ -41,6 +42,11 @@ void CPUDump::setupContextMenu()
return DbgIsDebugging();
});
mCommonActions = new CommonActions(this, getActionHelperFuncs(), [this]()
{
return rvaToVa(getInitialSelection());
});
MenuBuilder* wBinaryMenu = new MenuBuilder(this);
wBinaryMenu->addAction(makeShortcutAction(DIcon("binary_edit.png"), tr("&Edit"), SLOT(binaryEditSlot()), "ActionBinaryEdit"));
wBinaryMenu->addAction(makeShortcutAction(DIcon("binary_fill.png"), tr("&Fill..."), SLOT(binaryFillSlot()), "ActionBinaryFill"));
@ -75,13 +81,16 @@ void CPUDump::setupContextMenu()
{
return DbgFunctions()->PatchInRange(rvaToVa(getSelectionStart()), rvaToVa(getSelectionEnd()));
});
mMenuBuilder->addAction(makeShortcutAction(DIcon("stack.png"), tr("Follow in Stack"), SLOT(followStackSlot()), "ActionFollowStack"), [this](QMenu*)
{
auto start = rvaToVa(getSelectionStart());
return (DbgMemIsValidReadPtr(start) && DbgMemFindBaseAddr(start, 0) == DbgMemFindBaseAddr(DbgValFromString("csp"), 0));
});
mMenuBuilder->addAction(makeShortcutAction(DIcon("memmap_find_address_page.png"), tr("Follow in Memory Map"), SLOT(followInMemoryMapSlot()), "ActionFollowMemMap"));
mMenuBuilder->addAction(makeShortcutAction(DIcon(ArchValue("processor32.png", "processor64.png")), tr("Follow in Disassembler"), SLOT(followInDisasmSlot()), "ActionFollowDisasm"));
//mMenuBuilder->addAction(makeShortcutAction(DIcon("stack.png"), tr("Follow in Stack"), SLOT(followStackSlot()), "ActionFollowStack"), [this](QMenu*)
//{
// auto start = rvaToVa(getSelectionStart());
// return (DbgMemIsValidReadPtr(start) && DbgMemFindBaseAddr(start, 0) == DbgMemFindBaseAddr(DbgValFromString("csp"), 0));
//});
mCommonActions->build(mMenuBuilder, CommonActions::ActionDisasm | CommonActions::ActionMemoryMap | CommonActions::ActionDumpData | CommonActions::ActionDisasmData
| CommonActions::ActionStackDump);
//mMenuBuilder->addAction(makeShortcutAction(DIcon("memmap_find_address_page.png"), tr("Follow in Memory Map"), SLOT(followInMemoryMapSlot()), "ActionFollowMemMap"));
//mMenuBuilder->addAction(makeShortcutAction(DIcon(ArchValue("processor32.png", "processor64.png")), tr("Follow in Disassembler"), SLOT(followInDisasmSlot()), "ActionFollowDisasm"));
auto wIsValidReadPtrCallback = [this](QMenu*)
{
duint ptr = 0;
@ -89,8 +98,8 @@ void CPUDump::setupContextMenu()
return DbgMemIsValidReadPtr(ptr);
};
mMenuBuilder->addAction(makeShortcutAction(DIcon("processor32.png"), ArchValue(tr("&Follow DWORD in Disassembler"), tr("&Follow QWORD in Disassembler")), SLOT(followDataSlot()), "ActionFollowDwordQwordDisasm"), wIsValidReadPtrCallback);
mMenuBuilder->addAction(makeShortcutAction(DIcon("dump.png"), ArchValue(tr("&Follow DWORD in Current Dump"), tr("&Follow QWORD in Current Dump")), SLOT(followDataDumpSlot()), "ActionFollowDwordQwordDump"), wIsValidReadPtrCallback);
//mMenuBuilder->addAction(makeShortcutAction(DIcon("processor32.png"), ArchValue(tr("&Follow DWORD in Disassembler"), tr("&Follow QWORD in Disassembler")), SLOT(followDataSlot()), "ActionFollowDwordQwordDisasm"), wIsValidReadPtrCallback);
//mMenuBuilder->addAction(makeShortcutAction(DIcon("dump.png"), ArchValue(tr("&Follow DWORD in Current Dump"), tr("&Follow QWORD in Current Dump")), SLOT(followDataDumpSlot()), "ActionFollowDwordQwordDump"), wIsValidReadPtrCallback);
MenuBuilder* wFollowInDumpMenu = new MenuBuilder(this, [wIsValidReadPtrCallback, this](QMenu * menu)
{
@ -1610,25 +1619,25 @@ void CPUDump::undoSelectionSlot()
reloadData();
}
void CPUDump::followStackSlot()
{
DbgCmdExec(QString("sdump " + ToPtrString(rvaToVa(getSelectionStart()))));
}
//void CPUDump::followStackSlot()
//{
// DbgCmdExec(QString("sdump " + ToPtrString(rvaToVa(getSelectionStart()))));
//}
void CPUDump::followInDisasmSlot()
{
DbgCmdExec(QString("disasm " + ToPtrString(rvaToVa(getSelectionStart()))));
}
//void CPUDump::followInDisasmSlot()
//{
// DbgCmdExec(QString("disasm " + ToPtrString(rvaToVa(getSelectionStart()))));
//}
void CPUDump::followDataSlot()
{
DbgCmdExec(QString("disasm \"[%1]\"").arg(ToPtrString(rvaToVa(getSelectionStart()))));
}
//void CPUDump::followDataSlot()
//{
// DbgCmdExec(QString("disasm \"[%1]\"").arg(ToPtrString(rvaToVa(getSelectionStart()))));
//}
void CPUDump::followDataDumpSlot()
{
DbgCmdExec(QString("dump \"[%1]\"").arg(ToPtrString(rvaToVa(getSelectionStart()))));
}
//void CPUDump::followDataDumpSlot()
//{
// DbgCmdExec(QString("dump \"[%1]\"").arg(ToPtrString(rvaToVa(getSelectionStart()))));
//}
void CPUDump::selectionUpdatedSlot()
{
@ -1774,10 +1783,10 @@ void CPUDump::setView(ViewEnum_t view)
}
}
void CPUDump::followInMemoryMapSlot()
{
DbgCmdExec(QString("memmapdump %1").arg(ToHexString(rvaToVa(getSelectionStart()))));
}
//void CPUDump::followInMemoryMapSlot()
//{
// DbgCmdExec(QString("memmapdump %1").arg(ToHexString(rvaToVa(getSelectionStart()))));
//}
void CPUDump::headerButtonReleasedSlot(int colIndex)
{

View File

@ -7,6 +7,7 @@
class CPUMultiDump;
class CPUDisassembly;
class GotoDialog;
class CommonActions;
class CPUDump : public HexDump
{
@ -97,11 +98,11 @@ public slots:
void findPattern();
void copyFileOffsetSlot();
void undoSelectionSlot();
void followStackSlot();
//void followStackSlot();
void findReferencesSlot();
void followInDisasmSlot();
void followDataSlot();
void followDataDumpSlot();
//void followInDisasmSlot();
//void followDataSlot();
//void followDataDumpSlot();
void watchSlot();
@ -110,11 +111,12 @@ public slots:
void followInDumpNSlot();
void allocMemorySlot();
void followInMemoryMapSlot();
//void followInMemoryMapSlot();
void headerButtonReleasedSlot(int colIndex);
private:
MenuBuilder* mMenuBuilder;
CommonActions* mCommonActions;
QMenu* mPluginMenu;
QMenu* mFollowInDumpMenu;

View File

@ -13,7 +13,7 @@
#include <QMimeData>
#include <QFileDialog>
#include <QMessageBox>
#include "BreakpointMenu.h"
#include "CommonActions.h"
#include "StringUtil.h"
#include "MiscUtil.h"
#include <QMainWindow>
@ -2181,26 +2181,26 @@ void DisassemblerGraphView::setupContextMenu()
return DbgIsDebugging() && this->ready;
});
mMenuBuilder->addAction(makeShortcutAction(DIcon(QString("processor%1.png").arg(ArchValue("32", "64"))), tr("Follow in &Disassembler"), SLOT(followDisassemblerSlot()), "ActionGraphFollowDisassembler"), [this](QMenu*)
{
return this->cur_instr != 0;
});
//mMenuBuilder->addAction(makeShortcutAction(DIcon(QString("processor%1.png").arg(ArchValue("32", "64"))), tr("Follow in &Disassembler"), SLOT(followDisassemblerSlot()), "ActionGraphFollowDisassembler"), [this](QMenu*)
//{
// return this->cur_instr != 0;
//});
mMenuBuilder->addSeparator();
auto breakpointMenu = new BreakpointMenu(this, getActionHelperFuncs(), [this]()
mCommonActions = new CommonActions(this, getActionHelperFuncs(), [this]()
{
return zoomActionHelper();
});
breakpointMenu->build(mMenuBuilder);
mCommonActions->build(mMenuBuilder, CommonActions::ActionBookmark | CommonActions::ActionComment | CommonActions::ActionDisasm);
auto zoomActionHelperNonZero = [this](QMenu*)
{
return zoomActionHelper() != 0;
};
mMenuBuilder->addAction(makeShortcutAction(DIcon("comment.png"), tr("&Comment"), SLOT(setCommentSlot()), "ActionSetComment"), zoomActionHelperNonZero);
//mMenuBuilder->addAction(makeShortcutAction(DIcon("comment.png"), tr("&Comment"), SLOT(setCommentSlot()), "ActionSetComment"), zoomActionHelperNonZero);
mMenuBuilder->addAction(makeShortcutAction(DIcon("label.png"), tr("&Label"), SLOT(setLabelSlot()), "ActionSetLabel"), zoomActionHelperNonZero);
mMenuBuilder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), SLOT(setBookmarkSlot()), "ActionToggleBookmark"));
//mMenuBuilder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), SLOT(setBookmarkSlot()), "ActionToggleBookmark"));
mMenuBuilder->addAction(makeShortcutAction(DIcon("xrefs.png"), tr("Xrefs..."), SLOT(xrefSlot()), "ActionXrefs"), zoomActionHelperNonZero);
MenuBuilder* gotoMenu = new MenuBuilder(this);
@ -2363,10 +2363,10 @@ void DisassemblerGraphView::keyPressEvent(QKeyEvent* event)
}
}
void DisassemblerGraphView::followDisassemblerSlot()
/*void DisassemblerGraphView::followDisassemblerSlot()
{
DbgCmdExec(QString("disasm %1").arg(ToPtrString(this->cur_instr)));
}
}*/
void DisassemblerGraphView::colorsUpdatedSlot()
{
@ -2514,7 +2514,7 @@ void DisassemblerGraphView::saveImageSlot()
this->viewport()->update();
}
void DisassemblerGraphView::setCommentSlot()
/*void DisassemblerGraphView::setCommentSlot()
{
duint wVA = this->get_cursor_pos();
LineEditDialog mLineEdit(this);
@ -2543,7 +2543,7 @@ void DisassemblerGraphView::setCommentSlot()
SimpleErrorBox(this, tr("Error!"), tr("DbgSetCommentAt failed!"));
this->refreshSlot();
}
}*/
void DisassemblerGraphView::setLabelSlot()
{
@ -2583,7 +2583,7 @@ restart:
this->refreshSlot();
}
void DisassemblerGraphView::setBookmarkSlot()
/*void DisassemblerGraphView::setBookmarkSlot()
{
if(!DbgIsDebugging())
return;
@ -2603,7 +2603,7 @@ void DisassemblerGraphView::setBookmarkSlot()
}
GuiUpdateAllViews();
}
}*/
void DisassemblerGraphView::xrefSlot()
{

View File

@ -23,6 +23,7 @@ class MenuBuilder;
class CachedFontMetrics;
class GotoDialog;
class XrefBrowseDialog;
class CommonActions;
class DisassemblerGraphView : public QAbstractScrollArea, public ActionHelper<DisassemblerGraphView>
{
@ -267,7 +268,7 @@ public slots:
void loadGraphSlot(BridgeCFGraphList* graph, duint addr);
void graphAtSlot(duint addr);
void updateGraphSlot();
void followDisassemblerSlot();
//void followDisassemblerSlot();
void colorsUpdatedSlot();
void fontsUpdatedSlot();
void shortcutsUpdatedSlot();
@ -285,9 +286,9 @@ public slots:
void followActionSlot();
void refreshSlot();
void saveImageSlot();
void setCommentSlot();
//void setCommentSlot();
void setLabelSlot();
void setBookmarkSlot();
//void setBookmarkSlot();
void xrefSlot();
void mnemonicHelpSlot();
void fitToWindowSlot();
@ -334,6 +335,7 @@ private:
std::vector<int> row_edge_y;
CachedFontMetrics* mFontMetrics;
MenuBuilder* mMenuBuilder;
CommonActions* mCommonActions;
QMenu* mPluginMenu;
bool drawOverview;
bool onlySummary;

View File

@ -7,6 +7,7 @@
#include <memory>
#include "FileLines.h"
#include "Bridge.h"
#include "CommonActions.h"
SourceView::SourceView(QString path, duint addr, QWidget* parent)
: AbstractStdTable(parent),
@ -117,14 +118,6 @@ void SourceView::contextMenuSlot(const QPoint & pos)
wMenu.exec(mapToGlobal(pos));
}
void SourceView::followDisassemblerSlot()
{
duint addr = addrFromIndex(getInitialSelection());
if(!DbgMemIsValidReadPtr(addr))
return;
DbgCmdExec(QString("disasm %1").arg(ToPtrString(addr)));
}
void SourceView::followDumpSlot()
{
duint addr = addrFromIndex(getInitialSelection());
@ -133,22 +126,6 @@ void SourceView::followDumpSlot()
DbgCmdExec(QString("dump %1").arg(ToPtrString(addr)));
}
void SourceView::toggleBookmarkSlot()
{
duint addr = addrFromIndex(getInitialSelection());
if(!DbgMemIsValidReadPtr(addr))
return;
bool result;
if(DbgGetBookmarkAt(addr))
result = DbgSetBookmarkAt(addr, false);
else
result = DbgSetBookmarkAt(addr, true);
if(!result)
SimpleErrorBox(this, tr("Error!"), tr("DbgSetBookmarkAt failed!"));
GuiUpdateAllViews();
}
void SourceView::gotoLineSlot()
{
bool ok = false;
@ -176,21 +153,16 @@ void SourceView::showInDirectorySlot()
void SourceView::setupContextMenu()
{
mMenuBuilder = new MenuBuilder(this);
mMenuBuilder->addAction(makeAction(DIcon(ArchValue("processor32.png", "processor64.png")), tr("&Follow in Disassembler"), SLOT(followDisassemblerSlot())), [this](QMenu*)
{
return DbgMemIsValidReadPtr(addrFromIndex(getInitialSelection()));
});
mMenuBuilder->addAction(makeAction(DIcon("dump.png"), tr("Follow in &Dump"), SLOT(followDumpSlot())), [this](QMenu*)
{
return DbgMemIsValidReadPtr(addrFromIndex(getInitialSelection()));
});
mMenuBuilder->addSeparator();
mBreakpointMenu = new BreakpointMenu(this, getActionHelperFuncs(), [this]()
mCommonActions = new CommonActions(this, getActionHelperFuncs(), [this]()
{
return addrFromIndex(getInitialSelection());
});
mBreakpointMenu->build(mMenuBuilder);
mMenuBuilder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), SLOT(toggleBookmarkSlot()), "ActionToggleBookmark"));
mCommonActions->build(mMenuBuilder, CommonActions::ActionDisasm | CommonActions::ActionBreakpoint | CommonActions::ActionBookmark);
mMenuBuilder->addSeparator();
mMenuBuilder->addAction(makeShortcutAction(DIcon("geolocation-goto.png"), tr("Go to line"), SLOT(gotoLineSlot()), "ActionGotoExpression"));
mMenuBuilder->addAction(makeAction(DIcon("source.png"), tr("Open source file"), SLOT(openSourceFileSlot())));

View File

@ -3,9 +3,9 @@
#include <QWidget>
#include <AbstractStdTable.h>
#include "BreakpointMenu.h"
class FileLines;
class CommonActions;
class SourceView : public AbstractStdTable
{
@ -25,16 +25,14 @@ public:
private slots:
void contextMenuSlot(const QPoint & pos);
void followDisassemblerSlot();
void followDumpSlot();
void toggleBookmarkSlot();
void gotoLineSlot();
void openSourceFileSlot();
void showInDirectorySlot();
private:
MenuBuilder* mMenuBuilder = nullptr;
BreakpointMenu* mBreakpointMenu = nullptr;
CommonActions* mCommonActions = nullptr;
QString mSourcePath;
duint mModBase;
int mTabSize = 4; //TODO: make customizable?

View File

@ -6,10 +6,10 @@
#include "BrowseDialog.h"
#include "QBeaEngine.h"
#include "GotoDialog.h"
#include "CommonActions.h"
#include "LineEditDialog.h"
#include "WordEditDialog.h"
#include "CachedFontMetrics.h"
#include "BreakpointMenu.h"
#include "MRUList.h"
#include <QFileDialog>
@ -796,6 +796,13 @@ void TraceBrowser::prepareData()
void TraceBrowser::setupRightClickContextMenu()
{
mMenuBuilder = new MenuBuilder(this);
mCommonActions = new CommonActions(this, getActionHelperFuncs(), [this]
{
if(mTraceFile == nullptr || mTraceFile->Progress() < 100 || mTraceFile->Length() == 0)
return (duint)0;
else
return mTraceFile->Registers(getInitialSelection()).regcontext.cip;
});
QAction* toggleRunTrace = makeShortcutAction(DIcon("trace.png"), tr("Start Run Trace"), SLOT(toggleRunTraceSlot()), "ActionToggleRunTrace");
mMenuBuilder->addAction(toggleRunTrace, [toggleRunTrace](QMenu*)
{
@ -854,19 +861,12 @@ void TraceBrowser::setupRightClickContextMenu()
copyMenu->addAction(makeAction(DIcon("copy_address.png"), tr("Index"), SLOT(copyIndexSlot())));
mMenuBuilder->addMenu(makeMenu(DIcon("copy.png"), tr("&Copy")), copyMenu);
mMenuBuilder->addAction(makeShortcutAction(DIcon(ArchValue("processor32.png", "processor64.png")), tr("&Follow in Disassembler"), SLOT(followDisassemblySlot()), "ActionFollowDisasm"), isValid);
//mMenuBuilder->addAction(makeShortcutAction(DIcon(ArchValue("processor32.png", "processor64.png")), tr("&Follow in Disassembler"), SLOT(followDisassemblySlot()), "ActionFollowDisasm"), isValid);
mBreakpointMenu = new BreakpointMenu(this, getActionHelperFuncs(), [this, isValid]()
{
if(isValid(nullptr))
return mTraceFile->Registers(getInitialSelection()).regcontext.cip;
else
return (duint)0;
});
mBreakpointMenu->build(mMenuBuilder);
mCommonActions->build(mMenuBuilder, CommonActions::ActionDisasm | CommonActions::ActionBreakpoint | CommonActions::ActionComment | CommonActions::ActionBookmark);
mMenuBuilder->addAction(makeShortcutAction(DIcon("label.png"), tr("Label Current Address"), SLOT(setLabelSlot()), "ActionSetLabel"), isDebugging);
mMenuBuilder->addAction(makeShortcutAction(DIcon("comment.png"), tr("&Comment"), SLOT(setCommentSlot()), "ActionSetComment"), isDebugging);
mMenuBuilder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), SLOT(setBookmarkSlot()), "ActionToggleBookmark"), isDebugging);
//mMenuBuilder->addAction(makeShortcutAction(DIcon("comment.png"), tr("&Comment"), SLOT(setCommentSlot()), "ActionSetComment"), isDebugging);
//mMenuBuilder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), SLOT(setBookmarkSlot()), "ActionToggleBookmark"), isDebugging);
mMenuBuilder->addAction(makeShortcutAction(DIcon("highlight.png"), tr("&Highlighting mode"), SLOT(enableHighlightingModeSlot()), "ActionHighlightingMode"), isValid);
mMenuBuilder->addAction(makeShortcutAction(DIcon("helpmnemonic.png"), tr("Help on mnemonic"), SLOT(mnemonicHelpSlot()), "ActionHelpOnMnemonic"), isValid);
QAction* mnemonicBrief = makeShortcutAction(DIcon("helpbrief.png"), tr("Show mnemonic brief"), SLOT(mnemonicBriefSlot()), "ActionToggleMnemonicBrief");
@ -1038,7 +1038,7 @@ void TraceBrowser::mouseDoubleClickEvent(QMouseEvent* event)
switch(getColumnIndexFromX(event->x()))
{
case Index://Index: follow
followDisassemblySlot();
mCommonActions->followDisassemblySlot();
break;
case Address://Address: set RVA
if(mRvaDisplayEnabled && mTraceFile->Registers(getInitialSelection()).regcontext.cip == mRvaDisplayBase)
@ -1051,13 +1051,13 @@ void TraceBrowser::mouseDoubleClickEvent(QMouseEvent* event)
reloadData();
break;
case Opcode: //Opcode: Breakpoint
mBreakpointMenu->toggleInt3BPActionSlot();
mCommonActions->toggleInt3BPActionSlot();
break;
case Disassembly: //Instructions: follow
followDisassemblySlot();
mCommonActions->followDisassemblySlot();
break;
case Comments: //Comment
setCommentSlot();
mCommonActions->setCommentSlot();
break;
}
}
@ -1153,7 +1153,7 @@ void TraceBrowser::keyPressEvent(QKeyEvent* event)
void TraceBrowser::onSelectionChanged(unsigned long long selection)
{
if(mAutoDisassemblyFollowSelection)
followDisassemblySlot();
mCommonActions->followDisassemblySlot();
}
void TraceBrowser::tokenizerConfigUpdatedSlot()
@ -1770,65 +1770,6 @@ void TraceBrowser::exportSlot()
});
}
void TraceBrowser::setCommentSlot()
{
if(!DbgIsDebugging() || mTraceFile == nullptr || mTraceFile->Progress() < 100)
return;
duint wVA = mTraceFile->Registers(getInitialSelection()).regcontext.cip;
LineEditDialog mLineEdit(this);
mLineEdit.setTextMaxLength(MAX_COMMENT_SIZE - 2);
QString addr_text = ToPtrString(wVA);
char comment_text[MAX_COMMENT_SIZE] = "";
if(DbgGetCommentAt((duint)wVA, comment_text))
{
if(comment_text[0] == '\1') //automatic comment
mLineEdit.setText(QString(comment_text + 1));
else
mLineEdit.setText(QString(comment_text));
}
mLineEdit.setWindowTitle(tr("Add comment at ") + addr_text);
if(mLineEdit.exec() != QDialog::Accepted)
return;
QString comment = mLineEdit.editText.replace('\r', "").replace('\n', "");
if(!DbgSetCommentAt(wVA, comment.toUtf8().constData()))
SimpleErrorBox(this, tr("Error!"), tr("DbgSetCommentAt failed!"));
static bool easter = isEaster();
if(easter && comment.toLower() == "oep")
{
QFile file(":/icons/images/egg.wav");
if(file.open(QIODevice::ReadOnly))
{
QByteArray egg = file.readAll();
PlaySoundA(egg.data(), 0, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
}
}
GuiUpdateAllViews();
}
void TraceBrowser::setBookmarkSlot()
{
if(!DbgIsDebugging())
return;
duint wVA = mTraceFile->Registers(getInitialSelection()).regcontext.cip;
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 TraceBrowser::setLabelSlot()
{
if(!DbgIsDebugging() || mTraceFile == nullptr || mTraceFile->Progress() < 100)
@ -1871,18 +1812,6 @@ void TraceBrowser::enableHighlightingModeSlot()
reloadData();
}
void TraceBrowser::followDisassemblySlot()
{
if(mTraceFile == nullptr || mTraceFile->Progress() < 100)
return;
duint cip = mTraceFile->Registers(getInitialSelection()).regcontext.cip;
if(DbgMemIsValidReadPtr(cip))
DbgCmdExec(QString("dis ").append(ToPtrString(cip)));
else
GuiAddStatusBarMessage(tr("Cannot follow %1. Address is invalid.\n").arg(ToPtrString(cip)).toUtf8().constData());
}
void TraceBrowser::searchConstantSlot()
{
WordEditDialog constantDlg(this);

View File

@ -8,6 +8,7 @@
class TraceFileReader;
class BreakpointMenu;
class MRUList;
class CommonActions;
class TraceBrowser : public AbstractTableView
{
@ -60,6 +61,7 @@ private:
ZydisTokenizer::InstructionToken registersTokens(unsigned long long atIndex);
VaHistory mHistory;
MenuBuilder* mMenuBuilder;
CommonActions* mCommonActions;
bool mRvaDisplayEnabled;
duint mRvaDisplayBase;
@ -160,11 +162,11 @@ public slots:
void gotoSlot();
void gotoPreviousSlot();
void gotoNextSlot();
void followDisassemblySlot();
//void followDisassemblySlot();
void enableHighlightingModeSlot();
void setLabelSlot();
void setCommentSlot();
void setBookmarkSlot();
//void setCommentSlot();
//void setBookmarkSlot();
void mnemonicBriefSlot();
void mnemonicHelpSlot();
void copyDisassemblySlot();

View File

@ -0,0 +1,352 @@
#include "CommonActions.h"
#include "MenuBuilder.h"
#include <QAction>
#include <QMessageBox>
#include <QFile>
#include "StringUtil.h"
#include "MiscUtil.h"
#include "Breakpoints.h"
#include "LineEditDialog.h"
CommonActions::CommonActions(QWidget* parent, ActionHelperFuncs funcs, GetSelectionFunc getSelection)
: QObject(parent), ActionHelperProxy(funcs), mGetSelection(getSelection)
{
}
void CommonActions::build(MenuBuilder* builder, int actions)
{
build(builder, actions, [](QList<std::pair<QString, duint>> &, CommonActionsList) {});
}
void CommonActions::build(MenuBuilder* builder, int actions, std::function<void(QList<std::pair<QString, duint>>&, CommonActionsList)> additionalAddress)
{
// Condition Lambda
auto wIsValidCallback = [this](QMenu*)
{
return mGetSelection() != 0;
};
auto wIsValidReadPtrCallback = [this](QMenu*)
{
duint ptr = 0;
DbgMemRead(mGetSelection(), (unsigned char*)&ptr, sizeof(duint));
return DbgMemIsValidReadPtr(ptr);
};
// Menu action
if(actions & ActionDisasm)
{
builder->addAction(makeShortcutAction(DIcon(ArchValue("processor32.png", "processor64.png")), tr("Follow in Disassembler"), std::bind(&CommonActions::followDisassemblySlot, this), "ActionFollowDisasm"), wIsValidCallback);
}
if(actions & ActionDisasmData)
{
builder->addAction(makeCommandAction(DIcon("processor32.png"), ArchValue(tr("&Follow DWORD in Disassembler"), tr("&Follow QWORD in Disassembler")), "disasm [$]", "ActionFollowDwordQwordDisasm"), wIsValidReadPtrCallback);
}
if(actions & ActionDumpData)
{
builder->addAction(makeCommandAction(DIcon("dump.png"), ArchValue(tr("&Follow DWORD in Current Dump"), tr("&Follow QWORD in Current Dump")), "dump [$]", "ActionFollowDwordQwordDump"), wIsValidReadPtrCallback);
}
if(actions & ActionStackDump)
{
builder->addAction(makeCommandAction(DIcon("stack.png"), tr("Follow in Stack"), "sdump $", "ActionFollowStack"), [this](QMenu*)
{
auto start = mGetSelection();
return (DbgMemIsValidReadPtr(start) && DbgMemFindBaseAddr(start, 0) == DbgMemFindBaseAddr(DbgValFromString("csp"), 0));
});
}
if(actions & ActionMemoryMap)
{
builder->addAction(makeCommandAction(DIcon("memmap_find_address_page.png"), tr("Follow in Memory Map"), "memmapdump $", "ActionFollowMemMap"), wIsValidCallback);
}
if(actions & ActionBreakpoint)
{
QAction* toggleBreakpointAction = makeShortcutAction(DIcon("breakpoint_toggle.png"), tr("Toggle"), std::bind(&CommonActions::toggleInt3BPActionSlot, this), "ActionToggleBreakpoint");
QAction* editSoftwareBreakpointAction = makeShortcutAction(DIcon("breakpoint_edit_alt.png"), tr("Edit"), std::bind(&CommonActions::editSoftBpActionSlot, this), "ActionEditBreakpoint");
QAction* setHwBreakpointAction = makeShortcutAction(DIcon("breakpoint_execute.png"), tr("Set Hardware on Execution"), std::bind(&CommonActions::toggleHwBpActionSlot, this), "ActionSetHwBpE");
QAction* removeHwBreakpointAction = makeShortcutAction(DIcon("breakpoint_remove.png"), tr("Remove Hardware"), std::bind(&CommonActions::toggleHwBpActionSlot, this), "ActionRemoveHwBp");
QMenu* replaceSlotMenu = makeMenu(DIcon("breakpoint_execute.png"), tr("Set Hardware on Execution"));
// Replacement slot menu are only used when the breakpoints are full, so using "Unknown" as the placeholder. Might want to change this in case we display the menu when there are still free slots.
QAction* replaceSlot0Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot1.png"), tr("Replace Slot 0 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot0ActionSlot, this));
QAction* replaceSlot1Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot2.png"), tr("Replace Slot 1 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot1ActionSlot, this));
QAction* replaceSlot2Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot3.png"), tr("Replace Slot 2 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot2ActionSlot, this));
QAction* replaceSlot3Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot4.png"), tr("Replace Slot 3 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot3ActionSlot, this));
builder->addMenu(makeMenu(DIcon("breakpoint.png"), tr("Breakpoint")), [ = ](QMenu * menu)
{
auto selection = mGetSelection();
if(selection == 0)
return false;
BPXTYPE bpType = DbgGetBpxTypeAt(selection);
if((bpType & bp_normal) == bp_normal || (bpType & bp_hardware) == bp_hardware)
editSoftwareBreakpointAction->setText(tr("Edit"));
else
editSoftwareBreakpointAction->setText(tr("Set Conditional Breakpoint"));
menu->addAction(editSoftwareBreakpointAction);
menu->addAction(toggleBreakpointAction);
if((bpType & bp_hardware) == bp_hardware)
{
menu->addAction(removeHwBreakpointAction);
}
else
{
BPMAP bpList;
DbgGetBpList(bp_hardware, &bpList);
//get enabled hwbp count
int enabledCount = bpList.count;
for(int i = 0; i < bpList.count; i++)
if(!bpList.bp[i].enabled)
enabledCount--;
if(enabledCount < 4)
{
menu->addAction(setHwBreakpointAction);
}
else
{
for(int i = 0; i < bpList.count; i++)
{
if(bpList.bp[i].enabled)
{
switch(bpList.bp[i].slot)
{
case 0:
replaceSlot0Action->setText(tr("Replace Slot %1 (0x%2)").arg(1).arg(ToPtrString(bpList.bp[i].addr)));
break;
case 1:
replaceSlot1Action->setText(tr("Replace Slot %1 (0x%2)").arg(2).arg(ToPtrString(bpList.bp[i].addr)));
break;
case 2:
replaceSlot2Action->setText(tr("Replace Slot %1 (0x%2)").arg(3).arg(ToPtrString(bpList.bp[i].addr)));
break;
case 3:
replaceSlot3Action->setText(tr("Replace Slot %1 (0x%2)").arg(4).arg(ToPtrString(bpList.bp[i].addr)));
break;
default:
break;
}
}
}
menu->addMenu(replaceSlotMenu);
}
if(bpList.count)
BridgeFree(bpList.bp);
}
return true;
});
}
if(actions & ActionComment)
{
builder->addAction(makeShortcutAction(DIcon("comment.png"), tr("Comment"), std::bind(&CommonActions::setCommentSlot, this), "ActionSetComment"), wIsValidCallback);
}
if(actions & ActionBookmark)
{
builder->addAction(makeShortcutAction(DIcon("bookmark_toggle.png"), tr("Toggle Bookmark"), std::bind(&CommonActions::setBookmarkSlot, this), "ActionToggleBookmark"), wIsValidCallback);
}
}
QAction* CommonActions::makeCommandAction(const QIcon & icon, const QString & text, const char* cmd, const char* shortcut)
{
QAction* action;
action = makeShortcutAction(icon, text, [cmd, this]()
{
DbgCmdExec(QString(cmd).replace("$", ToPtrString(mGetSelection())));
}, shortcut);
action->setData(QVariant(cmd));
return action;
}
QWidget* CommonActions::widgetparent()
{
return dynamic_cast<QWidget*>(parent());
}
// Actions slots
void CommonActions::followDisassemblySlot()
{
duint cip = mGetSelection();
if(DbgMemIsValidReadPtr(cip))
DbgCmdExec(QString("dis ").append(ToPtrString(cip)));
else
GuiAddStatusBarMessage(tr("Cannot follow %1. Address is invalid.\n").arg(ToPtrString(cip)).toUtf8().constData());
}
void CommonActions::setCommentSlot()
{
if(!DbgIsDebugging())
return;
duint wVA = mGetSelection();
LineEditDialog mLineEdit(widgetparent());
mLineEdit.setTextMaxLength(MAX_COMMENT_SIZE - 2);
QString addr_text = ToPtrString(wVA);
char comment_text[MAX_COMMENT_SIZE] = "";
if(DbgGetCommentAt((duint)wVA, comment_text))
{
if(comment_text[0] == '\1') //automatic comment
mLineEdit.setText(QString(comment_text + 1));
else
mLineEdit.setText(QString(comment_text));
}
mLineEdit.setWindowTitle(tr("Add comment at ") + addr_text);
if(mLineEdit.exec() != QDialog::Accepted)
return;
QString comment = mLineEdit.editText.replace('\r', "").replace('\n', "");
if(!DbgSetCommentAt(wVA, comment.toUtf8().constData()))
SimpleErrorBox(widgetparent(), tr("Error!"), tr("DbgSetCommentAt failed!"));
static bool easter = isEaster();
if(easter && comment.toLower() == "oep")
{
QFile file(":/icons/images/egg.wav");
if(file.open(QIODevice::ReadOnly))
{
QByteArray egg = file.readAll();
PlaySoundA(egg.data(), 0, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
}
}
GuiUpdateAllViews();
}
void CommonActions::setBookmarkSlot()
{
if(!DbgIsDebugging())
return;
duint wVA = mGetSelection();
bool result;
if(DbgGetBookmarkAt(wVA))
result = DbgSetBookmarkAt(wVA, false);
else
result = DbgSetBookmarkAt(wVA, true);
if(!result)
SimpleErrorBox(widgetparent(), tr("Error!"), tr("DbgSetBookmarkAt failed!"));
GuiUpdateAllViews();
}
void CommonActions::toggleInt3BPActionSlot()
{
if(!DbgIsDebugging())
return;
duint wVA = mGetSelection();
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
QString wCmd;
if((wBpType & bp_normal) == bp_normal)
{
wCmd = "bc " + ToPtrString(wVA);
}
else
{
if(DbgFunctions()->IsDepEnabled() && !DbgFunctions()->MemIsCodePage(wVA, false))
{
QMessageBox msgyn(QMessageBox::Warning, tr("Current address is not executable"),
tr("Setting software breakpoint here may result in crash. Do you really want to continue?"), QMessageBox::Yes | QMessageBox::No, (QWidget*)parent());
msgyn.setWindowIcon(DIcon("compile-warning.png"));
msgyn.setParent((QWidget*)parent(), Qt::Dialog);
msgyn.setWindowFlags(msgyn.windowFlags() & (~Qt::WindowContextHelpButtonHint));
if(msgyn.exec() == QMessageBox::No)
return;
}
wCmd = "bp " + ToPtrString(wVA);
}
DbgCmdExec(wCmd);
//emit Disassembly::repainted();
}
void CommonActions::editSoftBpActionSlot()
{
auto selection = mGetSelection();
if(selection == 0)
return;
BPXTYPE bpType = DbgGetBpxTypeAt(selection);
if((bpType & bp_hardware) == bp_hardware)
Breakpoints::editBP(bp_hardware, ToHexString(selection), dynamic_cast<QWidget*>(parent()));
else if((bpType & bp_normal) == bp_normal)
Breakpoints::editBP(bp_normal, ToHexString(selection), dynamic_cast<QWidget*>(parent()));
else
{
DbgCmdExecDirect(QString("bp %1").arg(ToHexString(selection))); //Blocking call
if(!Breakpoints::editBP(bp_normal, ToHexString(selection), dynamic_cast<QWidget*>(parent())))
Breakpoints::removeBP(bp_normal, selection);
}
}
void CommonActions::toggleHwBpActionSlot()
{
duint wVA = mGetSelection();
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
QString wCmd;
if((wBpType & bp_hardware) == bp_hardware)
{
wCmd = "bphwc " + ToPtrString(wVA);
}
else
{
wCmd = "bphws " + ToPtrString(wVA);
}
DbgCmdExec(wCmd);
}
void CommonActions::setHwBpOnSlot0ActionSlot()
{
setHwBpAt(mGetSelection(), 0);
}
void CommonActions::setHwBpOnSlot1ActionSlot()
{
setHwBpAt(mGetSelection(), 1);
}
void CommonActions::setHwBpOnSlot2ActionSlot()
{
setHwBpAt(mGetSelection(), 2);
}
void CommonActions::setHwBpOnSlot3ActionSlot()
{
setHwBpAt(mGetSelection(), 3);
}
void CommonActions::setHwBpAt(duint va, int slot)
{
int wI = 0;
int wSlotIndex = -1;
BPMAP wBPList;
QString wCmd = "";
DbgGetBpList(bp_hardware, &wBPList);
// Find index of slot slot in the list
for(wI = 0; wI < wBPList.count; wI++)
{
if(wBPList.bp[wI].slot == (unsigned short)slot)
{
wSlotIndex = wI;
break;
}
}
if(wSlotIndex < 0) // Slot not used
{
wCmd = "bphws " + ToPtrString(va);
DbgCmdExec(wCmd);
}
else // Slot used
{
wCmd = "bphwc " + ToPtrString((duint)(wBPList.bp[wSlotIndex].addr));
DbgCmdExec(wCmd);
Sleep(200);
wCmd = "bphws " + ToPtrString(va);
DbgCmdExec(wCmd);
}
if(wBPList.count)
BridgeFree(wBPList.bp);
}

View File

@ -0,0 +1,74 @@
#ifndef COMMONACTIONS_H
#define COMMONACTIONS_H
#include <QAction>
#include <functional>
#include "ActionHelpers.h"
class MenuBuilder;
class CommonActions : public QObject, public ActionHelperProxy
{
Q_OBJECT
public:
typedef enum
{
ActionDisasm = 1,
ActionDisasmMore = 1 << 1,
ActionDisasmDump = 1 << 2,
ActionDisasmDumpMore = 1 << 3,
ActionDisasmData = 1 << 4,
ActionDump = 1 << 5,
ActionDumpMore = 1 << 6,
ActionDumpN = 1 << 7,
ActionDumpData = 1 << 8,
ActionStackDump = 1 << 9,
ActionMemoryMap = 1 << 10,
ActionGraph = 1 << 11,
ActionBreakpoint = 1 << 12,
ActionMemoryBreakpoint = 1 << 13,
ActionMnemonicHelp = 1 << 14,
ActionLabel = 1 << 15,
ActionLabelMore = 1 << 16,
ActionComment = 1 << 17,
ActionCommentMore = 1 << 18,
ActionBookmark = 1 << 19,
ActionBookmarkMore = 1 << 20,
ActionFindref = 1 << 21,
ActionFindrefMore = 1 << 22,
ActionXref = 1 << 23,
ActionXrefMore = 1 << 24,
ActionNewOrigin = 1 << 25,
ActionNewThread = 1 << 26,
ActionWatch = 1 << 27
} CommonActionsList;
using GetSelectionFunc = std::function<duint()>;
explicit CommonActions(QWidget* parent, ActionHelperFuncs funcs, GetSelectionFunc getSelection);
void build(MenuBuilder* builder, int actions);
void build(MenuBuilder* builder, int actions, std::function<void(QList<std::pair<QString, duint>>&, CommonActionsList)> additionalAddress);
QAction* makeCommandAction(const QIcon & icon, const QString & text, const char* cmd, const char* shortcut);
public slots:
void followDisassemblySlot();
void setCommentSlot();
void setBookmarkSlot();
void toggleInt3BPActionSlot();
void editSoftBpActionSlot();
void toggleHwBpActionSlot();
void setHwBpOnSlot0ActionSlot();
void setHwBpOnSlot1ActionSlot();
void setHwBpOnSlot2ActionSlot();
void setHwBpOnSlot3ActionSlot();
void setHwBpAt(duint va, int slot);
private:
GetSelectionFunc mGetSelection;
QWidget* widgetparent();
};
#endif //COMMONACTIONS_H

View File

@ -81,6 +81,7 @@ SOURCES += \
Src/Imports.cpp \
Src/Tracer/TraceRegisters.cpp \
Src/Tracer/TraceWidget.cpp \
Src/Utils/CommonActions.cpp \
Src/main.cpp \
Src/Gui/MainWindow.cpp \
Src/Gui/CPUWidget.cpp \
@ -180,7 +181,6 @@ SOURCES += \
Src/Gui/LocalVarsView.cpp \
Src/Gui/MessagesBreakpoints.cpp \
Src/Gui/AboutDialog.cpp \
Src/Gui/BreakpointMenu.cpp \
Src/Gui/ComboBoxDialog.cpp \
Src/Utils/SymbolAutoCompleteModel.cpp \
Src/Tracer/TraceBrowser.cpp \
@ -201,6 +201,7 @@ HEADERS += \
Src/Gui/SystemBreakpointScriptDialog.h \
Src/Tracer/TraceRegisters.h \
Src/Tracer/TraceWidget.h \
Src/Utils/CommonActions.h \
Src/main.h \
Src/Gui/MainWindow.h \
Src/Gui/CPUWidget.h \
@ -304,7 +305,6 @@ HEADERS += \
Src/Gui/LocalVarsView.h \
Src/Gui/MessagesBreakpoints.h \
Src/Gui/AboutDialog.h \
Src/Gui/BreakpointMenu.h \
Src/Gui/ComboBoxDialog.h \
Src/Utils/VaHistory.h \
Src/Utils/SymbolAutoCompleteModel.h \

View File

@ -217,7 +217,7 @@ SOURCES += \
gui/Src/Gui/LocalVarsView.cpp \
gui/Src/Gui/MessagesBreakpoints.cpp \
gui/Src/Gui/AboutDialog.cpp \
gui/Src/Gui/BreakpointMenu.cpp \
gui/Src/Gui/CommonActions.cpp \
gui/Src/Utils/SymbolAutoCompleteModel.cpp \
gui/Src/Tracer/TraceBrowser.cpp \
gui/Src/Tracer/TraceFileReader.cpp \
@ -457,7 +457,7 @@ HEADERS += \
gui/Src/Gui/LocalVarsView.h \
gui/Src/Gui/MessagesBreakpoints.h \
gui/Src/Gui/AboutDialog.h \
gui/Src/Gui/BreakpointMenu.h \
gui/Src/Gui/CommonActions.h \
gui/Src/Utils/SymbolAutoCompleteModel.h \
gui/Src/Tracer/TraceBrowser.h \
gui/Src/Tracer/TraceFileReader.h \