Merge branch 'patch-1' of https://github.com/torusrxxx/x64dbg into torusrxxx-patch-1
# Conflicts: # src/dbg/threading.h # src/dbg/x64_dbg.cpp # src/dbg/x64_dbg_dbg.vcxproj.filters # src/gui/resource.qrc
This commit is contained in:
commit
504c794667
|
@ -823,6 +823,11 @@ BRIDGE_IMPEXP bool DbgXrefGet(duint addr, XREF_INFO* info)
|
|||
return true;
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP bool DbgGetWatchList(ListOf(WATCHINFO) list)
|
||||
{
|
||||
return !!_dbg_sendmessage(DBG_GET_WATCH_LIST, list, nullptr);
|
||||
}
|
||||
|
||||
// FIXME all
|
||||
BRIDGE_IMPEXP bool DbgIsRunLocked()
|
||||
{
|
||||
|
@ -1027,6 +1032,7 @@ BRIDGE_IMPEXP void GuiUpdateAllViews()
|
|||
GuiUpdateDisassemblyView();
|
||||
GuiUpdateBreakpointsView();
|
||||
GuiUpdateDumpView();
|
||||
GuiUpdateWatchView();
|
||||
GuiUpdateThreadView();
|
||||
GuiUpdateSideBar();
|
||||
GuiUpdatePatches();
|
||||
|
@ -1215,6 +1221,12 @@ BRIDGE_IMPEXP void GuiUpdateDumpView()
|
|||
_gui_sendmessage(GUI_UPDATE_DUMP_VIEW, 0, 0);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void GuiUpdateWatchView()
|
||||
{
|
||||
CHECK_GUI_UPDATE_DISABLED
|
||||
_gui_sendmessage(GUI_UPDATE_WATCH_VIEW, 0, 0);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void GuiUpdateMemoryView()
|
||||
{
|
||||
CHECK_GUI_UPDATE_DISABLED
|
||||
|
|
|
@ -65,6 +65,7 @@ BRIDGE_IMPEXP int BridgeGetDbgVersion();
|
|||
#define MAX_CONDITIONAL_TEXT_SIZE 256
|
||||
#define MAX_SCRIPT_LINE_SIZE 2048
|
||||
#define MAX_THREAD_NAME_SIZE 256
|
||||
#define MAX_WATCH_NAME_SIZE 256
|
||||
#define MAX_STRING_SIZE 512
|
||||
#define MAX_ERROR_SIZE 512
|
||||
#define RIGHTS_STRING_SIZE (sizeof("ERWCG") + 1)
|
||||
|
@ -214,6 +215,7 @@ typedef enum
|
|||
DBG_ARGUMENT_OVERLAPS, // param1=FUNCTION* info, param2=unused
|
||||
DBG_ARGUMENT_ADD, // param1=FUNCTION* info, param2=unused
|
||||
DBG_ARGUMENT_DEL, // param1=FUNCTION* info, param2=unused
|
||||
DBG_GET_WATCH_LIST // param1=ListOf(WATCHINFO), param2=unused
|
||||
} DBGMSG;
|
||||
|
||||
typedef enum
|
||||
|
@ -343,6 +345,25 @@ typedef enum
|
|||
enc_middle //middle of data
|
||||
} ENCODETYPE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TYPE_UINT, // unsigned integer
|
||||
TYPE_INT, // signed integer
|
||||
TYPE_FLOAT,// single precision floating point value
|
||||
TYPE_ASCII, // ascii string
|
||||
TYPE_UNICODE, // unicode string
|
||||
TYPE_INVALID // invalid watch expression or data type
|
||||
} WATCHVARTYPE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MODE_DISABLED, // watchdog is disabled
|
||||
MODE_ISTRUE, // alert if expression is not 0
|
||||
MODE_ISFALSE, // alert if expression is 0
|
||||
MODE_CHANGED, // alert if expression is changed
|
||||
MODE_UNCHANGED // alert if expression is not changed
|
||||
} WATCHDOGMODE;
|
||||
|
||||
//Debugger typedefs
|
||||
typedef MEMORY_SIZE VALUE_SIZE;
|
||||
typedef struct SYMBOLINFO_ SYMBOLINFO;
|
||||
|
@ -389,6 +410,18 @@ typedef struct
|
|||
BRIDGEBP* bp;
|
||||
} BPMAP;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char WatchName[MAX_WATCH_NAME_SIZE];
|
||||
char Expression[MAX_CONDITIONAL_EXPR_SIZE];
|
||||
unsigned int window;
|
||||
unsigned int id;
|
||||
WATCHVARTYPE varType;
|
||||
WATCHDOGMODE watchdogMode;
|
||||
duint value;
|
||||
bool watchdogTriggered;
|
||||
} WATCHINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
duint start; //OUT
|
||||
|
@ -806,6 +839,7 @@ BRIDGE_IMPEXP duint DbgGetEncodeSizeAt(duint addr, duint codesize);
|
|||
BRIDGE_IMPEXP bool DbgSetEncodeType(duint addr, duint size, ENCODETYPE type);
|
||||
BRIDGE_IMPEXP void DbgDelEncodeTypeRange(duint start, duint end);
|
||||
BRIDGE_IMPEXP void DbgDelEncodeTypeSegment(duint start);
|
||||
BRIDGE_IMPEXP bool DbgGetWatchList(ListOf(WATCHINFO) list);
|
||||
|
||||
//Gui defines
|
||||
#define GUI_PLUGIN_MENU 0
|
||||
|
@ -901,6 +935,7 @@ typedef enum
|
|||
GUI_UNREGISTER_SCRIPT_LANG, // param1=int id, param2=unused
|
||||
GUI_UPDATE_ARGUMENT_VIEW, // param1=unused, param2=unused
|
||||
GUI_FOCUS_VIEW, // param1=int hWindow, param2=unused
|
||||
GUI_UPDATE_WATCH_VIEW // param1=unused, param2=unused
|
||||
} GUIMSG;
|
||||
|
||||
//GUI Typedefs
|
||||
|
@ -977,6 +1012,7 @@ BRIDGE_IMPEXP void GuiReferenceSetCurrentTaskProgress(int progress, const char*
|
|||
BRIDGE_IMPEXP void GuiReferenceSetSearchStartCol(int col);
|
||||
BRIDGE_IMPEXP void GuiStackDumpAt(duint addr, duint csp);
|
||||
BRIDGE_IMPEXP void GuiUpdateDumpView();
|
||||
BRIDGE_IMPEXP void GuiUpdateWatchView();
|
||||
BRIDGE_IMPEXP void GuiUpdateThreadView();
|
||||
BRIDGE_IMPEXP void GuiUpdateMemoryView();
|
||||
BRIDGE_IMPEXP void GuiAddRecentFile(const char* file);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "handles.h"
|
||||
#include "../bridge/bridgelist.h"
|
||||
#include "tcpconnections.h"
|
||||
#include "watch.h"
|
||||
|
||||
static DBGFUNCTIONS _dbgfunctions;
|
||||
|
||||
|
@ -292,6 +293,7 @@ void dbgfunctionsinit()
|
|||
_dbgfunctions.ModSizeFromAddr = ModSizeFromAddr;
|
||||
_dbgfunctions.ModGetParty = ModGetParty;
|
||||
_dbgfunctions.ModSetParty = ModSetParty;
|
||||
_dbgfunctions.WatchIsWatchdogTriggered = WatchIsWatchdogTriggered;
|
||||
_dbgfunctions.Assemble = assemble;
|
||||
_dbgfunctions.PatchGet = _patchget;
|
||||
_dbgfunctions.PatchInRange = _patchinrange;
|
||||
|
|
|
@ -143,6 +143,7 @@ typedef bool(*ENUMTCPCONNECTIONS)(ListOf(TCPCONNECTIONINFO) connections);
|
|||
typedef duint(*GETDBGEVENTS)();
|
||||
typedef int(*MODGETPARTY)(duint base);
|
||||
typedef void(*MODSETPARTY)(duint base, int party);
|
||||
typedef bool(*WATCHISWATCHDOGTRIGGERED)(unsigned int id);
|
||||
|
||||
typedef struct DBGFUNCTIONS_
|
||||
{
|
||||
|
@ -196,6 +197,7 @@ typedef struct DBGFUNCTIONS_
|
|||
GETDBGEVENTS GetDbgEvents;
|
||||
MODGETPARTY ModGetParty;
|
||||
MODSETPARTY ModSetParty;
|
||||
WATCHISWATCHDOGTRIGGERED WatchIsWatchdogTriggered;
|
||||
} DBGFUNCTIONS;
|
||||
|
||||
#ifdef BUILD_DBG
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "xrefs.h"
|
||||
#include "encodemap.h"
|
||||
#include "argument.h"
|
||||
#include "watch.h"
|
||||
|
||||
static bool bOnlyCipAutoComments = false;
|
||||
|
||||
|
@ -1211,6 +1212,12 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa
|
|||
BookmarkDelRange((duint)param1, (duint)param2, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case DBG_GET_WATCH_LIST:
|
||||
{
|
||||
BridgeList<WATCHINFO>::CopyData((ListInfo*)param1, WatchGetList());
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "bookmark.h"
|
||||
#include "function.h"
|
||||
#include "loop.h"
|
||||
#include "watch.h"
|
||||
#include "commandline.h"
|
||||
#include "database.h"
|
||||
#include "threading.h"
|
||||
|
@ -59,6 +60,7 @@ void DbSave(DbLoadSaveType saveType)
|
|||
EncodeMapCacheSave(root);
|
||||
TraceRecord.saveToDb(root);
|
||||
BpCacheSave(root);
|
||||
WatchCacheSave(root);
|
||||
|
||||
//save notes
|
||||
char* text = nullptr;
|
||||
|
@ -196,6 +198,7 @@ void DbLoad(DbLoadSaveType loadType)
|
|||
EncodeMapCacheLoad(root);
|
||||
TraceRecord.loadFromDb(root);
|
||||
BpCacheLoad(root);
|
||||
WatchCacheLoad(root);
|
||||
|
||||
// Load notes
|
||||
const char* text = json_string_value(json_object_get(root, "notes"));
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "command.h"
|
||||
#include "database.h"
|
||||
#include "addrinfo.h"
|
||||
#include "watch.h"
|
||||
#include "thread.h"
|
||||
#include "plugin_loader.h"
|
||||
#include "breakpoint.h"
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include "stackinfo.h"
|
||||
#include "stringformat.h"
|
||||
#include "TraceRecord.h"
|
||||
#include "historycontext.h"
|
||||
#include "taskthread.h"
|
||||
|
||||
struct TraceCondition
|
||||
|
@ -35,7 +37,7 @@ struct TraceCondition
|
|||
explicit TraceCondition(String expression, duint maxCount)
|
||||
: condition(expression), steps(0), maxSteps(maxCount) {}
|
||||
|
||||
bool ContinueTrace()
|
||||
inline bool ContinueTrace()
|
||||
{
|
||||
steps++;
|
||||
if(steps >= maxSteps)
|
||||
|
@ -261,7 +263,6 @@ duint dbggetdbgevents()
|
|||
return InterlockedExchange(&DbgEvents, 0);
|
||||
}
|
||||
|
||||
|
||||
static DWORD WINAPI updateCallStackThread(duint ptr)
|
||||
{
|
||||
stackupdatecallstack(ptr);
|
||||
|
@ -496,6 +497,10 @@ void cbPauseBreakpoint()
|
|||
auto CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
DeleteBPX(CIP);
|
||||
DebugUpdateGuiSetStateAsync(CIP, true);
|
||||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
// Watchdog
|
||||
cbWatchdog(0, nullptr);
|
||||
//lock
|
||||
lock(WAITID_RUN);
|
||||
SetForegroundWindow(GuiGetWindowHandle());
|
||||
|
@ -608,6 +613,9 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
|
|||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
|
||||
// Watchdog
|
||||
cbWatchdog(0, nullptr);
|
||||
|
||||
if(*bp.logText && logCondition) //log
|
||||
{
|
||||
dprintf("%s\n", stringformatinline(bp.logText).c_str());
|
||||
|
@ -695,10 +703,15 @@ void cbRunToUserCodeBreakpoint(void* ExceptionAddress)
|
|||
RunToUserCodeBreakpoints.clear();
|
||||
lock(WAITID_RUN);
|
||||
EXCLUSIVE_RELEASE();
|
||||
// Watchdog
|
||||
cbWatchdog(0, nullptr);
|
||||
// Plugin callback
|
||||
PLUG_CB_PAUSEDEBUG pauseInfo;
|
||||
pauseInfo.reserved = nullptr;
|
||||
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
|
||||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
// Update GUI
|
||||
DebugUpdateGuiSetStateAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
|
||||
SetForegroundWindow(GuiGetWindowHandle());
|
||||
bSkipExceptions = false;
|
||||
|
@ -873,6 +886,8 @@ void cbStep()
|
|||
DebugUpdateGuiSetStateAsync(CIP, true);
|
||||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
// Watchdog
|
||||
cbWatchdog(0, nullptr);
|
||||
// Plugin interaction
|
||||
PLUG_CB_STEPPED stepInfo;
|
||||
stepInfo.reserved = 0;
|
||||
|
@ -895,6 +910,8 @@ static void cbRtrFinalStep()
|
|||
// Trace record
|
||||
_dbg_dbgtraceexecute(CIP);
|
||||
DebugUpdateGuiSetStateAsync(CIP, true);
|
||||
// Watchdog
|
||||
cbWatchdog(0, nullptr);
|
||||
//lock
|
||||
lock(WAITID_RUN);
|
||||
SetForegroundWindow(GuiGetWindowHandle());
|
||||
|
@ -907,6 +924,7 @@ static void cbRtrFinalStep()
|
|||
|
||||
void cbRtrStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
unsigned char ch = 0x90;
|
||||
duint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
MemRead(cip, &ch, 1);
|
||||
|
@ -915,11 +933,14 @@ void cbRtrStep()
|
|||
if(ch == 0xC3 || ch == 0xC2)
|
||||
cbRtrFinalStep();
|
||||
else
|
||||
{
|
||||
StepOver((void*)cbRtrStep);
|
||||
}
|
||||
}
|
||||
|
||||
void cbTOCNDStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
if(traceCondition && traceCondition->ContinueTrace())
|
||||
{
|
||||
if(bTraceRecordEnabledDuringTrace)
|
||||
|
@ -936,6 +957,7 @@ void cbTOCNDStep()
|
|||
|
||||
void cbTICNDStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
if(traceCondition && traceCondition->ContinueTrace())
|
||||
{
|
||||
if(bTraceRecordEnabledDuringTrace)
|
||||
|
@ -952,6 +974,7 @@ void cbTICNDStep()
|
|||
|
||||
void cbTIBTStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
// Trace record
|
||||
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(!traceCondition)
|
||||
|
@ -976,6 +999,7 @@ void cbTIBTStep()
|
|||
|
||||
void cbTOBTStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
// Trace record
|
||||
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(!traceCondition)
|
||||
|
@ -1000,6 +1024,7 @@ void cbTOBTStep()
|
|||
|
||||
void cbTIITStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
// Trace record
|
||||
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(!traceCondition)
|
||||
|
@ -1024,6 +1049,7 @@ void cbTIITStep()
|
|||
|
||||
void cbTOITStep()
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
// Trace record
|
||||
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(!traceCondition)
|
||||
|
@ -1179,6 +1205,8 @@ static void cbExitProcess(EXIT_PROCESS_DEBUG_INFO* ExitProcess)
|
|||
plugincbcall(CB_EXITPROCESS, &callbackInfo);
|
||||
//unload main module
|
||||
SafeSymUnloadModule64(fdProcessInfo->hProcess, pCreateProcessBase);
|
||||
//history
|
||||
HistoryClear();
|
||||
ModClear(); //clear all modules
|
||||
}
|
||||
|
||||
|
@ -1204,6 +1232,7 @@ static void cbCreateThread(CREATE_THREAD_DEBUG_INFO* CreateThread)
|
|||
|
||||
if(settingboolget("Events", "ThreadStart"))
|
||||
{
|
||||
HistoryClear();
|
||||
//update memory map
|
||||
MemUpdateMap();
|
||||
//update GUI
|
||||
|
@ -1237,6 +1266,7 @@ static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread)
|
|||
callbackInfo.ExitThread = ExitThread;
|
||||
callbackInfo.dwThreadId = dwThreadId;
|
||||
plugincbcall(CB_EXITTHREAD, &callbackInfo);
|
||||
HistoryClear();
|
||||
ThreadExit(dwThreadId);
|
||||
dprintf("Thread %X exit\n", dwThreadId);
|
||||
|
||||
|
@ -1254,7 +1284,7 @@ static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread)
|
|||
}
|
||||
}
|
||||
|
||||
static void cbSystemBreakpoint(void* ExceptionData)
|
||||
static void cbSystemBreakpoint(void* ExceptionData) // TODO: System breakpoint event shouldn't be dropped
|
||||
{
|
||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||
|
||||
|
@ -2230,6 +2260,7 @@ static void debugLoopFunction(void* lpParameter, bool attach)
|
|||
DbClose();
|
||||
ModClear();
|
||||
ThreadClear();
|
||||
WatchClear();
|
||||
TraceRecord.clear();
|
||||
GuiSetDebugState(stopped);
|
||||
GuiUpdateAllViews();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
@brief Implements the debugger commands class.
|
||||
*/
|
||||
|
||||
#include "x64_dbg.h"
|
||||
#include "debugger_commands.h"
|
||||
#include "jit.h"
|
||||
#include "console.h"
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include "label.h"
|
||||
#include "bookmark.h"
|
||||
#include "function.h"
|
||||
#include "historycontext.h"
|
||||
#include "taskthread.h"
|
||||
|
||||
static bool bScyllaLoaded = false;
|
||||
|
@ -116,6 +118,8 @@ CMDRESULT cbDebugStop(int argc, char* argv[])
|
|||
// HACK: TODO: Don't kill script on debugger ending a process
|
||||
//scriptreset(); //reset the currently-loaded script
|
||||
StopDebug();
|
||||
//history
|
||||
HistoryClear();
|
||||
while(waitislocked(WAITID_STOP)) //custom waiting
|
||||
{
|
||||
unlock(WAITID_RUN);
|
||||
|
@ -124,6 +128,7 @@ CMDRESULT cbDebugStop(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
// Run
|
||||
CMDRESULT cbDebugRun(int argc, char* argv[])
|
||||
{
|
||||
// Don't "run" twice if the program is already running
|
||||
|
@ -139,8 +144,16 @@ CMDRESULT cbDebugRun(int argc, char* argv[])
|
|||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
// Run and clear history
|
||||
CMDRESULT cbDebugRun2(int argc, char* argv[])
|
||||
{
|
||||
HistoryClear();
|
||||
return cbDebugRun(argc, argv);
|
||||
}
|
||||
|
||||
CMDRESULT cbDebugErun(int argc, char* argv[])
|
||||
{
|
||||
HistoryClear();
|
||||
if(!dbgisrunning())
|
||||
dbgsetskipexceptions(true);
|
||||
else
|
||||
|
@ -715,16 +728,16 @@ CMDRESULT cbDebugSetBPGoto(int argc, char* argv[])
|
|||
}
|
||||
char cmd[deflen];
|
||||
_snprintf(cmd, sizeof(cmd), "SetBreakpointCondition %s, 0", argv[1]);
|
||||
if(!DbgCmdExecDirect(cmd))
|
||||
if(!_dbg_dbgcmddirectexec(cmd))
|
||||
return STATUS_ERROR;
|
||||
_snprintf(cmd, sizeof(cmd), "SetBreakpointCommand %s, \"CIP=%s\"", argv[1], argv[2]);
|
||||
if(!DbgCmdExecDirect(cmd))
|
||||
if(!_dbg_dbgcmddirectexec(cmd))
|
||||
return STATUS_ERROR;
|
||||
_snprintf(cmd, sizeof(cmd), "SetBreakpointCommandCondition %s, 1", argv[1]);
|
||||
if(!DbgCmdExecDirect(cmd))
|
||||
if(!_dbg_dbgcmddirectexec(cmd))
|
||||
return STATUS_ERROR;
|
||||
_snprintf(cmd, sizeof(cmd), "SetBreakpointFastResume %s, 0", argv[1]);
|
||||
if(!DbgCmdExecDirect(cmd))
|
||||
if(!_dbg_dbgcmddirectexec(cmd))
|
||||
return STATUS_ERROR;
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
@ -1205,6 +1218,8 @@ CMDRESULT cbDebugBplist(int argc, char* argv[])
|
|||
CMDRESULT cbDebugStepInto(int argc, char* argv[])
|
||||
{
|
||||
StepInto((void*)cbStep);
|
||||
// History
|
||||
HistoryAdd();
|
||||
dbgsetstepping(true);
|
||||
return cbDebugRun(argc, argv);
|
||||
}
|
||||
|
@ -1218,6 +1233,8 @@ CMDRESULT cbDebugeStepInto(int argc, char* argv[])
|
|||
CMDRESULT cbDebugStepOver(int argc, char* argv[])
|
||||
{
|
||||
StepOver((void*)cbStep);
|
||||
// History
|
||||
HistoryAdd();
|
||||
dbgsetstepping(true);
|
||||
return cbDebugRun(argc, argv);
|
||||
}
|
||||
|
@ -1235,6 +1252,7 @@ CMDRESULT cbDebugSingleStep(int argc, char* argv[])
|
|||
if(!valfromstring(argv[1], &stepcount))
|
||||
stepcount = 1;
|
||||
SingleStep((DWORD)stepcount, (void*)cbStep);
|
||||
HistoryClear();
|
||||
dbgsetstepping(true);
|
||||
return cbDebugRun(argc, argv);
|
||||
}
|
||||
|
@ -1272,6 +1290,7 @@ CMDRESULT cbDebugDisasm(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugRtr(int argc, char* argv[])
|
||||
{
|
||||
HistoryClear();
|
||||
StepOver((void*)cbRtrStep);
|
||||
cbDebugRun(argc, argv);
|
||||
return STATUS_CONTINUE;
|
||||
|
@ -1285,6 +1304,7 @@ CMDRESULT cbDebugeRtr(int argc, char* argv[])
|
|||
|
||||
CMDRESULT cbDebugRunToParty(int argc, char* argv[])
|
||||
{
|
||||
HistoryClear();
|
||||
EXCLUSIVE_ACQUIRE(LockRunToUserCode);
|
||||
std::vector<MODINFO> AllModules;
|
||||
ModGetList(AllModules);
|
||||
|
@ -1339,6 +1359,7 @@ static CMDRESULT cbDebugConditionalTrace(void* callBack, bool stepOver, int argc
|
|||
dprintf("Invalid expression \"%s\"\n", argv[1]);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
HistoryClear();
|
||||
if(stepOver)
|
||||
StepOver(callBack);
|
||||
else
|
||||
|
@ -1754,6 +1775,7 @@ CMDRESULT cbDebugSwitchthread(int argc, char* argv[])
|
|||
}
|
||||
//switch thread
|
||||
hActiveThread = ThreadGetHandle((DWORD)threadid);
|
||||
HistoryClear();
|
||||
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
|
||||
dputs("Thread switched!");
|
||||
return STATUS_CONTINUE;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
CMDRESULT cbDebugInit(int argc, char* argv[]);
|
||||
CMDRESULT cbDebugStop(int argc, char* argv[]);
|
||||
CMDRESULT cbDebugRun(int argc, char* argv[]);
|
||||
CMDRESULT cbDebugRun2(int argc, char* argv[]);
|
||||
CMDRESULT cbDebugErun(int argc, char* argv[]);
|
||||
CMDRESULT cbDebugSetBPXOptions(int argc, char* argv[]);
|
||||
CMDRESULT cbDebugSetBPX(int argc, char* argv[]);
|
||||
|
|
|
@ -114,7 +114,7 @@ duint disasmnext(unsigned char* data, duint base, duint size, duint ip, int n)
|
|||
const char* disasmtext(duint addr)
|
||||
{
|
||||
unsigned char buffer[MAX_DISASM_BUFFER] = "";
|
||||
DbgMemRead(addr, buffer, sizeof(buffer));
|
||||
MemRead(addr, buffer, sizeof(buffer));
|
||||
Capstone cp;
|
||||
static char instruction[64] = "";
|
||||
if(!cp.Disassemble(addr, buffer))
|
||||
|
@ -169,17 +169,17 @@ static void HandleCapstoneOperand(Capstone & cp, int opindex, DISASM_ARG* arg)
|
|||
switch(op.size)
|
||||
{
|
||||
case 1:
|
||||
DbgMemRead(value, (unsigned char*)&arg->memvalue, 1);
|
||||
MemRead(value, (unsigned char*)&arg->memvalue, 1);
|
||||
break;
|
||||
case 2:
|
||||
DbgMemRead(value, (unsigned char*)&arg->memvalue, 2);
|
||||
MemRead(value, (unsigned char*)&arg->memvalue, 2);
|
||||
break;
|
||||
case 4:
|
||||
DbgMemRead(value, (unsigned char*)&arg->memvalue, 4);
|
||||
MemRead(value, (unsigned char*)&arg->memvalue, 4);
|
||||
break;
|
||||
#ifdef _WIN64
|
||||
case 8:
|
||||
DbgMemRead(value, (unsigned char*)&arg->memvalue, 8);
|
||||
MemRead(value, (unsigned char*)&arg->memvalue, 8);
|
||||
break;
|
||||
#endif //_WIN64
|
||||
}
|
||||
|
@ -236,8 +236,10 @@ void disasmget(duint addr, DISASM_INSTR* instr)
|
|||
return;
|
||||
}
|
||||
unsigned char buffer[MAX_DISASM_BUFFER] = "";
|
||||
DbgMemRead(addr, buffer, sizeof(buffer));
|
||||
disasmget(buffer, addr, instr);
|
||||
if(MemRead(addr, buffer, sizeof(buffer)))
|
||||
disasmget(buffer, addr, instr);
|
||||
else
|
||||
memset(instr, 0, sizeof(DISASM_INSTR)); // Buffer overflow
|
||||
}
|
||||
|
||||
void disasmprint(duint addr)
|
||||
|
@ -369,4 +371,4 @@ int disasmgetsize(duint addr)
|
|||
if(!MemRead(addr, data, sizeof(data)))
|
||||
return 1;
|
||||
return disasmgetsize(addr, (unsigned char*)data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
#include "historycontext.h"
|
||||
#include "disasm_helper.h"
|
||||
#include "memory.h"
|
||||
#include "console.h"
|
||||
#include "watch.h"
|
||||
#include "_exports.h"
|
||||
|
||||
duint HistoryMaxCount = 4096;
|
||||
std::deque<HistoryContext> history;
|
||||
|
||||
//This will capture the current instruction
|
||||
HistoryContext::HistoryContext()
|
||||
{
|
||||
DISASM_INSTR instruction;
|
||||
if(GetFullContextDataEx(hActiveThread, ®isters) && MemIsValidReadPtr(registers.cip))
|
||||
{
|
||||
disasmget(registers.cip, &instruction);
|
||||
if(!(memcmp(instruction.instruction, "nop ", 4) == 0 || memcmp(instruction.instruction, "lea ", 4) == 0))
|
||||
// do not process the memory operands of these instructions, because these instructions do not write to the memory.
|
||||
{
|
||||
if(memcmp(instruction.instruction, "push", 4) == 0 || memcmp(instruction.instruction, "call", 4) == 0)
|
||||
// push and call instruction : save previous content on the stack
|
||||
{
|
||||
ChangedData olddata;
|
||||
olddata.addr = registers.csp - sizeof(duint);
|
||||
MemRead(olddata.addr, (unsigned char*)olddata.oldvalue, sizeof(duint));
|
||||
ChangedLocation.push_back(olddata);
|
||||
}
|
||||
// TODO: FPU/SSE instructions, ENTER instruction, and possibly other instructions.
|
||||
// These instructions can write more than sizeof(duint) bytes.
|
||||
for(int i = 0; i < instruction.argcount; i++)
|
||||
{
|
||||
DISASM_ARG & arg = instruction.arg[i];
|
||||
if(arg.type == DISASM_ARGTYPE::arg_memory)
|
||||
{
|
||||
ChangedData olddata;
|
||||
olddata.addr = arg.value;
|
||||
memcpy(olddata.oldvalue, &arg.memvalue, sizeof(arg.memvalue));
|
||||
ChangedLocation.push_back(olddata);
|
||||
}
|
||||
}
|
||||
}
|
||||
invalid = false;
|
||||
}
|
||||
else
|
||||
invalid = true;
|
||||
}
|
||||
|
||||
void HistoryContext::restore()
|
||||
{
|
||||
if(!invalid)
|
||||
{
|
||||
for(auto & i : ChangedLocation)
|
||||
MemWrite(i.addr, i.oldvalue, sizeof(duint));
|
||||
SetFullContextDataEx(hActiveThread, ®isters);
|
||||
cbWatchdog(0, nullptr);
|
||||
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
HistoryClear();
|
||||
dputs("Cannot restore last instruction.");
|
||||
}
|
||||
}
|
||||
|
||||
HistoryContext::~HistoryContext()
|
||||
{
|
||||
}
|
||||
|
||||
void HistoryAdd()
|
||||
{
|
||||
if(history.size() > HistoryMaxCount)
|
||||
history.pop_front();
|
||||
history.emplace_back();
|
||||
}
|
||||
|
||||
void HistoryRestore()
|
||||
{
|
||||
if(!history.empty())
|
||||
{
|
||||
history.back().restore();
|
||||
history.pop_back();
|
||||
}
|
||||
else
|
||||
dputs("History record is empty");
|
||||
}
|
||||
|
||||
bool HistoryIsEmpty()
|
||||
{
|
||||
return history.empty();
|
||||
}
|
||||
|
||||
void HistoryClear()
|
||||
{
|
||||
history.clear();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef HISTORYCONTEXT_H
|
||||
#define HISTORYCONTEXT_H
|
||||
|
||||
#include "debugger.h"
|
||||
#include <capstone_wrapper.h>
|
||||
|
||||
/**
|
||||
* @brief The class used to hold history context.
|
||||
**/
|
||||
class HistoryContext
|
||||
{
|
||||
public:
|
||||
HistoryContext();
|
||||
~HistoryContext();
|
||||
HistoryContext(const HistoryContext & copy);
|
||||
|
||||
void restore();
|
||||
|
||||
protected:
|
||||
TITAN_ENGINE_CONTEXT_t registers;
|
||||
struct ChangedData
|
||||
{
|
||||
duint addr;
|
||||
char oldvalue[32];
|
||||
};
|
||||
std::vector<ChangedData> ChangedLocation;
|
||||
bool invalid;
|
||||
};
|
||||
|
||||
void HistoryAdd();
|
||||
void HistoryRestore();
|
||||
void HistoryClear();
|
||||
bool HistoryIsEmpty();
|
||||
#endif //HISTORY_CONTEXT_H
|
|
@ -41,6 +41,7 @@
|
|||
#include "exhandlerinfo.h"
|
||||
#include "symbolinfo.h"
|
||||
#include "argument.h"
|
||||
#include "historycontext.h"
|
||||
|
||||
static bool bRefinit = false;
|
||||
static int maxFindResults = 5000;
|
||||
|
@ -2746,3 +2747,10 @@ CMDRESULT cbInstrExhandlers(int argc, char* argv[])
|
|||
dputs("Failed to get UnhandledExceptionFilter (loaded symbols for kernelbase.dll?)");
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbInstrInstrUndo(int argc, char* argv[])
|
||||
{
|
||||
HistoryRestore();
|
||||
GuiUpdateAllViews();
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
|
|
@ -98,5 +98,6 @@ CMDRESULT cbInstrBriefcheck(int argc, char* argv[]);
|
|||
CMDRESULT cbInstrDisableGuiUpdate(int argc, char* argv[]);
|
||||
CMDRESULT cbInstrEnableGuiUpdate(int argc, char* argv[]);
|
||||
CMDRESULT cbInstrExhandlers(int argc, char* argv[]);
|
||||
CMDRESULT cbInstrInstrUndo(int argc, char* argv[]);
|
||||
|
||||
#endif // _INSTRUCTION_H
|
||||
|
|
|
@ -62,6 +62,7 @@ enum SectionLock
|
|||
LockEncodeMaps,
|
||||
LockCallstackCache,
|
||||
LockRunToUserCode,
|
||||
LockWatch,
|
||||
LockExpressionFunctions,
|
||||
|
||||
// Number of elements in this enumeration. Must always be the last
|
||||
|
|
|
@ -0,0 +1,553 @@
|
|||
#include "watch.h"
|
||||
#include "console.h"
|
||||
#include "variable.h"
|
||||
#include "value.h"
|
||||
#include "threading.h"
|
||||
#include "debugger.h"
|
||||
#include "symbolinfo.h"
|
||||
#include <Windows.h>
|
||||
|
||||
std::map<unsigned int, WatchExpr*> watchexpr;
|
||||
unsigned int idCounter = 1;
|
||||
|
||||
WatchExpr::WatchExpr(const char* name, const char* expression, WATCHVARTYPE type) : expr(expression), varType(type), currValue(0), haveCurrValue(false), watchdogTriggered(false), watchWindow(0)
|
||||
{
|
||||
if(!expr.IsValidExpression())
|
||||
varType = WATCHVARTYPE::TYPE_INVALID;
|
||||
strcpy_s(this->WatchName, name);
|
||||
}
|
||||
|
||||
duint WatchExpr::getIntValue()
|
||||
{
|
||||
duint origVal = currValue;
|
||||
if(varType == WATCHVARTYPE::TYPE_UINT || varType == WATCHVARTYPE::TYPE_INT || varType == WATCHVARTYPE::TYPE_ASCII || varType == WATCHVARTYPE::TYPE_UNICODE)
|
||||
{
|
||||
duint val;
|
||||
bool ok = expr.Calculate(val, varType == WATCHVARTYPE::TYPE_INT, false);
|
||||
if(ok)
|
||||
{
|
||||
currValue = val;
|
||||
haveCurrValue = true;
|
||||
if(getType() != WATCHVARTYPE::TYPE_INVALID)
|
||||
{
|
||||
switch(getWatchdogMode())
|
||||
{
|
||||
default:
|
||||
case WATCHDOGMODE::MODE_DISABLED:
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_ISTRUE:
|
||||
if(currValue != 0)
|
||||
{
|
||||
duint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
dprintf("Watchdog %s (expression \"%s\") is triggered at " fhex " ! Original value: " fhex ", New value: " fhex "\n", WatchName, getExpr().c_str(), cip, origVal, currValue);
|
||||
watchdogTriggered = 1;
|
||||
}
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_ISFALSE:
|
||||
if(currValue == 0)
|
||||
{
|
||||
duint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
dprintf("Watchdog %s (expression \"%s\") is triggered at " fhex " ! Original value: " fhex ", New value: " fhex "\n", WatchName, getExpr().c_str(), cip, origVal, currValue);
|
||||
watchdogTriggered = 1;
|
||||
}
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_CHANGED:
|
||||
if(currValue != origVal || !haveCurrValue)
|
||||
{
|
||||
duint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
dprintf("Watchdog %s (expression \"%s\") is triggered at " fhex " ! Original value: " fhex ", New value: " fhex "\n", WatchName, getExpr().c_str(), cip, origVal, currValue);
|
||||
watchdogTriggered = 1;
|
||||
}
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_UNCHANGED:
|
||||
if(currValue == origVal || !haveCurrValue)
|
||||
{
|
||||
duint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
dprintf("Watchdog %s (expression \"%s\") is triggered at " fhex " ! Original value: " fhex ", New value: " fhex "\n", WatchName, getExpr().c_str(), cip, origVal, currValue);
|
||||
watchdogTriggered = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
currValue = 0;
|
||||
haveCurrValue = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WatchExpr::modifyExpr(const char* expression, WATCHVARTYPE type)
|
||||
{
|
||||
ExpressionParser b(expression);
|
||||
if(b.IsValidExpression())
|
||||
{
|
||||
expr = b;
|
||||
varType = type;
|
||||
currValue = 0;
|
||||
haveCurrValue = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void WatchExpr::modifyName(const char* newName)
|
||||
{
|
||||
strcpy_s(WatchName, newName);
|
||||
}
|
||||
|
||||
// Global functions
|
||||
// Clear all watch
|
||||
void WatchClear()
|
||||
{
|
||||
if(!watchexpr.empty())
|
||||
{
|
||||
for(auto i : watchexpr)
|
||||
delete i.second;
|
||||
watchexpr.clear();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int WatchAddExprUnlocked(const char* expr, WATCHVARTYPE type)
|
||||
{
|
||||
unsigned int newid = InterlockedExchangeAdd(&idCounter, 1);
|
||||
char DefaultName[MAX_WATCH_NAME_SIZE];
|
||||
sprintf_s(DefaultName, "Watch %u", newid);
|
||||
auto temp = watchexpr.emplace(std::make_pair(newid, new WatchExpr(DefaultName, expr, type)));
|
||||
return temp.second ? newid : 0;
|
||||
}
|
||||
|
||||
unsigned int WatchAddExpr(const char* expr, WATCHVARTYPE type)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
unsigned int id = WatchAddExprUnlocked(expr, type);
|
||||
EXCLUSIVE_RELEASE();
|
||||
GuiUpdateWatchView();
|
||||
return id;
|
||||
}
|
||||
|
||||
bool WatchModifyExpr(unsigned int id, const char* expr, WATCHVARTYPE type)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
{
|
||||
bool success = obj->second->modifyExpr(expr, type);
|
||||
EXCLUSIVE_RELEASE();
|
||||
GuiUpdateWatchView();
|
||||
return success;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void WatchModifyNameUnlocked(unsigned int id, const char* newName)
|
||||
{
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
{
|
||||
obj->second->modifyName(newName);
|
||||
}
|
||||
}
|
||||
|
||||
void WatchModifyName(unsigned int id, const char* newName)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
WatchModifyNameUnlocked(id, newName);
|
||||
EXCLUSIVE_RELEASE();
|
||||
GuiUpdateWatchView();
|
||||
}
|
||||
|
||||
void WatchDelete(unsigned int id)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
auto x = watchexpr.find(id);
|
||||
if(x != watchexpr.end())
|
||||
{
|
||||
delete x->second;
|
||||
watchexpr.erase(x);
|
||||
EXCLUSIVE_RELEASE();
|
||||
GuiUpdateWatchView();
|
||||
}
|
||||
}
|
||||
|
||||
void WatchSetWatchdogModeUnlocked(unsigned int id, WATCHDOGMODE mode)
|
||||
{
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
obj->second->setWatchdogMode(mode);
|
||||
}
|
||||
|
||||
void WatchSetWatchdogMode(unsigned int id, WATCHDOGMODE mode)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
WatchSetWatchdogModeUnlocked(id, mode);
|
||||
EXCLUSIVE_RELEASE();
|
||||
GuiUpdateWatchView();
|
||||
}
|
||||
|
||||
WATCHDOGMODE WatchGetWatchdogEnabled(unsigned int id)
|
||||
{
|
||||
SHARED_ACQUIRE(LockWatch);
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
return obj->second->getWatchdogMode();
|
||||
else
|
||||
return WATCHDOGMODE::MODE_DISABLED;
|
||||
}
|
||||
|
||||
duint WatchGetUnsignedValue(unsigned int id)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
return obj->second->getIntValue();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
WATCHVARTYPE WatchGetType(unsigned int id)
|
||||
{
|
||||
SHARED_ACQUIRE(LockWatch);
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
return obj->second->getType();
|
||||
else
|
||||
return WATCHVARTYPE::TYPE_INVALID;
|
||||
}
|
||||
|
||||
unsigned int WatchGetWindow(unsigned int id)
|
||||
{
|
||||
SHARED_ACQUIRE(LockWatch);
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
return obj->second->watchWindow;
|
||||
else
|
||||
return WATCHVARTYPE::TYPE_INVALID;
|
||||
}
|
||||
|
||||
bool WatchIsWatchdogTriggered(unsigned int id)
|
||||
{
|
||||
SHARED_ACQUIRE(LockWatch);
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
return obj->second->watchdogTriggered;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void WatchSetWindow(unsigned int id, unsigned int window)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
auto obj = watchexpr.find(id);
|
||||
if(obj != watchexpr.end())
|
||||
obj->second->watchWindow = window;
|
||||
EXCLUSIVE_RELEASE();
|
||||
GuiUpdateWatchView();
|
||||
}
|
||||
|
||||
std::vector<WATCHINFO> WatchGetList()
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
std::vector<WATCHINFO> watchList;
|
||||
for(auto & i : watchexpr)
|
||||
{
|
||||
WATCHINFO info;
|
||||
info.value = i.second->getCurrIntValue();
|
||||
strcpy_s(info.WatchName, i.second->getName());
|
||||
strcpy_s(info.Expression, i.second->getExpr().c_str());
|
||||
info.varType = i.second->getType();
|
||||
info.id = i.first;
|
||||
info.watchdogMode = i.second->getWatchdogMode();
|
||||
info.watchdogTriggered = i.second->watchdogTriggered;
|
||||
info.window = i.second->watchWindow;
|
||||
watchList.push_back(info);
|
||||
}
|
||||
return watchList;
|
||||
}
|
||||
|
||||
// Initialize id counter so that it begin with a unused value
|
||||
void WatchInitIdCounter()
|
||||
{
|
||||
idCounter = 1;
|
||||
for(auto i : watchexpr)
|
||||
if(i.first > idCounter)
|
||||
idCounter = i.first + 1;
|
||||
}
|
||||
|
||||
void WatchCacheSave(JSON root)
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
JSON watchroot = json_array();
|
||||
for(auto i : watchexpr)
|
||||
{
|
||||
if(i.second->getType() == WATCHVARTYPE::TYPE_INVALID)
|
||||
continue;
|
||||
JSON watchitem = json_object();
|
||||
json_object_set_new(watchitem, "Expression", json_string(i.second->getExpr().c_str()));
|
||||
json_object_set_new(watchitem, "Name", json_string(i.second->getName()));
|
||||
switch(i.second->getType())
|
||||
{
|
||||
case WATCHVARTYPE::TYPE_INT:
|
||||
json_object_set_new(watchitem, "DataType", json_string("int"));
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_UINT:
|
||||
json_object_set_new(watchitem, "DataType", json_string("uint"));
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_FLOAT:
|
||||
json_object_set_new(watchitem, "DataType", json_string("float"));
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_ASCII:
|
||||
json_object_set_new(watchitem, "DataType", json_string("ascii"));
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_UNICODE:
|
||||
json_object_set_new(watchitem, "DataType", json_string("unicode"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(i.second->getWatchdogMode())
|
||||
{
|
||||
case WATCHDOGMODE::MODE_DISABLED:
|
||||
json_object_set_new(watchitem, "WatchdogMode", json_string("Disabled"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_CHANGED:
|
||||
json_object_set_new(watchitem, "WatchdogMode", json_string("Changed"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_UNCHANGED:
|
||||
json_object_set_new(watchitem, "WatchdogMode", json_string("Unchanged"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_ISTRUE:
|
||||
json_object_set_new(watchitem, "WatchdogMode", json_string("IsTrue"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_ISFALSE:
|
||||
json_object_set_new(watchitem, "WatchdogMode", json_string("IsFalse"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
json_array_append_new(watchroot, watchitem);
|
||||
}
|
||||
json_object_set_new(root, "Watch", watchroot);
|
||||
}
|
||||
|
||||
void WatchCacheLoad(JSON root)
|
||||
{
|
||||
WatchClear();
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
JSON watchroot = json_object_get(root, "Watch");
|
||||
unsigned int i;
|
||||
JSON val;
|
||||
if(!watchroot)
|
||||
return;
|
||||
|
||||
json_array_foreach(watchroot, i, val)
|
||||
{
|
||||
const char* expr = json_string_value(json_object_get(val, "Expression"));
|
||||
if(!expr)
|
||||
continue;
|
||||
const char* datatype = json_string_value(json_object_get(val, "DataType"));
|
||||
if(!datatype)
|
||||
datatype = "uint";
|
||||
const char* WatchdogMode = json_string_value(json_object_get(val, "WatchdogMode"));
|
||||
if(!WatchdogMode)
|
||||
WatchdogMode = "Disabled";
|
||||
const char* watchname = json_string_value(json_object_get(val, "Name"));
|
||||
if(!watchname)
|
||||
watchname = "Watch";
|
||||
WATCHVARTYPE varType;
|
||||
WATCHDOGMODE watchdog_mode;
|
||||
if(strcmp(datatype, "int") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_INT;
|
||||
else if(strcmp(datatype, "uint") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_UINT;
|
||||
else if(strcmp(datatype, "float") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_FLOAT;
|
||||
else if(strcmp(datatype, "ascii") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_ASCII;
|
||||
else if(strcmp(datatype, "unicode") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_UNICODE;
|
||||
else
|
||||
continue;
|
||||
if(strcmp(WatchdogMode, "Disabled") == 0)
|
||||
watchdog_mode = WATCHDOGMODE::MODE_DISABLED;
|
||||
else if(strcmp(WatchdogMode, "Changed") == 0)
|
||||
watchdog_mode = WATCHDOGMODE::MODE_CHANGED;
|
||||
else if(strcmp(WatchdogMode, "Unchanged") == 0)
|
||||
watchdog_mode = WATCHDOGMODE::MODE_UNCHANGED;
|
||||
else if(strcmp(WatchdogMode, "IsTrue") == 0)
|
||||
watchdog_mode = WATCHDOGMODE::MODE_ISTRUE;
|
||||
else if(strcmp(WatchdogMode, "IsFalse") == 0)
|
||||
watchdog_mode = WATCHDOGMODE::MODE_ISFALSE;
|
||||
else
|
||||
continue;
|
||||
unsigned int id = WatchAddExprUnlocked(expr, varType);
|
||||
WatchModifyNameUnlocked(id, watchname);
|
||||
WatchSetWatchdogModeUnlocked(id, watchdog_mode);
|
||||
}
|
||||
WatchInitIdCounter(); // Initialize id counter so that it begin with a unused value
|
||||
}
|
||||
|
||||
CMDRESULT cbWatchdog(int argc, char* argv[])
|
||||
{
|
||||
EXCLUSIVE_ACQUIRE(LockWatch);
|
||||
bool watchdogTriggered = false;
|
||||
for(auto j = watchexpr.begin(); j != watchexpr.end(); j++)
|
||||
{
|
||||
std::pair<unsigned int, WatchExpr*> i = *j;
|
||||
i.second->watchdogTriggered = false;
|
||||
duint intVal = i.second->getIntValue();
|
||||
watchdogTriggered |= i.second->watchdogTriggered;
|
||||
}
|
||||
EXCLUSIVE_RELEASE();
|
||||
if(watchdogTriggered)
|
||||
GuiUpdateWatchView();
|
||||
varset("$result", watchdogTriggered ? 1 : 0, false);
|
||||
if(watchdogTriggered)
|
||||
varset("$breakcondition", 1, false);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbAddWatch(int argc, char* argv[])
|
||||
{
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("No enough arguments for addwatch\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
WATCHVARTYPE newtype = WATCHVARTYPE::TYPE_UINT;
|
||||
if(argc > 2)
|
||||
{
|
||||
if(_stricmp(argv[2], "uint") == 0)
|
||||
newtype = WATCHVARTYPE::TYPE_UINT;
|
||||
else if(_stricmp(argv[2], "int") == 0)
|
||||
newtype = WATCHVARTYPE::TYPE_INT;
|
||||
else if(_stricmp(argv[2], "float") == 0)
|
||||
newtype = WATCHVARTYPE::TYPE_FLOAT;
|
||||
else if(_stricmp(argv[2], "ascii") == 0)
|
||||
newtype = WATCHVARTYPE::TYPE_ASCII;
|
||||
else if(_stricmp(argv[2], "unicode") == 0)
|
||||
newtype = WATCHVARTYPE::TYPE_UNICODE;
|
||||
}
|
||||
unsigned int newid = WatchAddExpr(argv[1], newtype);
|
||||
varset("$result", newid, false);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbDelWatch(int argc, char* argv[])
|
||||
{
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("No enough arguments for delwatch\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
duint id;
|
||||
bool ok = valfromstring(argv[1], &id);
|
||||
if(!ok)
|
||||
{
|
||||
dputs("Error expression in argument 1.\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
WatchDelete((unsigned int)id);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
CMDRESULT cbSetWatchName(int argc, char* argv[])
|
||||
{
|
||||
if(argc < 3)
|
||||
{
|
||||
dputs("No enough arguments for SetWatchName");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
duint id;
|
||||
bool ok = valfromstring(argv[1], &id);
|
||||
if(ok)
|
||||
{
|
||||
WatchModifyName((unsigned int)id, argv[2]);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dputs("Error expression in argument 1.\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
CMDRESULT cbSetWatchExpression(int argc, char* argv[])
|
||||
{
|
||||
if(argc < 3)
|
||||
{
|
||||
dputs("No enough arguments for SetWatchExpression");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
duint id;
|
||||
bool ok = valfromstring(argv[1], &id);
|
||||
if(ok)
|
||||
{
|
||||
WATCHVARTYPE varType;
|
||||
if(argc > 3)
|
||||
{
|
||||
if(_stricmp(argv[3], "uint") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_UINT;
|
||||
else if(_stricmp(argv[3], "int") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_INT;
|
||||
else if(_stricmp(argv[3], "float") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_FLOAT;
|
||||
else if(_stricmp(argv[3], "ascii") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_ASCII;
|
||||
else if(_stricmp(argv[3], "unicode") == 0)
|
||||
varType = WATCHVARTYPE::TYPE_UNICODE;
|
||||
else
|
||||
varType = WATCHVARTYPE::TYPE_UINT;
|
||||
}
|
||||
else
|
||||
varType = WATCHVARTYPE::TYPE_UINT;
|
||||
WatchModifyExpr((unsigned int)id, argv[2], varType);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dputs("Error expression in argument 1.\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
CMDRESULT cbSetWatchdog(int argc, char* argv[])
|
||||
{
|
||||
if(argc < 2)
|
||||
{
|
||||
dputs("No enough arguments for delwatch\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
duint id;
|
||||
bool ok = valfromstring(argv[1], &id);
|
||||
if(!ok)
|
||||
{
|
||||
dputs("Error expression in argument 1.\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
WATCHDOGMODE mode;
|
||||
if(argc > 2)
|
||||
{
|
||||
if(_stricmp(argv[2], "disabled") == 0)
|
||||
mode = WATCHDOGMODE::MODE_DISABLED;
|
||||
else if(_stricmp(argv[2], "changed") == 0)
|
||||
mode = WATCHDOGMODE::MODE_CHANGED;
|
||||
else if(_stricmp(argv[2], "unchanged") == 0)
|
||||
mode = WATCHDOGMODE::MODE_UNCHANGED;
|
||||
else if(_stricmp(argv[2], "istrue") == 0)
|
||||
mode = WATCHDOGMODE::MODE_ISTRUE;
|
||||
else if(_stricmp(argv[2], "isfalse") == 0)
|
||||
mode = WATCHDOGMODE::MODE_ISFALSE;
|
||||
else
|
||||
{
|
||||
dputs("Unknown watchdog mode.\n");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
mode = (WatchGetWatchdogEnabled((unsigned int)id) == WATCHDOGMODE::MODE_DISABLED) ? WATCHDOGMODE::MODE_CHANGED : WATCHDOGMODE::MODE_DISABLED;
|
||||
WatchSetWatchdogMode((unsigned int)id, mode);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
#include "_global.h"
|
||||
#include "command.h"
|
||||
#include "expressionparser.h"
|
||||
#include "jansson\jansson.h"
|
||||
#include "..\bridge\bridgemain.h"
|
||||
|
||||
class WatchExpr
|
||||
{
|
||||
protected:
|
||||
char WatchName[MAX_WATCH_NAME_SIZE];
|
||||
ExpressionParser expr;
|
||||
WATCHDOGMODE watchdogMode;
|
||||
bool haveCurrValue;
|
||||
WATCHVARTYPE varType;
|
||||
duint currValue; // last result of getIntValue()
|
||||
|
||||
public:
|
||||
bool watchdogTriggered;
|
||||
unsigned int watchWindow;
|
||||
|
||||
WatchExpr(const char* name, const char* expression, WATCHVARTYPE type);
|
||||
~WatchExpr() {};
|
||||
duint getIntValue(); // evaluate the expression as integer
|
||||
bool modifyExpr(const char* expression, WATCHVARTYPE type); // modify the expression and data type
|
||||
void modifyName(const char* newName);
|
||||
|
||||
inline WATCHDOGMODE getWatchdogMode()
|
||||
{
|
||||
return watchdogMode;
|
||||
};
|
||||
inline char* getName()
|
||||
{
|
||||
return WatchName;
|
||||
};
|
||||
inline void setWatchdogMode(WATCHDOGMODE mode)
|
||||
{
|
||||
watchdogMode = mode;
|
||||
};
|
||||
inline WATCHVARTYPE getType()
|
||||
{
|
||||
return varType;
|
||||
};
|
||||
inline duint getCurrIntValue()
|
||||
{
|
||||
return currValue;
|
||||
};
|
||||
inline const String & getExpr()
|
||||
{
|
||||
return expr.GetExpression();
|
||||
}
|
||||
inline const bool HaveCurrentValue()
|
||||
{
|
||||
return haveCurrValue;
|
||||
};
|
||||
};
|
||||
|
||||
extern std::map<unsigned int, WatchExpr*> watchexpr;
|
||||
|
||||
void WatchClear();
|
||||
unsigned int WatchAddExpr(const char* expr, WATCHVARTYPE type);
|
||||
bool WatchModifyExpr(unsigned int id, const char* expr, WATCHVARTYPE type);
|
||||
void WatchModifyName(unsigned int id, const char* newName);
|
||||
void WatchDelete(unsigned int id);
|
||||
void WatchSetWatchdogMode(unsigned int id, bool isEnabled);
|
||||
bool WatchIsWatchdogTriggered(unsigned int id);
|
||||
WATCHDOGMODE WatchGetWatchdogMode(unsigned int id);
|
||||
duint WatchGetUnsignedValue(unsigned int id);
|
||||
WATCHVARTYPE WatchGetType(unsigned int id);
|
||||
std::vector<WATCHINFO> WatchGetList();
|
||||
|
||||
void WatchCacheSave(JSON root); // Save watch data to database
|
||||
void WatchCacheLoad(JSON root); // Load watch data from database
|
||||
|
||||
CMDRESULT cbWatchdog(int argc, char* argv[]);
|
||||
CMDRESULT cbAddWatch(int argc, char* argv[]);
|
||||
CMDRESULT cbDelWatch(int argc, char* argv[]);
|
||||
CMDRESULT cbSetWatchName(int argc, char* argv[]);
|
||||
CMDRESULT cbSetWatchExpression(int argc, char* argv[]);
|
||||
CMDRESULT cbSetWatchdog(int argc, char* argv[]);
|
|
@ -14,6 +14,7 @@
|
|||
#include "x64_dbg.h"
|
||||
#include "msgqueue.h"
|
||||
#include "threading.h"
|
||||
#include "watch.h"
|
||||
#include "plugin_loader.h"
|
||||
#include "_dbgfunctions.h"
|
||||
#include "debugger_commands.h"
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include "error.h"
|
||||
#include "exception.h"
|
||||
#include "expressionfunctions.h"
|
||||
#include "historycontext.h"
|
||||
|
||||
static MESSAGE_STACK* gMsgStack = 0;
|
||||
static HANDLE hCommandLoopThread = 0;
|
||||
|
@ -82,7 +84,7 @@ static void registercommands()
|
|||
dbgcmdnew("StopDebug\1stop\1dbgstop", cbDebugStop, true); //stop debugger
|
||||
dbgcmdnew("AttachDebugger\1attach", cbDebugAttach, false); //attach
|
||||
dbgcmdnew("DetachDebugger\1detach", cbDebugDetach, true); //detach
|
||||
dbgcmdnew("run\1go\1r\1g", cbDebugRun, true); //unlock WAITID_RUN
|
||||
dbgcmdnew("run\1go\1r\1g", cbDebugRun2, true); //unlock WAITID_RUN
|
||||
dbgcmdnew("erun\1egun\1er\1eg", cbDebugErun, true); //run + skip first chance exceptions
|
||||
dbgcmdnew("pause", cbDebugPause, true); //pause debugger
|
||||
dbgcmdnew("StepInto\1sti", cbDebugStepInto, true); //StepInto
|
||||
|
@ -113,6 +115,7 @@ static void registercommands()
|
|||
dbgcmdnew("skip", cbDebugSkip, true); //skip one instruction
|
||||
dbgcmdnew("RunToParty", cbDebugRunToParty, true); //Run to code in a party
|
||||
dbgcmdnew("RunToUserCode\1rtu", cbDebugRtu, true); //Run to user code
|
||||
dbgcmdnew("InstrUndo", cbInstrInstrUndo, true); //Instruction undo
|
||||
|
||||
//breakpoints
|
||||
dbgcmdnew("bplist", cbDebugBplist, true); //breakpoint list
|
||||
|
@ -163,6 +166,14 @@ static void registercommands()
|
|||
|
||||
dbgcmdnew("bpgoto", cbDebugSetBPGoto, true);
|
||||
|
||||
//watch
|
||||
dbgcmdnew("AddWatch", cbAddWatch, true); // add watch
|
||||
dbgcmdnew("DelWatch", cbDelWatch, true); // delete watch
|
||||
dbgcmdnew("CheckWatchdog", cbWatchdog, true); // Watchdog
|
||||
dbgcmdnew("SetWatchdog", cbSetWatchdog, true); // Setup watchdog
|
||||
dbgcmdnew("SetWatchName", cbSetWatchName, true); // Set watch name
|
||||
dbgcmdnew("SetWatchExpression", cbSetWatchExpression, true); // Set watch expression
|
||||
|
||||
//variables
|
||||
dbgcmdnew("varnew\1var", cbInstrVar, false); //make a variable arg1:name,[arg2:value]
|
||||
dbgcmdnew("vardel", cbInstrVarDel, false); //delete a variable, arg1:variable name
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef _X64_DBG_H
|
||||
#define _X64_DBG_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "_global.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
|
@ -52,6 +52,7 @@
|
|||
<ClCompile Include="expressionparser.cpp" />
|
||||
<ClCompile Include="filehelper.cpp" />
|
||||
<ClCompile Include="function.cpp" />
|
||||
<ClCompile Include="historycontext.cpp" />
|
||||
<ClCompile Include="jit.cpp" />
|
||||
<ClCompile Include="linearanalysis.cpp" />
|
||||
<ClCompile Include="FunctionPass.cpp" />
|
||||
|
@ -81,6 +82,7 @@
|
|||
<ClCompile Include="TraceRecord.cpp" />
|
||||
<ClCompile Include="value.cpp" />
|
||||
<ClCompile Include="variable.cpp" />
|
||||
<ClCompile Include="watch.cpp" />
|
||||
<ClCompile Include="x64_dbg.cpp" />
|
||||
<ClCompile Include="xrefs.cpp" />
|
||||
<ClCompile Include="xrefsanalysis.cpp" />
|
||||
|
@ -143,6 +145,7 @@
|
|||
<ClInclude Include="expressionparser.h" />
|
||||
<ClInclude Include="filehelper.h" />
|
||||
<ClInclude Include="function.h" />
|
||||
<ClInclude Include="historycontext.h" />
|
||||
<ClInclude Include="jit.h" />
|
||||
<ClInclude Include="keystone\arm.h" />
|
||||
<ClInclude Include="keystone\arm64.h" />
|
||||
|
@ -180,6 +183,7 @@
|
|||
<ClInclude Include="taskthread.h" />
|
||||
<ClInclude Include="tcpconnections.h" />
|
||||
<ClInclude Include="TraceRecord.h" />
|
||||
<ClInclude Include="watch.h" />
|
||||
<ClInclude Include="xrefs.h" />
|
||||
<ClInclude Include="xrefsanalysis.h" />
|
||||
<ClInclude Include="yara\yara\stream.h" />
|
||||
|
@ -417,4 +421,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
|
@ -338,6 +338,12 @@
|
|||
<ClCompile Include="expressionfunctions.cpp">
|
||||
<Filter>Source Files\Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="historycontext.cpp">
|
||||
<Filter>Source Files\Information</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="watch.cpp">
|
||||
<Filter>Source Files\Information</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="x64_dbg.h">
|
||||
|
@ -760,6 +766,12 @@
|
|||
<ClInclude Include="datainst_helper.h">
|
||||
<Filter>Header Files\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="historycontext.h">
|
||||
<Filter>Header Files\Information</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="watch.h">
|
||||
<Filter>Header Files\Information</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="taskthread.h">
|
||||
<Filter>Header Files\Utilities</Filter>
|
||||
</ClInclude>
|
||||
|
@ -767,4 +779,4 @@
|
|||
<Filter>Header Files\Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -574,6 +574,10 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_UPDATE_WATCH_VIEW:
|
||||
emit updateWatch();
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ signals:
|
|||
void focusDisasm();
|
||||
void focusDump();
|
||||
void focusStack();
|
||||
void updateWatch();
|
||||
|
||||
private:
|
||||
QMutex* mBridgeMutex;
|
||||
|
|
|
@ -527,6 +527,7 @@ void AppearanceDialog::colorInfoListInit()
|
|||
|
||||
colorInfoListAppend(tr("Other:"), "", "");
|
||||
colorInfoListAppend(tr("Current Thread"), "ThreadCurrentColor", "ThreadCurrentBackgroundColor");
|
||||
colorInfoListAppend(tr("Watch (When Watchdog is Triggered)"), "WatchTriggeredColor", "WatchTriggeredBackgroundColor");
|
||||
colorInfoListAppend(tr("Memory Map Breakpoint"), "MemoryMapBreakpointColor", "MemoryMapBreakpointBackgroundColor");
|
||||
colorInfoListAppend(tr("Memory Map %1").arg(ArchValue(tr("EIP"), tr("RIP"))), "MemoryMapCipColor", "MemoryMapCipBackgroundColor");
|
||||
colorInfoListAppend(tr("Memory Map Section Text"), "MemoryMapSectionTextColor", "");
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#include "BrowseDialog.h"
|
||||
#include "ui_BrowseDialog.h"
|
||||
#include <QFileDialog>
|
||||
|
||||
BrowseDialog::BrowseDialog(QWidget* parent, const QString & title, const QString & text, const QString & filter, const QString & defaultPath, bool save) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::BrowseDialog), mFilter(filter), mSave(save)
|
||||
{
|
||||
this->setWindowTitle(title);
|
||||
ui->setupUi(this);
|
||||
ui->label->setText(text);
|
||||
ui->lineEdit->setText(defaultPath);
|
||||
}
|
||||
|
||||
BrowseDialog::~BrowseDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void BrowseDialog::on_browse_clicked()
|
||||
{
|
||||
QString file;
|
||||
if(mSave)
|
||||
file = QFileDialog::getSaveFileName(this, ui->label->text(), ui->lineEdit->text(), mFilter);
|
||||
else
|
||||
file = QFileDialog::getOpenFileName(this, ui->label->text(), ui->lineEdit->text(), mFilter);
|
||||
if(file.size() != 0)
|
||||
ui->lineEdit->setText(file);
|
||||
}
|
||||
|
||||
void BrowseDialog::on_ok_clicked()
|
||||
{
|
||||
path = ui->lineEdit->text();
|
||||
accept();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef BROWSEDIALOG_H
|
||||
#define BROWSEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BrowseDialog;
|
||||
}
|
||||
|
||||
class BrowseDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BrowseDialog(QWidget* parent, const QString & title, const QString & text, const QString & filter, const QString & defaultPath, bool save);
|
||||
~BrowseDialog();
|
||||
|
||||
QString path;
|
||||
public slots:
|
||||
void on_browse_clicked();
|
||||
void on_ok_clicked();
|
||||
|
||||
private:
|
||||
Ui::BrowseDialog* ui;
|
||||
QString mFilter;
|
||||
bool mSave;
|
||||
};
|
||||
|
||||
#endif // BROWSEDIALOG_H
|
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BrowseDialog</class>
|
||||
<widget class="QDialog" name="BrowseDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>487</width>
|
||||
<height>97</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Please input the file path.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="browse">
|
||||
<property name="text">
|
||||
<string>&Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ok">
|
||||
<property name="text">
|
||||
<string>&OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancel">
|
||||
<property name="text">
|
||||
<string>&Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>cancel</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>BrowseDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>439</x>
|
||||
<y>75</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>243</x>
|
||||
<y>48</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -18,8 +18,13 @@ CPUMultiDump::CPUMultiDump(CPUDisassembly* disas, int nbCpuDumpTabs, QWidget* pa
|
|||
this->addTabEx(cpuDump, QIcon(":/icons/images/dump.png"), tr("Dump ") + QString::number(i + 1), QString("Dump ") + QString::number(i + 1));
|
||||
}
|
||||
|
||||
mCurrentCPUDump = (CPUDump*)currentWidget();
|
||||
mCurrentCPUDump = dynamic_cast<CPUDump*>(currentWidget());
|
||||
|
||||
mWatch = new WatchView(this);
|
||||
|
||||
//mMaxCPUDumpTabs++;
|
||||
this->addTabEx(mWatch, QIcon(":/icons/images/geolocation-goto.png"), tr("Watch ") + QString::number(1), QString("Watch 1"));
|
||||
mWatch->loadColumnFromConfig("Watch1");
|
||||
|
||||
connect(this, SIGNAL(currentChanged(int)), this, SLOT(updateCurrentTabSlot(int)));
|
||||
connect(tabBar(), SIGNAL(OnDoubleClickTabIndex(int)), this, SLOT(openChangeTabTitleDialogSlot(int)));
|
||||
|
@ -45,6 +50,8 @@ void CPUMultiDump::getTabNames(QList<QString> & names)
|
|||
names.clear();
|
||||
for(int i = 0; i < count(); i++)
|
||||
{
|
||||
if(!getNativeName(i).startsWith("Dump "))
|
||||
continue;
|
||||
// If empty name, then widget is detached
|
||||
if(this->tabBar()->tabText(i).length() == 0)
|
||||
{
|
||||
|
@ -76,7 +83,9 @@ int CPUMultiDump::getMaxCPUTabs()
|
|||
|
||||
void CPUMultiDump::updateCurrentTabSlot(int tabIndex)
|
||||
{
|
||||
mCurrentCPUDump = (CPUDump*)widget(tabIndex);
|
||||
CPUDump* t = dynamic_cast<CPUDump*>(widget(tabIndex));
|
||||
if(t)
|
||||
mCurrentCPUDump = t;
|
||||
}
|
||||
|
||||
void CPUMultiDump::printDumpAtSlot(dsint parVa)
|
||||
|
@ -86,6 +95,8 @@ void CPUMultiDump::printDumpAtSlot(dsint parVa)
|
|||
CPUDump* cpuDump = NULL;
|
||||
for(int i = 0; i < count(); i++)
|
||||
{
|
||||
if(!getNativeName(i).startsWith("Dump "))
|
||||
continue;
|
||||
cpuDump = (CPUDump*)widget(i);
|
||||
cpuDump->historyClear();
|
||||
cpuDump->addVaToHistory(parVa);
|
||||
|
@ -105,10 +116,21 @@ void CPUMultiDump::printDumpAtSlot(dsint parVa)
|
|||
void CPUMultiDump::printDumpAtNSlot(duint parVa, int index)
|
||||
{
|
||||
setCurrentIndex(index);
|
||||
|
||||
mCurrentCPUDump = (CPUDump*) widget(index);
|
||||
mCurrentCPUDump->printDumpAt(parVa);
|
||||
mCurrentCPUDump->addVaToHistory(parVa);
|
||||
CPUDump* current = dynamic_cast<CPUDump*>(widget(index));
|
||||
if(current)
|
||||
{
|
||||
current->printDumpAt(parVa);
|
||||
current->addVaToHistory(parVa);
|
||||
}
|
||||
else if(index > 0 && unsigned int(index) < mMaxCPUDumpTabs)
|
||||
{
|
||||
current = dynamic_cast<CPUDump*>(widget(index + 1));
|
||||
if(current)
|
||||
{
|
||||
current->printDumpAt(parVa);
|
||||
current->addVaToHistory(parVa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPUMultiDump::selectionGetSlot(SELECTIONDATA* selectionData)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QWidget>
|
||||
#include "CPUDump.h"
|
||||
#include "TabWidget.h"
|
||||
#include "WatchView.h"
|
||||
|
||||
class CPUDump;
|
||||
|
||||
|
@ -35,6 +36,7 @@ private:
|
|||
bool mInitAllDumpTabs;
|
||||
uint mMaxCPUDumpTabs;
|
||||
|
||||
WatchView* mWatch;
|
||||
};
|
||||
|
||||
#endif // CPUMULTIDUMP_H
|
||||
|
|
|
@ -0,0 +1,381 @@
|
|||
#include "FavouriteTools.h"
|
||||
#include "ui_FavouriteTools.h"
|
||||
#include "Bridge.h"
|
||||
#include "BrowseDialog.h"
|
||||
#include "MainWindow.h"
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include "MiscUtil.h"
|
||||
|
||||
FavouriteTools::FavouriteTools(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::FavouriteTools)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
//set window flags
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setModal(true);
|
||||
|
||||
setupTools("Tool", ui->listTools);
|
||||
setupTools("Script", ui->listScript);
|
||||
|
||||
QStringList tblHeaderCommand;
|
||||
tblHeaderCommand << tr("Command") << tr("Shortcut");
|
||||
QTableWidget* list = ui->listCommand;
|
||||
list->setColumnCount(2);
|
||||
list->verticalHeader()->setVisible(false);
|
||||
list->setHorizontalHeaderLabels(tblHeaderCommand);
|
||||
list->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
list->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
list->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
list->setShowGrid(false);
|
||||
list->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
list->verticalHeader()->setDefaultSectionSize(15);
|
||||
char buffer[MAX_SETTING_SIZE];
|
||||
int i;
|
||||
std::vector<QString> allCommand;
|
||||
std::vector<QString> allToolShortcut;
|
||||
for(i = 1; BridgeSettingGet("Favourite", QString("Command%1").arg(i).toUtf8().constData(), buffer); i++)
|
||||
{
|
||||
QString command = QString::fromUtf8(buffer);
|
||||
QString commandShortcut("");
|
||||
if(BridgeSettingGet("Favourite", QString("CommandShortcut%1").arg(i).toUtf8().constData(), buffer))
|
||||
commandShortcut = QString::fromUtf8(buffer);
|
||||
allCommand.push_back(command);
|
||||
allToolShortcut.push_back(commandShortcut);
|
||||
}
|
||||
i--;
|
||||
if(!allCommand.empty())
|
||||
{
|
||||
list->setRowCount(i);
|
||||
for(int j = 0; j < i; j++)
|
||||
{
|
||||
list->setItem(j, 0, new QTableWidgetItem(allCommand.at(j)));
|
||||
list->setItem(j, 1, new QTableWidgetItem(allToolShortcut.at(j)));
|
||||
}
|
||||
}
|
||||
originalToolsCount = ui->listTools->rowCount();
|
||||
originalScriptCount = ui->listScript->rowCount();
|
||||
originalCommandCount = ui->listCommand->rowCount();
|
||||
ui->listTools->selectRow(0);
|
||||
ui->listScript->selectRow(0);
|
||||
ui->listCommand->selectRow(0);
|
||||
connect(ui->listTools, SIGNAL(itemSelectionChanged()), this, SLOT(onListSelectionChanged()));
|
||||
connect(ui->listScript, SIGNAL(itemSelectionChanged()), this, SLOT(onListSelectionChanged()));
|
||||
connect(ui->listCommand, SIGNAL(itemSelectionChanged()), this, SLOT(onListSelectionChanged()));
|
||||
}
|
||||
|
||||
void FavouriteTools::setupTools(QString name, QTableWidget* list)
|
||||
{
|
||||
QStringList tblHeaderTools;
|
||||
tblHeaderTools << tr("Path") << tr("Shortcut") << tr("Description");
|
||||
list->setColumnCount(3);
|
||||
list->verticalHeader()->setVisible(false);
|
||||
list->setHorizontalHeaderLabels(tblHeaderTools);
|
||||
list->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
list->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
list->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
list->setShowGrid(false);
|
||||
list->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
list->verticalHeader()->setDefaultSectionSize(15);
|
||||
|
||||
char buffer[MAX_SETTING_SIZE];
|
||||
int i;
|
||||
std::vector<QString> allToolPath;
|
||||
std::vector<QString> allToolShortcut;
|
||||
std::vector<QString> allToolDescription;
|
||||
for(i = 1; BridgeSettingGet("Favourite", (name + QString::number(i)).toUtf8().constData(), buffer); i++)
|
||||
{
|
||||
QString toolPath = QString::fromUtf8(buffer);
|
||||
QString toolShortcut("");
|
||||
QString toolDescription("");
|
||||
if(BridgeSettingGet("Favourite", (name + "Shortcut" + QString::number(i)).toUtf8().constData(), buffer))
|
||||
toolShortcut = QString::fromUtf8(buffer);
|
||||
if(BridgeSettingGet("Favourite", (name + "Description" + QString::number(i)).toUtf8().constData(), buffer))
|
||||
toolDescription = QString::fromUtf8(buffer);
|
||||
allToolPath.push_back(toolPath);
|
||||
allToolShortcut.push_back(toolShortcut);
|
||||
allToolDescription.push_back(toolDescription);
|
||||
}
|
||||
i--;
|
||||
if(!allToolPath.empty())
|
||||
{
|
||||
list->setRowCount(i);
|
||||
for(int j = 0; j < i; j++)
|
||||
{
|
||||
list->setItem(j, 0, new QTableWidgetItem(allToolPath.at(j)));
|
||||
list->setItem(j, 1, new QTableWidgetItem(allToolShortcut.at(j)));
|
||||
list->setItem(j, 2, new QTableWidgetItem(allToolDescription.at(j)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Events
|
||||
void FavouriteTools::on_btnAddFavouriteTool_clicked()
|
||||
{
|
||||
QString filename;
|
||||
char buffer[MAX_SETTING_SIZE];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
BridgeSettingGet("Favourite", "LastToolPath", buffer);
|
||||
BrowseDialog browse(this, QString("Browse tool"), QString("Enter the path of the tool."), QString("Executable Files (*.exe);;All Files (*.*)"), QString::fromUtf8(buffer), false);
|
||||
if(browse.exec() != QDialog::Accepted)
|
||||
return;
|
||||
filename = browse.path;
|
||||
BridgeSettingSet("Favourite", "LastToolPath", filename.toUtf8().constData());
|
||||
int rows = ui->listTools->rowCount();
|
||||
ui->listTools->setRowCount(rows + 1);
|
||||
ui->listTools->setItem(rows, 0, new QTableWidgetItem(filename));
|
||||
ui->listTools->setItem(rows, 1, new QTableWidgetItem(QString()));
|
||||
ui->listTools->setItem(rows, 2, new QTableWidgetItem(filename));
|
||||
if(rows == 0)
|
||||
ui->listTools->selectRow(0);
|
||||
}
|
||||
|
||||
void FavouriteTools::upbutton(QTableWidget* table)
|
||||
{
|
||||
int currentRow = table->currentRow();
|
||||
if(currentRow == 0)
|
||||
return;
|
||||
for(int i = 0; i < table->columnCount(); i++)
|
||||
{
|
||||
QString prevContent(table->item(currentRow, i)->text());
|
||||
table->item(currentRow, i)->setText(table->item(currentRow - 1, i)->text());
|
||||
table->item(currentRow - 1, i)->setText(prevContent);
|
||||
}
|
||||
table->selectRow(currentRow - 1);
|
||||
}
|
||||
|
||||
void FavouriteTools::downbutton(QTableWidget* table)
|
||||
{
|
||||
int currentRow = table->currentRow();
|
||||
if(currentRow == table->rowCount() - 1)
|
||||
return;
|
||||
for(int i = 0; i < table->columnCount(); i++)
|
||||
{
|
||||
QString prevContent(table->item(currentRow, i)->text());
|
||||
table->item(currentRow, i)->setText(table->item(currentRow + 1, i)->text());
|
||||
table->item(currentRow + 1, i)->setText(prevContent);
|
||||
}
|
||||
table->selectRow(currentRow + 1);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnRemoveFavouriteTool_clicked()
|
||||
{
|
||||
QTableWidget* table = ui->listTools;
|
||||
table->removeRow(table->currentRow());
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnDescriptionFavouriteTool_clicked()
|
||||
{
|
||||
QTableWidget* table = ui->listTools;
|
||||
QString description = table->item(table->currentRow(), 2)->text();
|
||||
if(SimpleInputBox(this, tr("Enter the description"), description, description))
|
||||
table->item(table->currentRow(), 2)->setText(description);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnUpFavouriteTool_clicked()
|
||||
{
|
||||
upbutton(ui->listTools);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnDownFavouriteTool_clicked()
|
||||
{
|
||||
downbutton(ui->listTools);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnAddFavouriteScript_clicked()
|
||||
{
|
||||
QString filename;
|
||||
char buffer[MAX_SETTING_SIZE];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
BridgeSettingGet("Favourite", "LastScriptPath", buffer);
|
||||
filename = QFileDialog::getOpenFileName(this, tr("Select script"), QString::fromUtf8(buffer), tr("Script files (*.txt *.scr);;All files (*.*)"));
|
||||
if(filename.size() == 0)
|
||||
return;
|
||||
BridgeSettingSet("Favourite", "LastScriptPath", filename.toUtf8().constData());
|
||||
int rows = ui->listScript->rowCount();
|
||||
ui->listScript->setRowCount(rows + 1);
|
||||
ui->listScript->setItem(rows, 0, new QTableWidgetItem(filename));
|
||||
ui->listScript->setItem(rows, 1, new QTableWidgetItem(QString("NOT_SET")));
|
||||
ui->listScript->setItem(rows, 2, new QTableWidgetItem(filename));
|
||||
if(rows == 0)
|
||||
ui->listScript->selectRow(0);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnRemoveFavouriteScript_clicked()
|
||||
{
|
||||
QTableWidget* table = ui->listScript;
|
||||
table->removeRow(table->currentRow());
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnDescriptionFavouriteScript_clicked()
|
||||
{
|
||||
QTableWidget* table = ui->listScript;
|
||||
QString description = table->item(table->currentRow(), 2)->text();
|
||||
if(SimpleInputBox(this, tr("Enter the description"), description, description))
|
||||
table->item(table->currentRow(), 2)->setText(description);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnUpFavouriteScript_clicked()
|
||||
{
|
||||
upbutton(ui->listScript);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnDownFavouriteScript_clicked()
|
||||
{
|
||||
downbutton(ui->listScript);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnAddFavouriteCommand_clicked()
|
||||
{
|
||||
QString cmd;
|
||||
if(SimpleInputBox(this, tr("Enter the command that you want to create a shortcut for :"), "", cmd))
|
||||
{
|
||||
int rows = ui->listCommand->rowCount();
|
||||
ui->listCommand->setRowCount(rows + 1);
|
||||
ui->listCommand->setItem(rows, 0, new QTableWidgetItem(cmd));
|
||||
ui->listCommand->setItem(rows, 1, new QTableWidgetItem(QString("NOT_SET")));
|
||||
if(rows == 0)
|
||||
ui->listCommand->selectRow(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnRemoveFavouriteCommand_clicked()
|
||||
{
|
||||
QTableWidget* table = ui->listCommand;
|
||||
table->removeRow(table->currentRow());
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnUpFavouriteCommand_clicked()
|
||||
{
|
||||
upbutton(ui->listCommand);
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnDownFavouriteCommand_clicked()
|
||||
{
|
||||
downbutton(ui->listCommand);
|
||||
}
|
||||
|
||||
void FavouriteTools::onListSelectionChanged()
|
||||
{
|
||||
QTableWidget* table = qobject_cast<QTableWidget*>(sender());
|
||||
if(table == nullptr)
|
||||
throw std::exception("No active table!");
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows();
|
||||
if(indexes.count() < 1)
|
||||
return;
|
||||
ui->shortcutEdit->setErrorState(false);
|
||||
currentShortcut = QKeySequence(table->item(table->currentRow(), 1)->text());
|
||||
ui->shortcutEdit->setText(currentShortcut.toString(QKeySequence::NativeText));
|
||||
}
|
||||
|
||||
void FavouriteTools::on_shortcutEdit_askForSave()
|
||||
{
|
||||
QTableWidget* table;
|
||||
switch(ui->tabWidget->currentIndex())
|
||||
{
|
||||
case 0:
|
||||
table = ui->listTools;
|
||||
break;
|
||||
case 1:
|
||||
table = ui->listScript;
|
||||
break;
|
||||
case 2:
|
||||
table = ui->listCommand;
|
||||
break;
|
||||
default:
|
||||
throw std::exception("No active table!");
|
||||
}
|
||||
const QKeySequence newKey = ui->shortcutEdit->getKeysequence();
|
||||
if(newKey != currentShortcut)
|
||||
{
|
||||
bool good = true;
|
||||
if(!newKey.isEmpty())
|
||||
{
|
||||
for(auto i = Config()->Shortcuts.cbegin(); i != Config()->Shortcuts.cend(); ++i)
|
||||
{
|
||||
if(i.value().Hotkey == newKey) //newkey is trying to override a global shortcut
|
||||
{
|
||||
good = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(good)
|
||||
{
|
||||
QString keyText = "";
|
||||
if(!newKey.isEmpty())
|
||||
keyText = newKey.toString(QKeySequence::NativeText);
|
||||
table->item(table->currentRow(), 1)->setText(keyText);
|
||||
ui->shortcutEdit->setErrorState(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->shortcutEdit->setErrorState(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FavouriteTools::on_btnOK_clicked()
|
||||
{
|
||||
for(int i = 1; i <= ui->listTools->rowCount(); i++)
|
||||
{
|
||||
BridgeSettingSet("Favourite", QString("Tool%1").arg(i).toUtf8().constData(), ui->listTools->item(i - 1, 0)->text().toUtf8().constData());
|
||||
BridgeSettingSet("Favourite", QString("ToolShortcut%1").arg(i).toUtf8().constData(), ui->listTools->item(i - 1, 1)->text().toUtf8().constData());
|
||||
BridgeSettingSet("Favourite", QString("ToolDescription%1").arg(i).toUtf8().constData(), ui->listTools->item(i - 1, 2)->text().toUtf8().constData());
|
||||
}
|
||||
if(ui->listTools->rowCount() == 0)
|
||||
{
|
||||
BridgeSettingSet("Favourite", "Tool1", "");
|
||||
BridgeSettingSet("Favourite", "ToolShortcut1", "");
|
||||
BridgeSettingSet("Favourite", "ToolDescription1", "");
|
||||
}
|
||||
else
|
||||
for(int i = ui->listTools->rowCount() + 1; i <= originalToolsCount; i++)
|
||||
{
|
||||
BridgeSettingSet("Favourite", QString("Tool%1").arg(i).toUtf8().constData(), "");
|
||||
BridgeSettingSet("Favourite", QString("ToolShortcut%1").arg(i).toUtf8().constData(), "");
|
||||
BridgeSettingSet("Favourite", QString("ToolDescription%1").arg(i).toUtf8().constData(), "");
|
||||
}
|
||||
for(int i = 1; i <= ui->listScript->rowCount(); i++)
|
||||
{
|
||||
BridgeSettingSet("Favourite", QString("Script%1").arg(i).toUtf8().constData(), ui->listScript->item(i - 1, 0)->text().toUtf8().constData());
|
||||
BridgeSettingSet("Favourite", QString("ScriptShortcut%1").arg(i).toUtf8().constData(), ui->listScript->item(i - 1, 1)->text().toUtf8().constData());
|
||||
BridgeSettingSet("Favourite", QString("ScriptDescription%1").arg(i).toUtf8().constData(), ui->listScript->item(i - 1, 2)->text().toUtf8().constData());
|
||||
}
|
||||
if(ui->listScript->rowCount() == 0)
|
||||
{
|
||||
BridgeSettingSet("Favourite", "Script1", "");
|
||||
BridgeSettingSet("Favourite", "ScriptShortcut1", "");
|
||||
BridgeSettingSet("Favourite", "ScriptDescription1", "");
|
||||
}
|
||||
else
|
||||
for(int i = ui->listScript->rowCount() + 1; i <= originalScriptCount; i++)
|
||||
{
|
||||
BridgeSettingSet("Favourite", QString("Script%1").arg(i).toUtf8().constData(), "");
|
||||
BridgeSettingSet("Favourite", QString("ScriptShortcut%1").arg(i).toUtf8().constData(), "");
|
||||
BridgeSettingSet("Favourite", QString("ScriptDescription%1").arg(i).toUtf8().constData(), "");
|
||||
}
|
||||
for(int i = 1; i <= ui->listCommand->rowCount(); i++)
|
||||
{
|
||||
BridgeSettingSet("Favourite", QString("Command%1").arg(i).toUtf8().constData(), ui->listCommand->item(i - 1, 0)->text().toUtf8().constData());
|
||||
BridgeSettingSet("Favourite", QString("CommandShortcut%1").arg(i).toUtf8().constData(), ui->listCommand->item(i - 1, 1)->text().toUtf8().constData());
|
||||
}
|
||||
if(ui->listCommand->rowCount() == 0)
|
||||
{
|
||||
BridgeSettingSet("Favourite", "Command1", "");
|
||||
BridgeSettingSet("Favourite", "CommandShortcut1", "");
|
||||
}
|
||||
else
|
||||
for(int i = ui->listCommand->rowCount() + 1; i <= originalCommandCount; i++)
|
||||
{
|
||||
BridgeSettingSet("Favourite", QString("Command%1").arg(i).toUtf8().constData(), "");
|
||||
BridgeSettingSet("Favourite", QString("CommandShortcut%1").arg(i).toUtf8().constData(), "");
|
||||
}
|
||||
this->done(QDialog::Accepted);
|
||||
}
|
||||
|
||||
FavouriteTools::~FavouriteTools()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef FAVOURITETOOLS_H
|
||||
#define FAVOURITETOOLS_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTableWidget>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class FavouriteTools;
|
||||
}
|
||||
|
||||
class FavouriteTools : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FavouriteTools(QWidget* parent = 0);
|
||||
~FavouriteTools();
|
||||
public slots:
|
||||
void on_btnAddFavouriteTool_clicked();
|
||||
void on_btnRemoveFavouriteTool_clicked();
|
||||
void on_btnDescriptionFavouriteTool_clicked();
|
||||
void on_btnUpFavouriteTool_clicked();
|
||||
void on_btnDownFavouriteTool_clicked();
|
||||
void on_btnAddFavouriteScript_clicked();
|
||||
void on_btnRemoveFavouriteScript_clicked();
|
||||
void on_btnDescriptionFavouriteScript_clicked();
|
||||
void on_btnUpFavouriteScript_clicked();
|
||||
void on_btnDownFavouriteScript_clicked();
|
||||
void on_btnAddFavouriteCommand_clicked();
|
||||
void on_btnRemoveFavouriteCommand_clicked();
|
||||
void on_btnUpFavouriteCommand_clicked();
|
||||
void on_btnDownFavouriteCommand_clicked();
|
||||
void onListSelectionChanged();
|
||||
void on_shortcutEdit_askForSave();
|
||||
void on_btnOK_clicked();
|
||||
private:
|
||||
Ui::FavouriteTools* ui;
|
||||
QKeySequence currentShortcut;
|
||||
int originalToolsCount;
|
||||
int originalScriptCount;
|
||||
int originalCommandCount;
|
||||
|
||||
void upbutton(QTableWidget* table);
|
||||
void downbutton(QTableWidget* table);
|
||||
|
||||
void setupTools(QString name, QTableWidget* list);
|
||||
};
|
||||
|
||||
#endif // FAVOURITETOOLS_H
|
|
@ -0,0 +1,244 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FavouriteTools</class>
|
||||
<widget class="QDialog" name="FavouriteTools">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Favourites</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../resource.qrc">
|
||||
<normaloff>:/icons/images/star.png</normaloff>:/icons/images/star.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabFavouriteTool">
|
||||
<attribute name="title">
|
||||
<string>Tools</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="listTools"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAddFavouriteTool">
|
||||
<property name="text">
|
||||
<string>&Add...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRemoveFavouriteTool">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDescriptionFavouriteTool">
|
||||
<property name="text">
|
||||
<string>De&scription...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpFavouriteTool">
|
||||
<property name="text">
|
||||
<string>&Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDownFavouriteTool">
|
||||
<property name="text">
|
||||
<string>&Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabFavouriteScript">
|
||||
<attribute name="title">
|
||||
<string>Script</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="listScript"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAddFavouriteScript">
|
||||
<property name="text">
|
||||
<string>&Add...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRemoveFavouriteScript">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDescriptionFavouriteScript">
|
||||
<property name="text">
|
||||
<string>De&scription...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpFavouriteScript">
|
||||
<property name="text">
|
||||
<string>&Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDownFavouriteScript">
|
||||
<property name="text">
|
||||
<string>&Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabFavouriteCommand">
|
||||
<attribute name="title">
|
||||
<string>Command</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="listCommand"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAddFavouriteCommand">
|
||||
<property name="text">
|
||||
<string>&Add...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRemoveFavouriteCommand">
|
||||
<property name="text">
|
||||
<string>&Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnUpFavouriteCommand">
|
||||
<property name="text">
|
||||
<string>&Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDownFavouriteCommand">
|
||||
<property name="text">
|
||||
<string>&Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Shortcut</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="ShortcutEdit" name="shortcutEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnOK">
|
||||
<property name="text">
|
||||
<string>&OK</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCancel">
|
||||
<property name="text">
|
||||
<string>&Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ShortcutEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>ShortcutEdit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../resource.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>btnCancel</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>FavouriteTools</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>352</x>
|
||||
<y>378</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>199</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -71,7 +71,7 @@ void LineEditDialog::on_textEdit_textChanged(const QString & arg1)
|
|||
int ct = arg1.size() - (int) this->fixed_size;
|
||||
if(ct > 0)
|
||||
symbolct = "+";
|
||||
ui->label->setText(QString("<font color='red'>") + QString("CT: ") + symbolct + QString::number(ct) + QString("</font>"));
|
||||
ui->label->setText(tr("<font color='red'>CT: %1%2</font>").arg(symbolct).arg(ct));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "LineEditDialog.h"
|
||||
#include "StringUtil.h"
|
||||
#include "MiscUtil.h"
|
||||
#include "FavouriteTools.h"
|
||||
|
||||
QString MainWindow::windowTitle = "";
|
||||
|
||||
|
@ -241,6 +242,7 @@ MainWindow::MainWindow(QWidget* parent)
|
|||
connect(ui->actionTRTOBT, SIGNAL(triggered()), this, SLOT(execTRTOBT()));
|
||||
connect(ui->actionTRTIIT, SIGNAL(triggered()), this, SLOT(execTRTIIT()));
|
||||
connect(ui->actionTRTOIT, SIGNAL(triggered()), this, SLOT(execTRTOIT()));
|
||||
connect(ui->actionInstrUndo, SIGNAL(triggered()), this, SLOT(execInstrUndo()));
|
||||
connect(ui->actionSkipNextInstruction, SIGNAL(triggered()), this, SLOT(execSkip()));
|
||||
connect(ui->actionScript, SIGNAL(triggered()), this, SLOT(displayScriptWidget()));
|
||||
connect(ui->actionRunSelection, SIGNAL(triggered()), this, SLOT(runSelection()));
|
||||
|
@ -271,6 +273,7 @@ MainWindow::MainWindow(QWidget* parent)
|
|||
connect(ui->actionSEHChain, SIGNAL(triggered()), this, SLOT(displaySEHChain()));
|
||||
connect(ui->actionDonate, SIGNAL(triggered()), this, SLOT(donate()));
|
||||
connect(ui->actionReportBug, SIGNAL(triggered()), this, SLOT(reportBug()));
|
||||
connect(ui->actionCrashDump, SIGNAL(triggered()), this, SLOT(crashDump()));
|
||||
connect(ui->actionAttach, SIGNAL(triggered()), this, SLOT(displayAttach()));
|
||||
connect(ui->actionDetach, SIGNAL(triggered()), this, SLOT(detach()));
|
||||
connect(ui->actionChangeCommandLine, SIGNAL(triggered()), this, SLOT(changeCommandLine()));
|
||||
|
@ -292,16 +295,18 @@ MainWindow::MainWindow(QWidget* parent)
|
|||
connect(mTabWidget, SIGNAL(tabMovedTabWidget(int, int)), this, SLOT(tabMovedSlot(int, int)));
|
||||
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcuts()));
|
||||
|
||||
// Setup favourite tools menu
|
||||
updateFavouriteTools();
|
||||
|
||||
// Set default setttings (when not set)
|
||||
SettingsDialog defaultSettings;
|
||||
lastException = 0;
|
||||
defaultSettings.SaveSettings();
|
||||
// Don't need to set shortcuts because the code above will signal refreshShortcuts()
|
||||
|
||||
// Create updatechecker
|
||||
mUpdateChecker = new UpdateChecker(this);
|
||||
|
||||
refreshShortcuts();
|
||||
|
||||
// Setup close thread and dialog
|
||||
bCanClose = false;
|
||||
mCloseThread = new MainWindowCloseThread(this);
|
||||
|
@ -466,13 +471,17 @@ void MainWindow::refreshShortcuts()
|
|||
setGlobalShortcut(ui->actionTocnd, ConfigShortcut("DebugTraceOverConditional"));
|
||||
setGlobalShortcut(ui->actionTRBit, ConfigShortcut("DebugEnableTraceRecordBit"));
|
||||
setGlobalShortcut(ui->actionTRNone, ConfigShortcut("DebugTraceRecordNone"));
|
||||
setGlobalShortcut(ui->actionInstrUndo, ConfigShortcut("DebugInstrUndo"));
|
||||
|
||||
setGlobalShortcut(ui->actionScylla, ConfigShortcut("PluginsScylla"));
|
||||
|
||||
setGlobalShortcut(actionManageFavourites, ConfigShortcut("FavouritesManage"));
|
||||
|
||||
setGlobalShortcut(ui->actionSettings, ConfigShortcut("OptionsPreferences"));
|
||||
setGlobalShortcut(ui->actionAppearance, ConfigShortcut("OptionsAppearance"));
|
||||
setGlobalShortcut(ui->actionShortcuts, ConfigShortcut("OptionsShortcuts"));
|
||||
setGlobalShortcut(ui->actionTopmost, ConfigShortcut("OptionsTopmost"));
|
||||
setGlobalShortcut(ui->actionReloadStylesheet, ConfigShortcut("OptionsReloadStylesheet"));
|
||||
|
||||
setGlobalShortcut(ui->actionAbout, ConfigShortcut("HelpAbout"));
|
||||
setGlobalShortcut(ui->actionDonate, ConfigShortcut("HelpDonate"));
|
||||
|
@ -480,6 +489,7 @@ void MainWindow::refreshShortcuts()
|
|||
setGlobalShortcut(ui->actionCalculator, ConfigShortcut("HelpCalculator"));
|
||||
setGlobalShortcut(ui->actionReportBug, ConfigShortcut("HelpReportBug"));
|
||||
setGlobalShortcut(ui->actionManual, ConfigShortcut("HelpManual"));
|
||||
setGlobalShortcut(ui->actionCrashDump, ConfigShortcut("HelpCrashDump"));
|
||||
|
||||
setGlobalShortcut(ui->actionStrings, ConfigShortcut("ActionFindStrings"));
|
||||
setGlobalShortcut(ui->actionCalls, ConfigShortcut("ActionFindIntermodularCalls"));
|
||||
|
@ -652,6 +662,11 @@ void MainWindow::execTRTOIT()
|
|||
DbgCmdExec("toit");
|
||||
}
|
||||
|
||||
void MainWindow::execInstrUndo()
|
||||
{
|
||||
DbgCmdExec("InstrUndo");
|
||||
}
|
||||
|
||||
void MainWindow::execTicnd()
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
|
@ -1158,10 +1173,7 @@ void MainWindow::patchWindow()
|
|||
{
|
||||
if(!DbgIsDebugging())
|
||||
{
|
||||
QMessageBox msg(QMessageBox::Critical, tr("Error!"), tr("Patches cannot be shown when not debugging..."));
|
||||
msg.setWindowIcon(QIcon(":/icons/images/compile-error.png"));
|
||||
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
msg.exec();
|
||||
SimpleErrorBox(this, tr("Error!"), tr("Patches cannot be shown when not debugging..."));
|
||||
return;
|
||||
}
|
||||
GuiUpdatePatches();
|
||||
|
@ -1242,6 +1254,24 @@ void MainWindow::reportBug()
|
|||
QDesktopServices::openUrl(QUrl("http://report.x64dbg.com"));
|
||||
}
|
||||
|
||||
void MainWindow::crashDump()
|
||||
{
|
||||
QMessageBox msg(QMessageBox::Critical, tr("Generate crash dump"), tr("This action will crash the debugger and generate a crash dump. You will LOSE ALL YOUR DATA. Do you really want to continue?"));
|
||||
msg.setWindowIcon(QIcon(":/icons/images/fatal-error.png"));
|
||||
msg.setParent(this, Qt::Dialog);
|
||||
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
msg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
msg.setDefaultButton(QMessageBox::Cancel);
|
||||
if(msg.exec() != QMessageBox::Ok)
|
||||
return;
|
||||
|
||||
// Fatal error
|
||||
__debugbreak();
|
||||
|
||||
// Congratulations! We survived a fatal error!
|
||||
SimpleWarningBox(this, "Have fun debugging the debugger!", "Debugger detected!");
|
||||
}
|
||||
|
||||
void MainWindow::displayAttach()
|
||||
{
|
||||
AttachDialog attach(this);
|
||||
|
@ -1283,18 +1313,12 @@ void MainWindow::changeCommandLine()
|
|||
return; //pressed cancel
|
||||
|
||||
if(!DbgFunctions()->SetCmdline((char*)mLineEdit.editText.toUtf8().constData()))
|
||||
{
|
||||
QMessageBox msg(QMessageBox::Warning, tr("Error!"), tr("Could not set command line!"));
|
||||
msg.setWindowIcon(QIcon(":/icons/images/compile-warning.png"));
|
||||
msg.setParent(this, Qt::Dialog);
|
||||
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
msg.exec();
|
||||
}
|
||||
SimpleErrorBox(this, tr("Error!"), tr("Could not set command line!"));
|
||||
else
|
||||
{
|
||||
DbgFunctions()->MemUpdateMap();
|
||||
GuiUpdateMemoryView();
|
||||
GuiAddStatusBarMessage(QString("New command line: " + mLineEdit.editText + "\n").toUtf8().constData());
|
||||
GuiAddStatusBarMessage((tr("New command line: ") + mLineEdit.editText + "\n").toUtf8().constData());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1404,3 +1428,108 @@ void MainWindow::displayHandlesWidget()
|
|||
{
|
||||
showQWidgetTab(mHandlesView);
|
||||
}
|
||||
|
||||
void MainWindow::manageFavourites()
|
||||
{
|
||||
FavouriteTools favToolsDialog(this);
|
||||
favToolsDialog.exec();
|
||||
updateFavouriteTools();
|
||||
}
|
||||
|
||||
void MainWindow::updateFavouriteTools()
|
||||
{
|
||||
char buffer[MAX_SETTING_SIZE];
|
||||
bool isanythingexists = false;
|
||||
ui->menuFavourites->clear();
|
||||
for(unsigned int i = 1; BridgeSettingGet("Favourite", QString("Tool%1").arg(i).toUtf8().constData(), buffer); i++)
|
||||
{
|
||||
QString exePath = QString::fromUtf8(buffer);
|
||||
QAction* newAction = new QAction(this);
|
||||
newAction->setData(QVariant(QString("Tool,%1").arg(exePath)));
|
||||
if(BridgeSettingGet("Favourite", QString("ToolShortcut%1").arg(i).toUtf8().constData(), buffer))
|
||||
if(*buffer && strcmp(buffer, "NOT_SET") != 0)
|
||||
setGlobalShortcut(newAction, QKeySequence(QString::fromUtf8(buffer)));
|
||||
if(BridgeSettingGet("Favourite", QString("ToolDescription%1").arg(i).toUtf8().constData(), buffer))
|
||||
newAction->setText(QString::fromUtf8(buffer));
|
||||
else
|
||||
newAction->setText(exePath);
|
||||
connect(newAction, SIGNAL(triggered()), this, SLOT(clickFavouriteTool()));
|
||||
ui->menuFavourites->addAction(newAction);
|
||||
isanythingexists = true;
|
||||
}
|
||||
if(isanythingexists)
|
||||
{
|
||||
isanythingexists = false;
|
||||
ui->menuFavourites->addSeparator();
|
||||
}
|
||||
for(unsigned int i = 1; BridgeSettingGet("Favourite", QString("Script%1").arg(i).toUtf8().constData(), buffer); i++)
|
||||
{
|
||||
QString scriptPath = QString::fromUtf8(buffer);
|
||||
QAction* newAction = new QAction(this);
|
||||
newAction->setData(QVariant(QString("Script,%1").arg(scriptPath)));
|
||||
if(BridgeSettingGet("Favourite", QString("ScriptShortcut%1").arg(i).toUtf8().constData(), buffer))
|
||||
if(*buffer && strcmp(buffer, "NOT_SET") != 0)
|
||||
setGlobalShortcut(newAction, QKeySequence(QString::fromUtf8(buffer)));
|
||||
if(BridgeSettingGet("Favourite", QString("ScriptDescription%1").arg(i).toUtf8().constData(), buffer))
|
||||
newAction->setText(QString::fromUtf8(buffer));
|
||||
else
|
||||
newAction->setText(scriptPath);
|
||||
connect(newAction, SIGNAL(triggered()), this, SLOT(clickFavouriteTool()));
|
||||
ui->menuFavourites->addAction(newAction);
|
||||
isanythingexists = true;
|
||||
}
|
||||
if(isanythingexists)
|
||||
{
|
||||
isanythingexists = false;
|
||||
ui->menuFavourites->addSeparator();
|
||||
}
|
||||
for(unsigned int i = 1; BridgeSettingGet("Favourite", QString("Command%1").arg(i).toUtf8().constData(), buffer); i++)
|
||||
{
|
||||
QAction* newAction = new QAction(QString::fromUtf8(buffer), this);
|
||||
newAction->setData(QVariant(QString("Command")));
|
||||
if(BridgeSettingGet("Favourite", QString("CommandShortcut%1").arg(i).toUtf8().constData(), buffer))
|
||||
if(*buffer && strcmp(buffer, "NOT_SET") != 0)
|
||||
setGlobalShortcut(newAction, QKeySequence(QString::fromUtf8(buffer)));
|
||||
connect(newAction, SIGNAL(triggered()), this, SLOT(clickFavouriteTool()));
|
||||
ui->menuFavourites->addAction(newAction);
|
||||
isanythingexists = true;
|
||||
}
|
||||
if(isanythingexists)
|
||||
ui->menuFavourites->addSeparator();
|
||||
actionManageFavourites = new QAction(QIcon(":/icons/images/star.png"), tr("Manage Favourite Tools"), this);
|
||||
ui->menuFavourites->addAction(actionManageFavourites);
|
||||
setGlobalShortcut(actionManageFavourites, ConfigShortcut("FavouritesManage"));
|
||||
connect(ui->menuFavourites->actions().last(), SIGNAL(triggered()), this, SLOT(manageFavourites()));
|
||||
}
|
||||
|
||||
void MainWindow::clickFavouriteTool()
|
||||
{
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
if(action == nullptr)
|
||||
throw std::exception("Bad favourite tool shortcut action");
|
||||
QString data = action->data().toString();
|
||||
if(data.startsWith("Tool,"))
|
||||
{
|
||||
QString toolPath = data.mid(5);
|
||||
duint PID = DbgValFromString("$pid");
|
||||
toolPath.replace(QString("%PID%"), QString::number(PID), Qt::CaseInsensitive);
|
||||
PROCESS_INFORMATION procinfo;
|
||||
STARTUPINFO startupinfo;
|
||||
memset(&procinfo, 0, sizeof(PROCESS_INFORMATION));
|
||||
memset(&startupinfo, 0, sizeof(startupinfo));
|
||||
startupinfo.cb = sizeof(startupinfo);
|
||||
CreateProcessW(nullptr, (LPWSTR)toolPath.toStdWString().c_str(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupinfo, &procinfo);
|
||||
CloseHandle(procinfo.hThread);
|
||||
CloseHandle(procinfo.hProcess);
|
||||
}
|
||||
else if(data.startsWith("Script,"))
|
||||
{
|
||||
QString scriptPath = data.mid(7);
|
||||
DbgScriptUnload();
|
||||
DbgScriptLoad(scriptPath.toUtf8().constData());
|
||||
}
|
||||
else if(data.compare("Command") == 0)
|
||||
{
|
||||
DbgCmdExec(action->text().toUtf8().constData());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ public slots:
|
|||
void execTRTOBT();
|
||||
void execTRTIIT();
|
||||
void execTRTOIT();
|
||||
void execInstrUndo();
|
||||
void displayCpuWidget();
|
||||
void displaySymbolWidget();
|
||||
void displaySourceViewWidget();
|
||||
|
@ -116,6 +117,7 @@ public slots:
|
|||
void displayBookmarks();
|
||||
void displayFunctions();
|
||||
void checkUpdates();
|
||||
void crashDump();
|
||||
void displayCallstack();
|
||||
void displaySEHChain();
|
||||
void setGlobalShortcut(QAction* action, const QKeySequence & key);
|
||||
|
@ -140,6 +142,9 @@ public slots:
|
|||
void dbgStateChangedSlot(DBGSTATE state);
|
||||
void displayNotesWidget();
|
||||
void displayHandlesWidget();
|
||||
void manageFavourites();
|
||||
void updateFavouriteTools();
|
||||
void clickFavouriteTool();
|
||||
|
||||
private:
|
||||
Ui::MainWindow* ui;
|
||||
|
@ -175,6 +180,8 @@ private:
|
|||
int mMaxMRU;
|
||||
unsigned int lastException;
|
||||
|
||||
QAction* actionManageFavourites;
|
||||
|
||||
void loadMRUList(int maxItems);
|
||||
void saveMRUList();
|
||||
void addMRUEntry(QString entry);
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
<addaction name="actionSkipNextInstruction"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuTrace_record"/>
|
||||
<addaction name="actionInstrUndo"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCommand"/>
|
||||
<addaction name="separator"/>
|
||||
|
@ -131,6 +132,8 @@
|
|||
<addaction name="actionManual"/>
|
||||
<addaction name="actionFaq"/>
|
||||
<addaction name="actionAbout"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCrashDump"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuPlugins">
|
||||
<property name="title">
|
||||
|
@ -148,10 +151,16 @@
|
|||
<addaction name="actionTopmost"/>
|
||||
<addaction name="actionReloadStylesheet"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuFavourites">
|
||||
<property name="title">
|
||||
<string>Favourites</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuDebug"/>
|
||||
<addaction name="menuPlugins"/>
|
||||
<addaction name="menuFavourites"/>
|
||||
<addaction name="menuOptions"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
|
@ -898,6 +907,25 @@
|
|||
<string>Run until e&xpression</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInstrUndo">
|
||||
<property name="text">
|
||||
<string>Undo last instruction</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCrashDump">
|
||||
<property name="icon">
|
||||
<iconset resource="../../resource.qrc">
|
||||
<normaloff>:/icons/images/fatal-error.png</normaloff>:/icons/images/fatal-error.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate crash dump</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionManageFavourite">
|
||||
<property name="text">
|
||||
<string>&Manage Favourite Tools...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
#include "Bridge.h"
|
||||
#include "WatchView.h"
|
||||
#include "CPUMultiDump.h"
|
||||
#include "MiscUtil.h"
|
||||
|
||||
WatchView::WatchView(CPUMultiDump* parent) : StdTable(parent)
|
||||
{
|
||||
int charWidth = getCharWidth();
|
||||
addColumnAt(8 + charWidth * 12, tr("Name"), false);
|
||||
addColumnAt(8 + charWidth * 20, tr("Expression"), false);
|
||||
addColumnAt(8 + charWidth * sizeof(duint) * 2, tr("Value"), false);
|
||||
addColumnAt(8 + charWidth * 8, tr("Type"), false);
|
||||
addColumnAt(150, tr("Watchdog Mode"), false);
|
||||
addColumnAt(30, tr("ID"), false);
|
||||
|
||||
connect(Bridge::getBridge(), SIGNAL(updateWatch()), this, SLOT(updateWatch()));
|
||||
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
|
||||
|
||||
updateColors();
|
||||
setupContextMenu();
|
||||
setDrawDebugOnly(true);
|
||||
}
|
||||
|
||||
void WatchView::updateWatch()
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
{
|
||||
setRowCount(0);
|
||||
return;
|
||||
}
|
||||
BridgeList<WATCHINFO> WatchList;
|
||||
DbgGetWatchList(&WatchList);
|
||||
setRowCount(WatchList.Count());
|
||||
for(int i = 0; i < WatchList.Count(); i++)
|
||||
{
|
||||
setCellContent(i, 0, QString::fromUtf8(WatchList[i].WatchName));
|
||||
setCellContent(i, 1, QString::fromUtf8(WatchList[i].Expression));
|
||||
switch(WatchList[i].varType)
|
||||
{
|
||||
case WATCHVARTYPE::TYPE_UINT:
|
||||
setCellContent(i, 3, "UINT");
|
||||
setCellContent(i, 2, ToPtrString(WatchList[i].value));
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_INT:
|
||||
setCellContent(i, 3, "INT");
|
||||
setCellContent(i, 2, QString::number((dsint)WatchList[i].value));
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_FLOAT:
|
||||
setCellContent(i, 3, "FLOAT");
|
||||
setCellContent(i, 2, QString::number(*(float*)&WatchList[i].value));
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_ASCII:
|
||||
setCellContent(i, 3, "ASCII");
|
||||
{
|
||||
char buffer[128];
|
||||
// zero the buffer
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if(DbgMemRead(WatchList[i].value, (unsigned char*)buffer, sizeof(buffer) - 1))
|
||||
{
|
||||
// convert the ASCII string to QString
|
||||
QString text = QString::fromLocal8Bit(buffer);
|
||||
if(strlen(buffer) == sizeof(buffer) - 1)
|
||||
text.append("...");
|
||||
// remove CRLF
|
||||
text.replace(QChar('\x13'), "\\r");
|
||||
text.replace(QChar('\x10'), "\\n");
|
||||
setCellContent(i, 2, text);
|
||||
}
|
||||
else
|
||||
setCellContent(i, 2, tr("%1 is not readable.").arg(ToPtrString(WatchList[i].value)));
|
||||
}
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_UNICODE:
|
||||
setCellContent(i, 3, "UNICODE");
|
||||
{
|
||||
unsigned short buffer[128];
|
||||
// zero the buffer
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if(DbgMemRead(WatchList[i].value, (unsigned char*)buffer, sizeof(buffer) - sizeof(unsigned short)))
|
||||
{
|
||||
QString text = QString::fromUtf16(buffer);
|
||||
size_t size = text.size();
|
||||
// Check if the last character is an incomplete UTF-16 surrogate.
|
||||
if(text.at(text.size() - 1).isHighSurrogate())
|
||||
text.chop(text.size() - 1); // Delete the incomplete surrogate.
|
||||
// Check if something is truncated.
|
||||
if(size == sizeof(buffer) / sizeof(unsigned short) - 1)
|
||||
text.append("...");
|
||||
// remove CRLF
|
||||
text.replace(QChar('\x13'), "\\r");
|
||||
text.replace(QChar('\x10'), "\\n");
|
||||
setCellContent(i, 2, text);
|
||||
}
|
||||
else
|
||||
setCellContent(i, 2, tr("%1 is not readable.").arg(ToPtrString(WatchList[i].value)));
|
||||
}
|
||||
break;
|
||||
case WATCHVARTYPE::TYPE_INVALID:
|
||||
default:
|
||||
setCellContent(i, 3, "INVALID");
|
||||
setCellContent(i, 2, "");
|
||||
break;
|
||||
}
|
||||
switch(WatchList[i].watchdogMode)
|
||||
{
|
||||
case WATCHDOGMODE::MODE_DISABLED:
|
||||
default:
|
||||
setCellContent(i, 4, tr("Disabled"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_CHANGED:
|
||||
setCellContent(i, 4, tr("Changed"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_ISTRUE:
|
||||
setCellContent(i, 4, tr("Is true"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_ISFALSE:
|
||||
setCellContent(i, 4, tr("Is false"));
|
||||
break;
|
||||
case WATCHDOGMODE::MODE_UNCHANGED:
|
||||
setCellContent(i, 4, tr("Not changed"));
|
||||
break;
|
||||
}
|
||||
setCellContent(i, 5, QString::number(WatchList[i].id));
|
||||
}
|
||||
reloadData();
|
||||
}
|
||||
|
||||
void WatchView::updateColors()
|
||||
{
|
||||
mWatchTriggeredColor = QPen(ConfigColor("WatchTriggeredColor"));
|
||||
mWatchTriggeredBackgroundColor = QBrush(ConfigColor("WatchTriggeredBackgroundColor"));
|
||||
StdTable::updateColors();
|
||||
}
|
||||
|
||||
void WatchView::setupContextMenu()
|
||||
{
|
||||
mMenu = new MenuBuilder(this, [](QMenu*)
|
||||
{
|
||||
return DbgIsDebugging();
|
||||
});
|
||||
mMenu->addAction(makeAction(tr("&Add..."), SLOT(addWatchSlot())));
|
||||
mMenu->addAction(makeAction(tr("&Delete"), SLOT(delWatchSlot())));
|
||||
mMenu->addAction(makeAction(tr("Rename"), SLOT(renameWatchSlot())));
|
||||
mMenu->addAction(makeAction(tr("&Edit..."), SLOT(editWatchSlot())));
|
||||
QMenu* watchdogMenu = new QMenu(tr("Watchdog"), this);
|
||||
watchdogMenu->addAction(makeAction(QIcon(":/icons/images/close-all-tabs.png"), tr("Disabled"), SLOT(watchdogDisableSlot())));
|
||||
watchdogMenu->addSeparator();
|
||||
watchdogMenu->addAction(makeAction(tr("Changed"), SLOT(watchdogChangedSlot())));
|
||||
watchdogMenu->addAction(makeAction(tr("Not changed"), SLOT(watchdogUnchangedSlot())));
|
||||
watchdogMenu->addAction(makeAction(tr("Is true"), SLOT(watchdogIsTrueSlot())));
|
||||
watchdogMenu->addAction(makeAction(tr("Is false"), SLOT(watchdogIsFalseSlot())));
|
||||
mMenu->addMenu(watchdogMenu);
|
||||
}
|
||||
|
||||
QString WatchView::getSelectedId()
|
||||
{
|
||||
return getCellContent(getInitialSelection(), 5);
|
||||
}
|
||||
|
||||
QString WatchView::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
{
|
||||
QString ret = StdTable::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);
|
||||
const dsint row = rowBase + rowOffset;
|
||||
if(row != getInitialSelection() && DbgFunctions()->WatchIsWatchdogTriggered(getCellContent(row, 5).toUInt()))
|
||||
{
|
||||
painter->fillRect(QRect(x, y, w, h), mWatchTriggeredBackgroundColor);
|
||||
painter->setPen(mWatchTriggeredColor); //white text
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, ret);
|
||||
return "";
|
||||
}
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
//SLOTS
|
||||
|
||||
void WatchView::contextMenuSlot(const QPoint & pos)
|
||||
{
|
||||
QMenu wMenu(this);
|
||||
mMenu->build(&wMenu);
|
||||
wMenu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void WatchView::addWatchSlot()
|
||||
{
|
||||
QString name;
|
||||
if(SimpleInputBox(this, tr("Enter the expression to watch"), "", name))
|
||||
DbgCmdExecDirect(QString("AddWatch ").append(name).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::delWatchSlot()
|
||||
{
|
||||
DbgCmdExecDirect(QString("DelWatch ").append(getSelectedId()).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::renameWatchSlot()
|
||||
{
|
||||
QString name;
|
||||
if(SimpleInputBox(this, tr("Enter the name of the watch variable"), getCellContent(getInitialSelection(), 0), name))
|
||||
DbgCmdExecDirect(QString("SetWatchName ").append(getSelectedId() + "," + name).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::editWatchSlot()
|
||||
{
|
||||
QString expr;
|
||||
if(SimpleInputBox(this, tr("Enter the expression to watch"), "", expr))
|
||||
DbgCmdExecDirect(QString("SetWatchExpression ").append(getSelectedId()).append(",").append(expr).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::watchdogDisableSlot()
|
||||
{
|
||||
DbgCmdExecDirect(QString("SetWatchdog %1, \"disabled\"").arg(getSelectedId()).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::watchdogChangedSlot()
|
||||
{
|
||||
DbgCmdExecDirect(QString("SetWatchdog %1, \"changed\"").arg(getSelectedId()).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::watchdogUnchangedSlot()
|
||||
{
|
||||
DbgCmdExecDirect(QString("SetWatchdog %1, \"unchanged\"").arg(getSelectedId()).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::watchdogIsTrueSlot()
|
||||
{
|
||||
DbgCmdExecDirect(QString("SetWatchdog %1, \"istrue\"").arg(getSelectedId()).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
||||
|
||||
void WatchView::watchdogIsFalseSlot()
|
||||
{
|
||||
DbgCmdExecDirect(QString("SetWatchdog %1, \"isfalse\"").arg(getSelectedId()).toUtf8().constData());
|
||||
updateWatch();
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef WATCHVIEW_H
|
||||
#define WATCHVIEW_H
|
||||
#include "StdTable.h"
|
||||
#include "MenuBuilder.h"
|
||||
|
||||
class CPUMultiDump;
|
||||
|
||||
class WatchView : public StdTable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WatchView(CPUMultiDump* parent);
|
||||
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h);
|
||||
void updateColors();
|
||||
|
||||
public slots:
|
||||
void contextMenuSlot(const QPoint & event);
|
||||
void updateWatch();
|
||||
void addWatchSlot();
|
||||
void delWatchSlot();
|
||||
void renameWatchSlot();
|
||||
void editWatchSlot();
|
||||
void watchdogDisableSlot();
|
||||
void watchdogChangedSlot();
|
||||
void watchdogUnchangedSlot();
|
||||
void watchdogIsTrueSlot();
|
||||
void watchdogIsFalseSlot();
|
||||
|
||||
protected:
|
||||
void setupContextMenu();
|
||||
|
||||
QString getSelectedId();
|
||||
|
||||
MenuBuilder* mMenu;
|
||||
QPen mWatchTriggeredColor;
|
||||
QBrush mWatchTriggeredBackgroundColor;
|
||||
};
|
||||
|
||||
#endif // WATCHVIEW_H
|
|
@ -161,6 +161,8 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
|
|||
|
||||
defaultColors.insert("ThreadCurrentColor", QColor("#FFFFFF"));
|
||||
defaultColors.insert("ThreadCurrentBackgroundColor", QColor("#000000"));
|
||||
defaultColors.insert("WatchTriggeredColor", QColor("#FF0000"));
|
||||
defaultColors.insert("WatchTriggeredBackgroundColor", QColor("#FFF8F0"));
|
||||
defaultColors.insert("MemoryMapBreakpointColor", QColor("#000000"));
|
||||
defaultColors.insert("MemoryMapBreakpointBackgroundColor", QColor("#FF0000"));
|
||||
defaultColors.insert("MemoryMapCipColor", QColor("#FFFFFF"));
|
||||
|
@ -199,6 +201,7 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
|
|||
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "CPUStack", 3);
|
||||
for(int i = 1; i <= 5; i++)
|
||||
AbstractTableView::setupColumnConfigDefaultValue(guiUint, QString("CPUDump%1").arg(i), 4);
|
||||
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Watch1", 6);
|
||||
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "SoftwareBreakpoint", 10);
|
||||
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "HardwareBreakpoint", 10);
|
||||
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "MemoryBreakpoint", 10);
|
||||
|
@ -296,13 +299,17 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
|
|||
defaultShortcuts.insert("DebugTraceOverConditional", Shortcut(tr("Debug -> Trace Over Conditional"), ""));
|
||||
defaultShortcuts.insert("DebugEnableTraceRecordBit", Shortcut(tr("Debug -> Trace Record -> Bit"), ""));
|
||||
defaultShortcuts.insert("DebugTraceRecordNone", Shortcut(tr("Debug -> Trace Record -> None"), ""));
|
||||
defaultShortcuts.insert("DebugInstrUndo", Shortcut(tr("Debug -> Undo instruction"), "Alt+U"));
|
||||
|
||||
defaultShortcuts.insert("PluginsScylla", Shortcut(tr("Plugins -> Scylla"), "Ctrl+I", true));
|
||||
|
||||
defaultShortcuts.insert("FavouritesManage", Shortcut(tr("Favourites -> Manage Favourite Tools"), "", true));
|
||||
|
||||
defaultShortcuts.insert("OptionsPreferences", Shortcut(tr("Options -> Preferences"), "", true));
|
||||
defaultShortcuts.insert("OptionsAppearance", Shortcut(tr("Options -> Appearance"), "", true));
|
||||
defaultShortcuts.insert("OptionsShortcuts", Shortcut(tr("Options -> Shortcuts"), "", true));
|
||||
defaultShortcuts.insert("OptionsTopmost", Shortcut(tr("Options -> Topmost"), "Ctrl+F5", true));
|
||||
defaultShortcuts.insert("OptionsReloadStylesheet", Shortcut(tr("Options -> Reload style.css") , "", true));
|
||||
|
||||
defaultShortcuts.insert("HelpAbout", Shortcut(tr("Help -> About"), "", true));
|
||||
defaultShortcuts.insert("HelpDonate", Shortcut(tr("Help -> Donate"), "", true));
|
||||
|
@ -310,6 +317,7 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
|
|||
defaultShortcuts.insert("HelpCalculator", Shortcut(tr("Help -> Calculator"), "?"));
|
||||
defaultShortcuts.insert("HelpReportBug", Shortcut(tr("Help -> Report Bug"), "", true));
|
||||
defaultShortcuts.insert("HelpManual", Shortcut(tr("Help -> Manual"), "F1", true));
|
||||
defaultShortcuts.insert("HelpCrashDump", Shortcut(tr("Help -> Generate Crash Dump"), "", true));
|
||||
|
||||
defaultShortcuts.insert("ActionFindStrings", Shortcut(tr("Actions -> Find Strings"), "", true));
|
||||
defaultShortcuts.insert("ActionFindIntermodularCalls", Shortcut(tr("Actions -> Find Intermodular Calls"), "", true));
|
||||
|
|
|
@ -23,7 +23,7 @@ QByteArray & ByteReverse(QByteArray & array)
|
|||
return array;
|
||||
}
|
||||
|
||||
QString SimpleInputBox(QWidget* parent, const QString & title, QString defaultValue)
|
||||
bool SimpleInputBox(QWidget* parent, const QString & title, QString defaultValue, QString & output)
|
||||
{
|
||||
LineEditDialog mEdit(parent);
|
||||
mEdit.setWindowIcon(parent->windowIcon());
|
||||
|
@ -31,9 +31,12 @@ QString SimpleInputBox(QWidget* parent, const QString & title, QString defaultVa
|
|||
mEdit.setWindowTitle(title);
|
||||
mEdit.setCheckBox(false);
|
||||
if(mEdit.exec() == QDialog::Accepted)
|
||||
return mEdit.editText;
|
||||
{
|
||||
output = mEdit.editText;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
return false;
|
||||
}
|
||||
|
||||
void SimpleErrorBox(QWidget* parent, const QString & title, const QString & text)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
void SetApplicationIcon(WId winId);
|
||||
QByteArray & ByteReverse(QByteArray & array);
|
||||
QString SimpleInputBox(QWidget* parent, const QString & title, QString defaultValue = "");
|
||||
bool SimpleInputBox(QWidget* parent, const QString & title, QString defaultValue, QString & output);
|
||||
void SimpleErrorBox(QWidget* parent, const QString & title, const QString & text);
|
||||
void SimpleWarningBox(QWidget* parent, const QString & title, const QString & text);
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 757 B |
|
@ -217,6 +217,8 @@
|
|||
<file>images/thread-setpriority_alt.png</file>
|
||||
<file>images/thread-switch.png</file>
|
||||
<file>images/unicode.png</file>
|
||||
<file>images/fatal-error.png</file>
|
||||
<file>images/star.png</file>
|
||||
<file>images/16bit.png</file>
|
||||
<file>images/16bit-short.png</file>
|
||||
<file>images/32bit.png</file>
|
||||
|
|
|
@ -156,7 +156,10 @@ SOURCES += \
|
|||
Src/Gui/CodepageSelectionDialog.cpp \
|
||||
Src/Gui/ColumnReorderDialog.cpp \
|
||||
Src/Utils/EncodeMap.cpp \
|
||||
Src/Utils/CodeFolding.cpp
|
||||
Src/Utils/CodeFolding.cpp \
|
||||
Src/Gui/WatchView.cpp \
|
||||
Src/Gui/FavouriteTools.cpp \
|
||||
Src/Gui/BrowseDialog.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
|
@ -254,7 +257,10 @@ HEADERS += \
|
|||
Src/Utils/CachedFontMetrics.h \
|
||||
Src/Gui/ColumnReorderDialog.h \
|
||||
Src/Utils/EncodeMap.h \
|
||||
Src/Utils/CodeFolding.h
|
||||
Src/Utils/CodeFolding.h \
|
||||
Src/Gui/WatchView.h \
|
||||
Src/Gui/FavouriteTools.h \
|
||||
Src/Gui/BrowseDialog.h
|
||||
|
||||
|
||||
FORMS += \
|
||||
|
@ -287,7 +293,9 @@ FORMS += \
|
|||
Src/Gui/EditFloatRegister.ui \
|
||||
Src/Gui/XrefBrowseDialog.ui \
|
||||
Src/Gui/CodepageSelectionDialog.ui \
|
||||
Src/Gui/ColumnReorderDialog.ui
|
||||
Src/Gui/ColumnReorderDialog.ui \
|
||||
Src/Gui/FavouriteTools.ui \
|
||||
Src/Gui/BrowseDialog.ui
|
||||
|
||||
TRANSLATIONS = \
|
||||
Translations/x64dbg.ts
|
||||
|
|
Loading…
Reference in New Issue