1
0
Fork 0

Merge pull request #651 from torusrxxx/development

Conditional breakpoint

This will make a lot of people happy, thanks a lot!
This commit is contained in:
Duncan Ogilvie 2016-05-22 17:34:01 +02:00
commit c1f505b46e
15 changed files with 1110 additions and 211 deletions

View File

@ -61,6 +61,8 @@ BRIDGE_IMPEXP int BridgeGetDbgVersion();
#define MAX_MODULE_SIZE 256 #define MAX_MODULE_SIZE 256
#define MAX_IMPORT_SIZE 65536 #define MAX_IMPORT_SIZE 65536
#define MAX_BREAKPOINT_SIZE 256 #define MAX_BREAKPOINT_SIZE 256
#define MAX_CONDITIONAL_EXPR_SIZE 256
#define MAX_CONDITIONAL_LOG_SIZE 256
#define MAX_SCRIPT_LINE_SIZE 2048 #define MAX_SCRIPT_LINE_SIZE 2048
#define MAX_THREAD_NAME_SIZE 256 #define MAX_THREAD_NAME_SIZE 256
#define MAX_STRING_SIZE 512 #define MAX_STRING_SIZE 512
@ -321,6 +323,12 @@ typedef struct
char name[MAX_BREAKPOINT_SIZE]; char name[MAX_BREAKPOINT_SIZE];
char mod[MAX_MODULE_SIZE]; char mod[MAX_MODULE_SIZE];
unsigned short slot; unsigned short slot;
// extended part
unsigned int hitCount;
bool fastResume;
char condition[MAX_CONDITIONAL_EXPR_SIZE];
char log[MAX_CONDITIONAL_LOG_SIZE];
char hitCmd[MAX_CONDITIONAL_EXPR_SIZE];
} BRIDGEBP; } BRIDGEBP;
typedef struct typedef struct
@ -844,7 +852,7 @@ typedef struct
} SCRIPTTYPEINFO; } SCRIPTTYPEINFO;
//GUI functions //GUI functions
// TODO: Most of these functions are not unicode-aware. Rewrite them. //code page is utf8
BRIDGE_IMPEXP void GuiDisasmAt(duint addr, duint cip); BRIDGE_IMPEXP void GuiDisasmAt(duint addr, duint cip);
BRIDGE_IMPEXP void GuiSetDebugState(DBGSTATE state); BRIDGE_IMPEXP void GuiSetDebugState(DBGSTATE state);
BRIDGE_IMPEXP void GuiAddLogMessage(const char* msg); BRIDGE_IMPEXP void GuiAddLogMessage(const char* msg);

View File

@ -568,64 +568,27 @@ extern "C" DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* bpmap)
int retcount = 0; int retcount = 0;
std::vector<BRIDGEBP> bridgeList; std::vector<BRIDGEBP> bridgeList;
BRIDGEBP curBp; BRIDGEBP curBp;
BP_TYPE currentBpType;
switch(type)
{
case bp_normal:
currentBpType = BPNORMAL;
break;
case bp_hardware:
currentBpType = BPHARDWARE;
break;
case bp_memory:
currentBpType = BPMEMORY;
break;
default:
return 0;
}
unsigned short slot = 0; unsigned short slot = 0;
for(int i = 0; i < bpcount; i++) for(int i = 0; i < bpcount; i++)
{ {
memset(&curBp, 0, sizeof(BRIDGEBP)); if(list[i].type != currentBpType)
switch(type) continue;
{ BpToBridge(&list[i], &curBp);
case bp_none: //all types
break;
case bp_normal: //normal
if(list[i].type != BPNORMAL)
continue;
break;
case bp_hardware: //hardware
if(list[i].type != BPHARDWARE)
continue;
break;
case bp_memory: //memory
if(list[i].type != BPMEMORY)
continue;
break;
default:
return 0;
}
switch(list[i].type)
{
case BPNORMAL:
curBp.type = bp_normal;
break;
case BPHARDWARE:
curBp.type = bp_hardware;
break;
case BPMEMORY:
curBp.type = bp_memory;
break;
}
switch(((DWORD)list[i].titantype) >> 8)
{
case UE_DR0:
slot = 0;
break;
case UE_DR1:
slot = 1;
break;
case UE_DR2:
slot = 2;
break;
case UE_DR3:
slot = 3;
break;
}
curBp.addr = list[i].addr;
curBp.enabled = list[i].enabled;
curBp.active = list[i].active;
strcpy_s(curBp.mod, list[i].mod);
strcpy_s(curBp.name, list[i].name);
curBp.singleshoot = list[i].singleshoot;
curBp.slot = slot;
bridgeList.push_back(curBp); bridgeList.push_back(curBp);
retcount++; retcount++;
} }

View File

@ -8,6 +8,8 @@
#include "memory.h" #include "memory.h"
#include "threading.h" #include "threading.h"
#include "module.h" #include "module.h"
#include "value.h"
#include "debugger.h"
typedef std::pair<BP_TYPE, duint> BreakpointKey; typedef std::pair<BP_TYPE, duint> BreakpointKey;
std::map<BreakpointKey, BREAKPOINT> breakpoints; std::map<BreakpointKey, BREAKPOINT> breakpoints;
@ -121,7 +123,7 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
for(auto & i : breakpoints) for(auto & i : breakpoints)
{ {
// Do the names match? // Do the names match?
if(strcmp(Name, i.second.name) != 0) if(_stricmp(Name, i.second.name) != 0)
continue; continue;
// Fill out the optional user buffer // Fill out the optional user buffer
@ -139,6 +141,17 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
return false; return false;
} }
bool BpGetAny(BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
{
if(BpGet(0, Type, Name, Bp))
return true;
duint addr;
if(valfromstring(Name, &addr))
if(BpGet(addr, Type, 0, Bp))
return true;
return false;
}
bool BpDelete(duint Address, BP_TYPE Type) bool BpDelete(duint Address, BP_TYPE Type)
{ {
ASSERT_DEBUGGING("Command function call"); ASSERT_DEBUGGING("Command function call");
@ -204,6 +217,66 @@ bool BpSetTitanType(duint Address, BP_TYPE Type, int TitanType)
return true; return true;
} }
bool BpSetCondition(duint Address, BP_TYPE Type, const char* Condition)
{
ASSERT_DEBUGGING("Command function call");
EXCLUSIVE_ACQUIRE(LockBreakpoints);
// Set breakpoint condition
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
if(!bpInfo)
return false;
strcpy_s(bpInfo->condition, Condition);
return true;
}
bool BpSetLogText(duint Address, BP_TYPE Type, const char* Log)
{
ASSERT_DEBUGGING("Command function call");
EXCLUSIVE_ACQUIRE(LockBreakpoints);
// Set breakpoint log
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
if(!bpInfo)
return false;
strcpy_s(bpInfo->logText, MAX_CONDITIONAL_LOG_SIZE, Log);
return true;
}
bool BpSetHitCommand(duint Address, BP_TYPE Type, const char* Cmd)
{
ASSERT_DEBUGGING("Command function call");
EXCLUSIVE_ACQUIRE(LockBreakpoints);
// Set breakpoint hit command
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
if(!bpInfo)
return false;
strcpy_s(bpInfo->hitcmd, MAX_CONDITIONAL_EXPR_SIZE, Cmd);
return true;
}
bool BpSetFastResume(duint Address, BP_TYPE Type, bool fastResume)
{
ASSERT_DEBUGGING("Command function call");
EXCLUSIVE_ACQUIRE(LockBreakpoints);
// Set breakpoint fast resume
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
if(!bpInfo)
return false;
bpInfo->fastResume = fastResume;
return true;
}
bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module) bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module)
{ {
ASSERT_DEBUGGING("Export call"); ASSERT_DEBUGGING("Export call");
@ -270,6 +343,32 @@ int BpGetCount(BP_TYPE Type, bool EnabledOnly)
return count; return count;
} }
uint32 BpGetHitCount(duint Address, BP_TYPE Type)
{
SHARED_ACQUIRE(LockBreakpoints);
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
if(!bpInfo)
return false;
return bpInfo->hitcount;
}
bool BpResetHitCount(duint Address, BP_TYPE Type, uint32 newHitCount)
{
EXCLUSIVE_ACQUIRE(LockBreakpoints);
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
if(!bpInfo)
return false;
bpInfo->hitcount = newHitCount;
return true;
}
void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp) void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp)
{ {
// //
@ -282,11 +381,16 @@ void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp)
memset(BridgeBp, 0, sizeof(BRIDGEBP)); memset(BridgeBp, 0, sizeof(BRIDGEBP));
strcpy_s(BridgeBp->mod, Bp->mod); strcpy_s(BridgeBp->mod, Bp->mod);
strcpy_s(BridgeBp->name, Bp->name); strcpy_s(BridgeBp->name, Bp->name);
strcpy_s(BridgeBp->condition, Bp->condition);
strcpy_s(BridgeBp->log, Bp->logText);
strcpy_s(BridgeBp->hitCmd, Bp->hitcmd);
BridgeBp->active = Bp->active; BridgeBp->active = Bp->active;
BridgeBp->addr = Bp->addr; BridgeBp->addr = Bp->addr;
BridgeBp->enabled = Bp->enabled; BridgeBp->enabled = Bp->enabled;
BridgeBp->singleshoot = Bp->singleshoot; BridgeBp->singleshoot = Bp->singleshoot;
BridgeBp->fastResume = Bp->fastResume;
BridgeBp->hitCount = Bp->hitcount;
switch(Bp->type) switch(Bp->type)
{ {
@ -295,6 +399,21 @@ void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp)
break; break;
case BPHARDWARE: case BPHARDWARE:
BridgeBp->type = bp_hardware; BridgeBp->type = bp_hardware;
switch(((DWORD)Bp->titantype) >> 8)
{
case UE_DR0:
BridgeBp->slot = 0;
break;
case UE_DR1:
BridgeBp->slot = 1;
break;
case UE_DR2:
BridgeBp->slot = 2;
break;
case UE_DR3:
BridgeBp->slot = 3;
break;
}
break; break;
case BPMEMORY: case BPMEMORY:
BridgeBp->type = bp_memory; BridgeBp->type = bp_memory;
@ -333,6 +452,10 @@ void BpCacheSave(JSON Root)
json_object_set_new(jsonObj, "titantype", json_hex(breakpoint.titantype)); json_object_set_new(jsonObj, "titantype", json_hex(breakpoint.titantype));
json_object_set_new(jsonObj, "name", json_string(breakpoint.name)); json_object_set_new(jsonObj, "name", json_string(breakpoint.name));
json_object_set_new(jsonObj, "module", json_string(breakpoint.mod)); json_object_set_new(jsonObj, "module", json_string(breakpoint.mod));
json_object_set_new(jsonObj, "condition", json_string(breakpoint.condition));
json_object_set_new(jsonObj, "log", json_string(breakpoint.logText));
json_object_set_new(jsonObj, "hitcommand", json_string(breakpoint.hitcmd));
json_object_set_new(jsonObj, "fastresume", json_boolean(true));
json_array_append_new(jsonBreakpoints, jsonObj); json_array_append_new(jsonBreakpoints, jsonObj);
} }
@ -372,15 +495,33 @@ void BpCacheLoad(JSON Root)
breakpoint.titantype = (DWORD)json_hex_value(json_object_get(value, "titantype")); breakpoint.titantype = (DWORD)json_hex_value(json_object_get(value, "titantype"));
// Name // Name
const char* name = json_string_value(json_object_get(value, "name")); const char* text = json_string_value(json_object_get(value, "name"));
if(name) if(text)
strcpy_s(breakpoint.name, name); strcpy_s(breakpoint.name, text);
// Module // Module
const char* mod = json_string_value(json_object_get(value, "module")); const char* mod = json_string_value(json_object_get(value, "module"));
if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE) if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE)
strcpy_s(breakpoint.mod, mod); strcpy_s(breakpoint.mod, mod);
// Condition
text = json_string_value(json_object_get(value, "condition"));
if(text)
strcpy_s(breakpoint.condition, text);
// Log string
text = json_string_value(json_object_get(value, "log"));
if(text)
strcpy_s(breakpoint.logText, text);
// Hit command
text = json_string_value(json_object_get(value, "hitcommand"));
if(text)
strcpy_s(breakpoint.hitcmd, text);
// Fast resume
breakpoint.fastResume = json_boolean_value(json_object_get(value, "fastresume"));
// Build the hash map key: MOD_HASH + ADDRESS // Build the hash map key: MOD_HASH + ADDRESS
duint key = ModHashFromName(breakpoint.mod) + breakpoint.addr; duint key = ModHashFromName(breakpoint.mod) + breakpoint.addr;
breakpoints.insert(std::make_pair(BreakpointKey(breakpoint.type, key), breakpoint)); breakpoints.insert(std::make_pair(BreakpointKey(breakpoint.type, key), breakpoint));
@ -391,4 +532,4 @@ void BpClear()
{ {
EXCLUSIVE_ACQUIRE(LockBreakpoints); EXCLUSIVE_ACQUIRE(LockBreakpoints);
breakpoints.clear(); breakpoints.clear();
} }

View File

@ -28,6 +28,11 @@ struct BREAKPOINT
DWORD titantype; DWORD titantype;
char name[MAX_BREAKPOINT_SIZE]; char name[MAX_BREAKPOINT_SIZE];
char mod[MAX_MODULE_SIZE]; char mod[MAX_MODULE_SIZE];
char condition[MAX_CONDITIONAL_EXPR_SIZE]; // condition to stop. If true, debugger halts.
char logText[MAX_CONDITIONAL_LOG_SIZE]; // text to log.
char hitcmd[MAX_CONDITIONAL_EXPR_SIZE]; // script command to execute.
uint32 hitcount; // hit counter
bool fastResume; // if true, debugger resumes without any GUI/Script/Plugin interaction.
}; };
// Breakpoint enumeration callback // Breakpoint enumeration callback
@ -37,16 +42,23 @@ BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, duint Address);
int BpGetList(std::vector<BREAKPOINT>* List); int BpGetList(std::vector<BREAKPOINT>* List);
bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE Type, DWORD TitanType, const char* Name); bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE Type, DWORD TitanType, const char* Name);
bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp); bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp);
bool BpGetAny(BP_TYPE Type, const char* Name, BREAKPOINT* Bp);
bool BpDelete(duint Address, BP_TYPE Type); bool BpDelete(duint Address, BP_TYPE Type);
bool BpEnable(duint Address, BP_TYPE Type, bool Enable); bool BpEnable(duint Address, BP_TYPE Type, bool Enable);
bool BpSetName(duint Address, BP_TYPE Type, const char* Name); bool BpSetName(duint Address, BP_TYPE Type, const char* Name);
bool BpSetTitanType(duint Address, BP_TYPE Type, int TitanType); bool BpSetTitanType(duint Address, BP_TYPE Type, int TitanType);
bool BpSetCondition(duint Address, BP_TYPE Type, const char* Condition);
bool BpSetLogText(duint Address, BP_TYPE Type, const char* Log);
bool BpSetHitCommand(duint Address, BP_TYPE Type, const char* Cmd);
bool BpSetFastResume(duint Address, BP_TYPE Type, bool fastResume);
bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module); bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module);
bool BpEnumAll(BPENUMCALLBACK EnumCallback); bool BpEnumAll(BPENUMCALLBACK EnumCallback);
int BpGetCount(BP_TYPE Type, bool EnabledOnly = false); int BpGetCount(BP_TYPE Type, bool EnabledOnly = false);
uint32 BpGetHitCount(duint Address, BP_TYPE Type);
bool BpResetHitCount(duint Address, BP_TYPE Type, uint32 newHitCount);
void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp); void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp);
void BpCacheSave(JSON Root); void BpCacheSave(JSON Root);
void BpCacheLoad(JSON Root); void BpCacheLoad(JSON Root);
void BpClear(); void BpClear();
#endif // _BREAKPOINT_H #endif // _BREAKPOINT_H

View File

@ -269,192 +269,285 @@ void DebugUpdateStack(duint dumpAddr, duint csp, bool forceDump)
GuiStackDumpAt(dumpAddr, csp); GuiStackDumpAt(dumpAddr, csp);
} }
void BreakpointProlog(duint condition, BREAKPOINT& bp, PLUG_CB_BREAKPOINT& bpInfo)
{
// update GUI
if(condition != 0)
{
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
}
// plugin interaction
lock(WAITID_RUN);
PLUG_CB_PAUSEDEBUG pauseInfo;
memset(&pauseInfo, 0, sizeof(pauseInfo));
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
plugincbcall(CB_BREAKPOINT, &bpInfo);
// conditional
if(bp.logText[0] != 0)
{
char logText2[MAX_CONDITIONAL_LOG_SIZE + 1];
memcpy(logText2, bp.logText, MAX_CONDITIONAL_LOG_SIZE);
strcat_s(logText2, "\n");
GuiAddLogMessage(logText2);
}
if(bp.hitcmd[0] != 0 && condition != 0)
{
DbgCmdExec(bp.hitcmd);
}
if(condition == 0)
{
unlock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
bSkipExceptions = false;
}
//lock
wait(WAITID_RUN);
}
void cbUserBreakpoint() void cbUserBreakpoint()
{ {
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId); hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
BREAKPOINT* bpPtr;
BREAKPOINT bp; BREAKPOINT bp;
BRIDGEBP pluginBp; BRIDGEBP pluginBp;
PLUG_CB_BREAKPOINT bpInfo; PLUG_CB_BREAKPOINT bpInfo;
bpInfo.breakpoint = 0; ULONG_PTR CIP;
if(!BpGet(GetContextDataEx(hActiveThread, UE_CIP), BPNORMAL, 0, &bp) && bp.enabled) duint condition = 1;
memset(&bpInfo, 0, sizeof(bpInfo));
CIP = GetContextDataEx(hActiveThread, UE_CIP);
bpPtr = BpInfoFromAddr(BPNORMAL, CIP);
if(!(bpPtr && bpPtr->enabled))
dputs("Breakpoint reached not in list!"); dputs("Breakpoint reached not in list!");
else else
{ {
const char* bptype = "INT3"; const char* bptype = "INT3";
int titantype = bp.titantype; // increment hit count
if((titantype & UE_BREAKPOINT_TYPE_UD2) == UE_BREAKPOINT_TYPE_UD2) InterlockedIncrement(&bpPtr->hitcount);
bptype = "UD2"; // condition eval
else if((titantype & UE_BREAKPOINT_TYPE_LONG_INT3) == UE_BREAKPOINT_TYPE_LONG_INT3) bp = *bpPtr;
bptype = "LONG INT3"; bp.addr += ModBaseFromAddr(CIP);
const char* symbolicname = SymGetSymbolicName(bp.addr); //setBpActive(bp);
if(symbolicname)
//if(bp.type == BPHARDWARE) //TODO: properly implement this (check debug registers)
// bp.active = true;
//else
bp.active = MemIsValidReadPtr(bp.addr);
if(bpPtr->condition[0] != 0)
{ {
if(*bp.name) if(*(uint16*)bp.condition == 0x30) // short curcit for condition "0"
dprintf("%s breakpoint \"%s\" at %s (" fhex ")!\n", bptype, bp.name, symbolicname, bp.addr); condition = 0;
else else
dprintf("%s breakpoint at %s (" fhex ")!\n", bptype, symbolicname, bp.addr); valfromstring(bp.condition, &condition); // if this fails, condition remains 1
if(bp.fastResume && condition == 0) // fast resume : ignore GUI/Script/Plugin/Singleshoot/Other
return;
} }
else if(bp.logText[0] == 0 && condition != 0)
{ {
if(*bp.name) int titantype = bp.titantype;
dprintf("%s breakpoint \"%s\" at " fhex "!\n", bptype, bp.name, bp.addr); if((titantype & UE_BREAKPOINT_TYPE_UD2) == UE_BREAKPOINT_TYPE_UD2)
bptype = "UD2";
else if((titantype & UE_BREAKPOINT_TYPE_LONG_INT3) == UE_BREAKPOINT_TYPE_LONG_INT3)
bptype = "LONG INT3";
const char* symbolicname = SymGetSymbolicName(bp.addr);
if(symbolicname)
{
if(*bp.name)
dprintf("%s breakpoint \"%s\" at %s (" fhex ")!\n", bptype, bp.name, symbolicname, bp.addr);
else
dprintf("%s breakpoint at %s (" fhex ")!\n", bptype, symbolicname, bp.addr);
}
else else
dprintf("%s breakpoint at " fhex "!\n", bptype, bp.addr); {
} if(*bp.name)
dprintf("%s breakpoint \"%s\" at " fhex "!\n", bptype, bp.name, bp.addr);
else
dprintf("%s breakpoint at " fhex "!\n", bptype, bp.addr);
}
} // else: BreakpointProlog outputs the log.
if(bp.singleshoot) if(bp.singleshoot)
BpDelete(bp.addr, BPNORMAL); BpDelete(bp.addr, BPNORMAL);
BpToBridge(&bp, &pluginBp); BpToBridge(&bp, &pluginBp);
bpInfo.breakpoint = &pluginBp; bpInfo.breakpoint = &pluginBp;
} }
GuiSetDebugState(paused); BreakpointProlog(condition, bp, bpInfo);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
bSkipExceptions = false;
PLUG_CB_PAUSEDEBUG pauseInfo;
pauseInfo.reserved = 0;
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
plugincbcall(CB_BREAKPOINT, &bpInfo);
wait(WAITID_RUN);
} }
void cbHardwareBreakpoint(void* ExceptionAddress) void cbHardwareBreakpoint(void* ExceptionAddress)
{ {
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId); hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
duint cip = GetContextDataEx(hActiveThread, UE_CIP); BREAKPOINT* bpPtr;
BREAKPOINT bp; BREAKPOINT bp;
BRIDGEBP pluginBp; BRIDGEBP pluginBp;
PLUG_CB_BREAKPOINT bpInfo; PLUG_CB_BREAKPOINT bpInfo;
bpInfo.breakpoint = 0; ULONG_PTR CIP;
if(!BpGet((duint)ExceptionAddress, BPHARDWARE, 0, &bp)) duint condition = 1;
memset(&bpInfo, 0, sizeof(bpInfo));
CIP = GetContextDataEx(hActiveThread, UE_CIP);
bpPtr = BpInfoFromAddr(BPHARDWARE, (duint)ExceptionAddress);
if(!(bpPtr && bpPtr->enabled))
dputs("Hardware breakpoint reached not in list!"); dputs("Hardware breakpoint reached not in list!");
else else
{ {
const char* bpsize = ""; const char* bpsize = "";
switch(TITANGETSIZE(bp.titantype)) //size // increment hit count
InterlockedIncrement(&bpPtr->hitcount);
// condition eval
bp = *bpPtr;
bp.addr += ModBaseFromAddr(CIP);
//setBpActive(bp);
//if(bp.type == BPHARDWARE) //TODO: properly implement this (check debug registers)
bp.active = true;
//else
// bp.active = MemIsValidReadPtr(bp.addr);
if(bpPtr->condition[0] != 0)
{ {
case UE_HARDWARE_SIZE_1: if(*(uint16*)bp.condition == 0x30) // short curcit for condition "0"
bpsize = "byte, "; condition = 0;
break; else
case UE_HARDWARE_SIZE_2: valfromstring(bp.condition, &condition); // if this fails, condition remains 1
bpsize = "word, "; if(bp.fastResume && condition == 0) // fast resume : ignore GUI/Script/Plugin/Singleshoot/Other
break; return;
case UE_HARDWARE_SIZE_4: }
bpsize = "dword, "; if(bp.logText[0] == 0 && condition != 0)
break; {
switch (TITANGETSIZE(bp.titantype)) //size
{
case UE_HARDWARE_SIZE_1:
bpsize = "byte, ";
break;
case UE_HARDWARE_SIZE_2:
bpsize = "word, ";
break;
case UE_HARDWARE_SIZE_4:
bpsize = "dword, ";
break;
#ifdef _WIN64 #ifdef _WIN64
case UE_HARDWARE_SIZE_8: case UE_HARDWARE_SIZE_8:
bpsize = "qword, "; bpsize = "qword, ";
break; break;
#endif //_WIN64 #endif //_WIN64
} }
const char* bptype = ""; const char* bptype = "";
switch(TITANGETTYPE(bp.titantype)) //type switch (TITANGETTYPE(bp.titantype)) //type
{ {
case UE_HARDWARE_EXECUTE: case UE_HARDWARE_EXECUTE:
bptype = "execute"; bptype = "execute";
bpsize = ""; bpsize = "";
break; break;
case UE_HARDWARE_READWRITE: case UE_HARDWARE_READWRITE:
bptype = "read/write"; bptype = "read/write";
break; break;
case UE_HARDWARE_WRITE: case UE_HARDWARE_WRITE:
bptype = "write"; bptype = "write";
break; break;
} }
const char* symbolicname = SymGetSymbolicName(bp.addr); const char* symbolicname = SymGetSymbolicName(bp.addr);
if(symbolicname) if(symbolicname)
{ {
if(*bp.name) if(*bp.name)
dprintf("Hardware breakpoint (%s%s) \"%s\" at %s (" fhex ")!\n", bpsize, bptype, bp.name, symbolicname, bp.addr); dprintf("Hardware breakpoint (%s%s) \"%s\" at %s (" fhex ")!\n", bpsize, bptype, bp.name, symbolicname, bp.addr);
else
dprintf("Hardware breakpoint (%s%s) at %s (" fhex ")!\n", bpsize, bptype, symbolicname, bp.addr);
}
else else
dprintf("Hardware breakpoint (%s%s) at %s (" fhex ")!\n", bpsize, bptype, symbolicname, bp.addr); {
} if(*bp.name)
else dprintf("Hardware breakpoint (%s%s) \"%s\" at " fhex "!\n", bpsize, bptype, bp.name, bp.addr);
{ else
if(*bp.name) dprintf("Hardware breakpoint (%s%s) at " fhex "!\n", bpsize, bptype, bp.addr);
dprintf("Hardware breakpoint (%s%s) \"%s\" at " fhex "!\n", bpsize, bptype, bp.name, bp.addr); }
else } // else: BreakpointProlog outputs the log.
dprintf("Hardware breakpoint (%s%s) at " fhex "!\n", bpsize, bptype, bp.addr); if(bp.singleshoot)
} BpDelete(bp.addr, BPHARDWARE);
BpToBridge(&bp, &pluginBp); BpToBridge(&bp, &pluginBp);
bpInfo.breakpoint = &pluginBp; bpInfo.breakpoint = &pluginBp;
} }
GuiSetDebugState(paused); BreakpointProlog(condition, bp, bpInfo);
DebugUpdateGui(cip, true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
bSkipExceptions = false;
PLUG_CB_PAUSEDEBUG pauseInfo;
pauseInfo.reserved = 0;
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
plugincbcall(CB_BREAKPOINT, &bpInfo);
wait(WAITID_RUN);
} }
void cbMemoryBreakpoint(void* ExceptionAddress) void cbMemoryBreakpoint(void* ExceptionAddress)
{ {
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId); hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
duint cip = GetContextDataEx(hActiveThread, UE_CIP); BREAKPOINT* bpPtr;
duint size;
duint base = MemFindBaseAddr((duint)ExceptionAddress, &size, true);
BREAKPOINT bp; BREAKPOINT bp;
BRIDGEBP pluginBp; BRIDGEBP pluginBp;
PLUG_CB_BREAKPOINT bpInfo; PLUG_CB_BREAKPOINT bpInfo;
bpInfo.breakpoint = 0; duint size;
if(!BpGet(base, BPMEMORY, 0, &bp)) duint base = MemFindBaseAddr((duint)ExceptionAddress, &size, true);
ULONG_PTR CIP;
duint condition = 1;
memset(&bpInfo, 0, sizeof(bpInfo));
CIP = GetContextDataEx(hActiveThread, UE_CIP);
bpPtr = BpInfoFromAddr(BPMEMORY, base);
if(!(bpPtr && bpPtr->enabled))
dputs("Memory breakpoint reached not in list!"); dputs("Memory breakpoint reached not in list!");
else else
{ {
const char* bptype = ""; // increment hit count
switch(bp.titantype) InterlockedIncrement(&bpPtr->hitcount);
// condition eval
bp = *bpPtr;
bp.addr += ModBaseFromAddr(CIP);
//setBpActive(bp);
//if(bp.type == BPHARDWARE) //TODO: properly implement this (check debug registers)
// bp.active = true;
//else
bp.active = MemIsValidReadPtr(bp.addr);
if(bpPtr->condition[0] != 0)
{ {
case UE_MEMORY_READ: if(*(uint16*)bp.condition == 0x30) // short curcit for condition "0"
bptype = " (read)"; condition = 0;
break;
case UE_MEMORY_WRITE:
bptype = " (write)";
break;
case UE_MEMORY_EXECUTE:
bptype = " (execute)";
break;
case UE_MEMORY:
bptype = " (read/write/execute)";
break;
}
const char* symbolicname = SymGetSymbolicName(bp.addr);
if(symbolicname)
{
if(*bp.name)
dprintf("Memory breakpoint%s \"%s\" at %s (" fhex ", " fhex ")!\n", bptype, bp.name, symbolicname, bp.addr, ExceptionAddress);
else else
dprintf("Memory breakpoint%s at %s (" fhex ", " fhex ")!\n", bptype, symbolicname, bp.addr, ExceptionAddress); valfromstring(bp.condition, &condition); // if this fails, condition remains 1
if(bp.fastResume && condition == 0) // fast resume : ignore GUI/Script/Plugin/Singleshoot/Other
return;
} }
else if(bp.logText[0] == 0 && condition!=0)
{ {
if(*bp.name) const char* bptype = "";
dprintf("Memory breakpoint%s \"%s\" at " fhex " (" fhex ")!\n", bptype, bp.name, bp.addr, ExceptionAddress); switch (bp.titantype)
{
case UE_MEMORY_READ:
bptype = " (read)";
break;
case UE_MEMORY_WRITE:
bptype = " (write)";
break;
case UE_MEMORY_EXECUTE:
bptype = " (execute)";
break;
case UE_MEMORY:
bptype = " (read/write/execute)";
break;
}
const char* symbolicname = SymGetSymbolicName(bp.addr);
if(symbolicname)
{
if(*bp.name)
dprintf("Memory breakpoint%s \"%s\" at %s (" fhex ", " fhex ")!\n", bptype, bp.name, symbolicname, bp.addr, ExceptionAddress);
else
dprintf("Memory breakpoint%s at %s (" fhex ", " fhex ")!\n", bptype, symbolicname, bp.addr, ExceptionAddress);
}
else else
dprintf("Memory breakpoint%s at " fhex " (" fhex ")!\n", bptype, bp.addr, ExceptionAddress); {
} if(*bp.name)
dprintf("Memory breakpoint%s \"%s\" at " fhex " (" fhex ")!\n", bptype, bp.name, bp.addr, ExceptionAddress);
else
dprintf("Memory breakpoint%s at " fhex " (" fhex ")!\n", bptype, bp.addr, ExceptionAddress);
}
} // else: BreakpointProlog outputs the log.
BpToBridge(&bp, &pluginBp); BpToBridge(&bp, &pluginBp);
bpInfo.breakpoint = &pluginBp; bpInfo.breakpoint = &pluginBp;
} }
if(bp.singleshoot) if(bp.singleshoot)
BpDelete(bp.addr, BPMEMORY); //delete from breakpoint list BpDelete(bp.addr, BPMEMORY); //delete from breakpoint list
GuiSetDebugState(paused); BreakpointProlog(condition, bp, bpInfo);
DebugUpdateGui(cip, true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
bSkipExceptions = false;
PLUG_CB_PAUSEDEBUG pauseInfo;
pauseInfo.reserved = 0;
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
plugincbcall(CB_BREAKPOINT, &bpInfo);
wait(WAITID_RUN);
} }
void cbLibrarianBreakpoint(void* lpData) void cbLibrarianBreakpoint(void* lpData)

View File

@ -115,4 +115,7 @@ extern char szSymbolCachePath[MAX_PATH];
extern bool bUndecorateSymbolNames; extern bool bUndecorateSymbolNames;
extern bool bEnableSourceDebugging; extern bool bEnableSourceDebugging;
//private
void BreakpointProlog(duint condition, BREAKPOINT& bp, PLUG_CB_BREAKPOINT& bpInfo);
#endif // _DEBUGGER_H #endif // _DEBUGGER_H

View File

@ -445,6 +445,352 @@ CMDRESULT cbDebugDisableBPX(int argc, char* argv[])
return STATUS_CONTINUE; return STATUS_CONTINUE;
} }
CMDRESULT cbDebugSetBPXConditionCommon(BP_TYPE Type, int argc, char* argv[])
{
BREAKPOINT bp;
if(argc < 2)
{
dprintf("not enough arguments!\n");
return STATUS_ERROR;
}
else if(argc == 2)
{
if(BpGetAny(Type, argv[1], &bp))
{
if(!BpSetCondition(bp.addr, Type, ""))
{
dprintf("Can't set condition on breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
else
{
if(BpGetAny(Type, argv[1], &bp))
{
BpSetCondition(bp.addr, Type, argv[2]);
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
}
CMDRESULT cbDebugSetBPXLogCommon(BP_TYPE Type, int argc, char* argv[])
{
BREAKPOINT bp;
if(argc < 2)
{
dprintf("not enough arguments!\n");
return STATUS_ERROR;
}
else if(argc == 2)
{
if(BpGetAny(Type, argv[1], &bp))
{
if(!(BpSetLogText(bp.addr, Type, "")))
{
dprintf("Can't set logging text on breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
else
{
if(BpGetAny(Type, argv[1], &bp))
{
BpSetLogText(bp.addr, Type, argv[2]);
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
}
CMDRESULT cbDebugSetBPXCommandCommon(BP_TYPE Type, int argc, char* argv[])
{
BREAKPOINT bp;
if(argc < 2)
{
dprintf("not enough arguments!\n");
return STATUS_ERROR;
}
else if(argc == 2)
{
if(BpGetAny(Type, argv[1], &bp))
{
if(!BpSetHitCommand(bp.addr, Type, ""))
{
dprintf("Can't set command on hit on breakpoint \"%s\"", argv[1]);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
else
{
if(BpGetAny(Type, argv[1], &bp))
{
if(!(BpSetHitCommand(bp.addr, Type, argv[2])))
{
dprintf("Can't set command on hit on breakpoint \"%s\"", argv[1]);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
}
CMDRESULT cbDebugGetBPXHitCountCommon(BP_TYPE Type, int argc, char* argv[])
{
BREAKPOINT bp;
if(argc < 2)
{
dprintf("not enough arguments!\n");
return STATUS_ERROR;
}
else if(argc == 2)
{
duint result;
if(BpGetAny(Type, argv[1], &bp))
{
//result = BpGetHitCount(bp.addr, bp.type);
result = bp.hitcount; // improving performance
varset("$result", result, false);
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
else
{
dprintf("Too much arguments!\n");
return STATUS_ERROR;
}
}
CMDRESULT cbDebugResetBPXHitCountCommon(BP_TYPE Type, int argc, char* argv[])
{
BREAKPOINT bp;
if(argc < 2)
{
dprintf("not enough arguments!\n");
return STATUS_ERROR;
}
else if(argc == 2)
{
duint result;
if(BpGetAny(Type, argv[1], &bp))
{
result = BpResetHitCount(bp.addr, bp.type, 0);
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
else
{
duint value;
if(!(valfromstring(argv[2], &value)))
{
dprintf("Invalid expression \"%1\"", argv[2]);
}
if(BpGetAny(Type, argv[1], &bp))
{
if(!(BpResetHitCount(bp.addr, Type, (uint32)value)))
{
dprintf("Can't set command on hit on breakpoint \"%s\"", argv[1]);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
}
CMDRESULT cbDebugSetBPXFastResumeCommon(BP_TYPE Type, int argc, char* argv[]){
BREAKPOINT bp;
if(argc < 2)
{
dprintf("not enough arguments!\n");
return STATUS_ERROR;
}
else if(argc == 2)
{
duint value;
if(BpGetAny(Type, argv[1], &bp))
{
if(!valfromstring(argv[2], &value))
{
dprintf("Invalid expression \"%1\"", argv[2]);
return STATUS_ERROR;
}
if(!(BpSetFastResume(bp.addr, Type, true)))
{
dprintf("Can't set fast resume on breakpoint \"%1\"", argv[1]);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
else
{
duint result;
if(!(valfromstring(argv[2], &result)))
{
dprintf("Invalid expression \"%1\"", argv[2]);
}
if(BpGetAny(Type, argv[1], &bp))
{
if(!(BpSetFastResume(bp.addr, Type, result != 0)))
{
dprintf("Can't set fast resume on breakpoint \"%1\"", argv[1]);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
else
{
dprintf("No such breakpoint \"%s\"\n", argv[1]);
return STATUS_ERROR;
}
}
}
CMDRESULT cbDebugSetBPXCondition(int argc, char* argv[])
{
return cbDebugSetBPXConditionCommon(BPNORMAL, argc, argv);
}
CMDRESULT cbDebugSetBPXLog(int argc, char* argv[])
{
return cbDebugSetBPXLogCommon(BPNORMAL, argc, argv);
}
CMDRESULT cbDebugSetBPXCommand(int argc, char* argv[])
{
return cbDebugSetBPXCommandCommon(BPNORMAL, argc, argv);
}
CMDRESULT cbDebugSetBPXFastResume(int argc, char* argv[])
{
return cbDebugSetBPXFastResumeCommon(BPNORMAL, argc, argv);
}
CMDRESULT cbDebugResetBPXHitCount(int argc, char* argv[])
{
return cbDebugResetBPXHitCountCommon(BPNORMAL, argc, argv);
}
CMDRESULT cbDebugGetBPXHitCount(int argc, char* argv[])
{
return cbDebugGetBPXHitCountCommon(BPNORMAL, argc, argv);
}
CMDRESULT cbDebugSetBPXHardwareCondition(int argc, char* argv[])
{
return cbDebugSetBPXConditionCommon(BPHARDWARE, argc, argv);
}
CMDRESULT cbDebugSetBPXHardwareLog(int argc, char* argv[])
{
return cbDebugSetBPXLogCommon(BPHARDWARE, argc, argv);
}
CMDRESULT cbDebugSetBPXHardwareCommand(int argc, char* argv[])
{
return cbDebugSetBPXCommandCommon(BPHARDWARE, argc, argv);
}
CMDRESULT cbDebugSetBPXHardwareFastResume(int argc, char* argv[])
{
return cbDebugSetBPXFastResumeCommon(BPHARDWARE, argc, argv);
}
CMDRESULT cbDebugResetBPXHardwareHitCount(int argc, char* argv[])
{
return cbDebugResetBPXHitCountCommon(BPHARDWARE, argc, argv);
}
CMDRESULT cbDebugGetBPXHardwareHitCount(int argc, char* argv[])
{
return cbDebugGetBPXHitCountCommon(BPHARDWARE, argc, argv);
}
CMDRESULT cbDebugSetBPXMemoryCondition(int argc, char* argv[])
{
return cbDebugSetBPXConditionCommon(BPMEMORY, argc, argv);
}
CMDRESULT cbDebugSetBPXMemoryLog(int argc, char* argv[])
{
return cbDebugSetBPXLogCommon(BPMEMORY, argc, argv);
}
CMDRESULT cbDebugSetBPXMemoryCommand(int argc, char* argv[])
{
return cbDebugSetBPXCommandCommon(BPMEMORY, argc, argv);
}
CMDRESULT cbDebugResetBPXMemoryHitCount(int argc, char* argv[])
{
return cbDebugSetBPXFastResumeCommon(BPMEMORY, argc, argv);
}
CMDRESULT cbDebugSetBPXMemoryFastResume(int argc, char* argv[])
{
return cbDebugResetBPXHitCountCommon(BPMEMORY, argc, argv);
}
CMDRESULT cbDebugGetBPXMemoryHitCount(int argc, char* argv[])
{
return cbDebugGetBPXHitCountCommon(BPMEMORY, argc, argv);
}
CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[]) CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[])
{ {
if(argc < 2) if(argc < 2)
@ -2151,4 +2497,4 @@ CMDRESULT cbDebugSetfreezestack(int argc, char* argv[])
dbgsetfreezestack(freeze); dbgsetfreezestack(freeze);
dprintf("Stack is now %s\n", freeze ? "freezed" : "unfreezed"); dprintf("Stack is now %s\n", freeze ? "freezed" : "unfreezed");
return STATUS_CONTINUE; return STATUS_CONTINUE;
} }

View File

@ -14,14 +14,32 @@ CMDRESULT cbDebugSetBPX(int argc, char* argv[]);
CMDRESULT cbDebugDeleteBPX(int argc, char* argv[]); CMDRESULT cbDebugDeleteBPX(int argc, char* argv[]);
CMDRESULT cbDebugEnableBPX(int argc, char* argv[]); CMDRESULT cbDebugEnableBPX(int argc, char* argv[]);
CMDRESULT cbDebugDisableBPX(int argc, char* argv[]); CMDRESULT cbDebugDisableBPX(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXLog(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXCommand(int argc, char* argv[]);
CMDRESULT cbDebugGetBPXHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXFastResume(int argc, char* argv[]);
CMDRESULT cbDebugResetBPXHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[]); CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[]); CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugEnableHardwareBreakpoint(int argc, char* argv[]); CMDRESULT cbDebugEnableHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugDisableHardwareBreakpoint(int argc, char* argv[]); CMDRESULT cbDebugDisableHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXHardwareCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXHardwareLog(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXHardwareCommand(int argc, char* argv[]);
CMDRESULT cbDebugGetBPXHardwareHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXHardwareFastResume(int argc, char* argv[]);
CMDRESULT cbDebugResetBPXHardwareHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetMemoryBpx(int argc, char* argv[]); CMDRESULT cbDebugSetMemoryBpx(int argc, char* argv[]);
CMDRESULT cbDebugDeleteMemoryBreakpoint(int argc, char* argv[]); CMDRESULT cbDebugDeleteMemoryBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugEnableMemoryBreakpoint(int argc, char* argv[]); CMDRESULT cbDebugEnableMemoryBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugDisableMemoryBreakpoint(int argc, char* argv[]); CMDRESULT cbDebugDisableMemoryBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXMemoryCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXMemoryLog(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXMemoryCommand(int argc, char* argv[]);
CMDRESULT cbDebugGetBPXMemoryHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXMemoryFastResume(int argc, char* argv[]);
CMDRESULT cbDebugResetBPXMemoryHitCount(int argc, char* argv[]);
CMDRESULT cbDebugBplist(int argc, char* argv[]); CMDRESULT cbDebugBplist(int argc, char* argv[]);
CMDRESULT cbDebugStepInto(int argc, char* argv[]); CMDRESULT cbDebugStepInto(int argc, char* argv[]);
CMDRESULT cbDebugeStepInto(int argc, char* argv[]); CMDRESULT cbDebugeStepInto(int argc, char* argv[]);
@ -69,4 +87,4 @@ CMDRESULT cbDebugSetfreezestack(int argc, char* argv[]);
//misc //misc
void showcommandlineerror(cmdline_error_t* cmdline_error); void showcommandlineerror(cmdline_error_t* cmdline_error);
#endif //_DEBUGGER_COMMANDS_H #endif //_DEBUGGER_COMMANDS_H

View File

@ -1683,7 +1683,7 @@ bool valfromstring_noexpr(const char* string, duint* value, bool silent, bool ba
/** /**
\brief Gets a value from a string. This function can parse expressions, memory locations, registers, flags, API names, labels, symbols and variables. \brief Gets a value from a string. This function can parse expressions, memory locations, registers, flags, API names, labels, symbols and variables.
\param string The string to parse. \param string The string to parse.
\param [out] value The value of the expression. This value cannot be null. \param [out] value The value of the expression. This value cannot be null. When the expression is invalid, value is not changed.
\param silent true to not output anything to the console. \param silent true to not output anything to the console.
\param baseonly true to skip parsing API names, labels, symbols and variables (basic expressions only). \param baseonly true to skip parsing API names, labels, symbols and variables (basic expressions only).
\param [out] value_size This function can output the value size parsed (for example memory location size or register size). Can be null. \param [out] value_size This function can output the value size parsed (for example memory location size or register size). Can be null.

View File

@ -124,6 +124,24 @@ static void registercommands()
dbgcmdnew("DeleteMemoryBPX\1membpc\1bpmc", cbDebugDeleteMemoryBreakpoint, true); //delete memory breakpoint dbgcmdnew("DeleteMemoryBPX\1membpc\1bpmc", cbDebugDeleteMemoryBreakpoint, true); //delete memory breakpoint
dbgcmdnew("EnableMemoryBreakpoint\1membpe\1bpme", cbDebugEnableMemoryBreakpoint, true); //enable memory breakpoint dbgcmdnew("EnableMemoryBreakpoint\1membpe\1bpme", cbDebugEnableMemoryBreakpoint, true); //enable memory breakpoint
dbgcmdnew("DisableMemoryBreakpoint\1membpd\1bpmd", cbDebugDisableMemoryBreakpoint, true); //enable memory breakpoint dbgcmdnew("DisableMemoryBreakpoint\1membpd\1bpmd", cbDebugDisableMemoryBreakpoint, true); //enable memory breakpoint
dbgcmdnew("SetBreakpointCondition\1bpcond", cbDebugSetBPXCondition, true); //set breakpoint condition
dbgcmdnew("SetBreakpointLog\1bplog", cbDebugSetBPXLog, true); //set breakpoint log
dbgcmdnew("SetBreakpointCommand", cbDebugSetBPXCommand, true); //set breakpoint command on hit
dbgcmdnew("SetBreakpointFastResume", cbDebugSetBPXFastResume, true); //set breakpoint fast resume
dbgcmdnew("GetBreakpointHitCount", cbDebugGetBPXHitCount, true); //get breakpoint hit count
dbgcmdnew("ResetBreakpointHitCount", cbDebugResetBPXHitCount, true); //reset breakpoint hit count
dbgcmdnew("SetHardwareBreakpointCondition\1bphwcond", cbDebugSetBPXHardwareCondition, true); //set breakpoint condition
dbgcmdnew("SetHardwareBreakpointLog\1bphwlog", cbDebugSetBPXHardwareLog, true); //set breakpoint log
dbgcmdnew("SetHardwareBreakpointCommand", cbDebugSetBPXHardwareCommand, true); //set breakpoint command on hit
dbgcmdnew("SetHardwareBreakpointFastResume", cbDebugSetBPXHardwareFastResume, true); //set breakpoint fast resume
dbgcmdnew("GetHardwareBreakpointHitCount", cbDebugGetBPXHardwareHitCount, true); //get breakpoint hit count
dbgcmdnew("ResetHardwareBreakpointHitCount", cbDebugResetBPXHardwareHitCount, true); //reset breakpoint hit count
dbgcmdnew("SetMemoryBreakpointCondition\1bpmcond", cbDebugSetBPXMemoryCondition, true); //set breakpoint condition
dbgcmdnew("SetMemoryBreakpointLog\1bpmlog", cbDebugSetBPXMemoryLog, true); //set breakpoint log
dbgcmdnew("SetMemoryBreakpointCommand", cbDebugSetBPXMemoryCommand, true); //set breakpoint command on hit
dbgcmdnew("SetMemoryBreakpointFastResume", cbDebugSetBPXMemoryFastResume, true); //set breakpoint fast resume
dbgcmdnew("SetMemoryGetBreakpointHitCount", cbDebugGetBPXMemoryHitCount, true); //get breakpoint hit count
dbgcmdnew("ResetMemoryBreakpointHitCount", cbDebugResetBPXMemoryHitCount, true); //reset breakpoint hit count
//variables //variables
dbgcmdnew("varnew\1var", cbInstrVar, false); //make a variable arg1:name,[arg2:value] dbgcmdnew("varnew\1var", cbInstrVar, false); //make a variable arg1:name,[arg2:value]
@ -500,7 +518,7 @@ extern "C" DLL_EXPORT void _dbg_dbgexitsignal()
if(memleaks()) if(memleaks())
dprintf("%d memory leak(s) found!\n", memleaks()); dprintf("%d memory leak(s) found!\n", memleaks());
else else
DeleteFileA(alloctrace); DeleteFileW(StringUtils::Utf8ToUtf16(alloctrace).c_str());
dputs("Cleaning up wait objects..."); dputs("Cleaning up wait objects...");
waitdeinitialize(); waitdeinitialize();
dputs("Cleaning up debugger threads..."); dputs("Cleaning up debugger threads...");
@ -529,4 +547,4 @@ extern "C" DLL_EXPORT bool _dbg_dbgcmddirectexec(const char* cmd)
bool dbgisstopped() bool dbgisstopped()
{ {
return bIsStopped; return bIsStopped;
} }

View File

@ -304,7 +304,8 @@ bool CapstoneTokenizer::tokenizeMnemonic()
type = TokenType::MnemonicNop; type = TokenType::MnemonicNop;
else if(_cp.IsInt3()) else if(_cp.IsInt3())
type = TokenType::MnemonicInt3; type = TokenType::MnemonicInt3;
else if(_cp.InGroup(CS_GRP_PRIVILEGE) || _cp.InGroup(CS_GRP_IRET) || _cp.InGroup(CS_GRP_INVALID)) else if(_cp.InGroup(CS_GRP_PRIVILEGE) || _cp.InGroup(CS_GRP_IRET) || _cp.InGroup(CS_GRP_INVALID)
|| id == X86_INS_RDTSC || id == X86_INS_SYSCALL || id == X86_INS_SYSENTER || id == X86_INS_CPUID || id == X86_INS_RDRAND || id == X86_INS_RDTSCP)
type = TokenType::MnemonicUnusual; type = TokenType::MnemonicUnusual;
else else
{ {

View File

@ -2,6 +2,7 @@
#include "Configuration.h" #include "Configuration.h"
#include "Bridge.h" #include "Bridge.h"
#include "Breakpoints.h" #include "Breakpoints.h"
#include "LineEditDialog.h"
BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent) BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
{ {
@ -13,6 +14,11 @@ BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
mSoftBPTable->addColumnAt(8 + wCharWidth * 32, tr("Name"), false); mSoftBPTable->addColumnAt(8 + wCharWidth * 32, tr("Name"), false);
mSoftBPTable->addColumnAt(8 + wCharWidth * 32, tr("Module/Label"), false); mSoftBPTable->addColumnAt(8 + wCharWidth * 32, tr("Module/Label"), false);
mSoftBPTable->addColumnAt(8 + wCharWidth * 8, tr("State"), false); mSoftBPTable->addColumnAt(8 + wCharWidth * 8, tr("State"), false);
mSoftBPTable->addColumnAt(8 + wCharWidth * 10, tr("Hit count"), false);
mSoftBPTable->addColumnAt(8 + wCharWidth * 32, tr("Log text"), false);
mSoftBPTable->addColumnAt(8 + wCharWidth * 32, tr("Condition"), false);
mSoftBPTable->addColumnAt(8 + wCharWidth * 2, tr("Fast resume"), false);
mSoftBPTable->addColumnAt(8 + wCharWidth * 16, tr("Command on hit"), false);
mSoftBPTable->addColumnAt(wCharWidth * 10, tr("Comment"), false); mSoftBPTable->addColumnAt(wCharWidth * 10, tr("Comment"), false);
// Hardware // Hardware
@ -22,6 +28,11 @@ BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
mHardBPTable->addColumnAt(8 + wCharWidth * 32, tr("Name"), false); mHardBPTable->addColumnAt(8 + wCharWidth * 32, tr("Name"), false);
mHardBPTable->addColumnAt(8 + wCharWidth * 32, tr("Module/Label"), false); mHardBPTable->addColumnAt(8 + wCharWidth * 32, tr("Module/Label"), false);
mHardBPTable->addColumnAt(8 + wCharWidth * 8, tr("State"), false); mHardBPTable->addColumnAt(8 + wCharWidth * 8, tr("State"), false);
mHardBPTable->addColumnAt(8 + wCharWidth * 10, tr("Hit count"), false);
mHardBPTable->addColumnAt(8 + wCharWidth * 32, tr("Log text"), false);
mHardBPTable->addColumnAt(8 + wCharWidth * 32, tr("Condition"), false);
mHardBPTable->addColumnAt(8 + wCharWidth * 2, tr("Fast resume"), false);
mHardBPTable->addColumnAt(8 + wCharWidth * 16, tr("Command on hit"), false);
mHardBPTable->addColumnAt(wCharWidth * 10, tr("Comment"), false); mHardBPTable->addColumnAt(wCharWidth * 10, tr("Comment"), false);
// Memory // Memory
@ -31,6 +42,11 @@ BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
mMemBPTable->addColumnAt(8 + wCharWidth * 32, tr("Name"), false); mMemBPTable->addColumnAt(8 + wCharWidth * 32, tr("Name"), false);
mMemBPTable->addColumnAt(8 + wCharWidth * 32, tr("Module/Label"), false); mMemBPTable->addColumnAt(8 + wCharWidth * 32, tr("Module/Label"), false);
mMemBPTable->addColumnAt(8 + wCharWidth * 8, tr("State"), false); mMemBPTable->addColumnAt(8 + wCharWidth * 8, tr("State"), false);
mMemBPTable->addColumnAt(8 + wCharWidth * 10, tr("Hit count"), false);
mMemBPTable->addColumnAt(8 + wCharWidth * 32, tr("Log text"), false);
mMemBPTable->addColumnAt(8 + wCharWidth * 32, tr("Condition"), false);
mMemBPTable->addColumnAt(8 + wCharWidth * 2, tr("Fast resume"), false);
mMemBPTable->addColumnAt(8 + wCharWidth * 16, tr("Command on hit"), false);
mMemBPTable->addColumnAt(wCharWidth * 10, tr("Comment"), false); mMemBPTable->addColumnAt(wCharWidth * 10, tr("Comment"), false);
// Splitter // Splitter
@ -48,6 +64,7 @@ BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
this->setLayout(mVertLayout); this->setLayout(mVertLayout);
// Create the action list for the right click context menu // Create the action list for the right click context menu
setupCondBPRightClickContextMenu();
setupHardBPRightClickContextMenu(); setupHardBPRightClickContextMenu();
setupSoftBPRightClickContextMenu(); setupSoftBPRightClickContextMenu();
setupMemBPRightClickContextMenu(); setupMemBPRightClickContextMenu();
@ -98,16 +115,23 @@ void BreakpointsView::reloadData()
else else
mHardBPTable->setCellContent(wI, 3, tr("Disabled")); mHardBPTable->setCellContent(wI, 3, tr("Disabled"));
char comment[MAX_COMMENT_SIZE] = ""; mHardBPTable->setCellContent(wI, 4, QString("%1").arg(wBPList.bp[wI].hitCount));
if(DbgGetCommentAt(wBPList.bp[wI].addr, comment)) mHardBPTable->setCellContent(wI, 5, QString().fromUtf8(wBPList.bp[wI].log));
mHardBPTable->setCellContent(wI, 6, QString().fromUtf8(wBPList.bp[wI].condition));
mHardBPTable->setCellContent(wI, 7, wBPList.bp[wI].fastResume ? "X" : "");
mHardBPTable->setCellContent(wI, 8, QString().fromUtf8(wBPList.bp[wI].hitCmd));
char text[MAX_COMMENT_SIZE] = "";
if(DbgGetCommentAt(wBPList.bp[wI].addr, text))
{ {
if(comment[0] == '\1') //automatic comment if(text[0] == '\1') //automatic comment
mHardBPTable->setCellContent(wI, 4, QString(comment + 1)); mHardBPTable->setCellContent(wI, 9, QString(text + 1));
else else
mHardBPTable->setCellContent(wI, 4, comment); mHardBPTable->setCellContent(wI, 9, QString().fromUtf8(text));
} }
else else
mHardBPTable->setCellContent(wI, 4, ""); mHardBPTable->setCellContent(wI, 9, "");
} }
mHardBPTable->reloadData(); mHardBPTable->reloadData();
if(wBPList.count) if(wBPList.count)
@ -137,16 +161,22 @@ void BreakpointsView::reloadData()
else else
mSoftBPTable->setCellContent(wI, 3, tr("Disabled")); mSoftBPTable->setCellContent(wI, 3, tr("Disabled"));
mSoftBPTable->setCellContent(wI, 4, QString("%1").arg(wBPList.bp[wI].hitCount));
mSoftBPTable->setCellContent(wI, 5, QString().fromUtf8(wBPList.bp[wI].log));
mSoftBPTable->setCellContent(wI, 6, QString().fromUtf8(wBPList.bp[wI].condition));
mSoftBPTable->setCellContent(wI, 7, wBPList.bp[wI].fastResume ? "X" : "");
mSoftBPTable->setCellContent(wI, 8, QString().fromUtf8(wBPList.bp[wI].hitCmd));
char comment[MAX_COMMENT_SIZE] = ""; char comment[MAX_COMMENT_SIZE] = "";
if(DbgGetCommentAt(wBPList.bp[wI].addr, comment)) if(DbgGetCommentAt(wBPList.bp[wI].addr, comment))
{ {
if(comment[0] == '\1') //automatic comment if(comment[0] == '\1') //automatic comment
mSoftBPTable->setCellContent(wI, 4, QString(comment + 1)); mSoftBPTable->setCellContent(wI, 9, QString(comment + 1));
else else
mSoftBPTable->setCellContent(wI, 4, comment); mSoftBPTable->setCellContent(wI, 9, QString().fromUtf8(comment));
} }
else else
mSoftBPTable->setCellContent(wI, 4, ""); mSoftBPTable->setCellContent(wI, 9, "");
} }
mSoftBPTable->reloadData(); mSoftBPTable->reloadData();
if(wBPList.count) if(wBPList.count)
@ -176,16 +206,22 @@ void BreakpointsView::reloadData()
else else
mMemBPTable->setCellContent(wI, 3, tr("Disabled")); mMemBPTable->setCellContent(wI, 3, tr("Disabled"));
mMemBPTable->setCellContent(wI, 4, QString("%1").arg(wBPList.bp[wI].hitCount));
mMemBPTable->setCellContent(wI, 5, QString().fromUtf8(wBPList.bp[wI].log));
mMemBPTable->setCellContent(wI, 6, QString().fromUtf8(wBPList.bp[wI].condition));
mMemBPTable->setCellContent(wI, 7, wBPList.bp[wI].fastResume ? "X" : "");
mMemBPTable->setCellContent(wI, 8, QString().fromUtf8(wBPList.bp[wI].hitCmd));
char comment[MAX_COMMENT_SIZE] = ""; char comment[MAX_COMMENT_SIZE] = "";
if(DbgGetCommentAt(wBPList.bp[wI].addr, comment)) if(DbgGetCommentAt(wBPList.bp[wI].addr, comment))
{ {
if(comment[0] == '\1') //automatic comment if(comment[0] == '\1') //automatic comment
mMemBPTable->setCellContent(wI, 4, QString(comment + 1)); mMemBPTable->setCellContent(wI, 9, QString(comment + 1));
else else
mMemBPTable->setCellContent(wI, 4, comment); mMemBPTable->setCellContent(wI, 9, QString().fromUtf8(comment));
} }
else else
mMemBPTable->setCellContent(wI, 4, ""); mMemBPTable->setCellContent(wI, 9, "");
} }
mMemBPTable->reloadData(); mMemBPTable->reloadData();
@ -214,6 +250,11 @@ void BreakpointsView::setupHardBPRightClickContextMenu()
mHardBPEnableDisableAction->setShortcutContext(Qt::WidgetShortcut); mHardBPEnableDisableAction->setShortcutContext(Qt::WidgetShortcut);
mHardBPTable->addAction(mHardBPEnableDisableAction); mHardBPTable->addAction(mHardBPEnableDisableAction);
connect(mHardBPEnableDisableAction, SIGNAL(triggered()), this, SLOT(enableDisableHardBPActionSlot())); connect(mHardBPEnableDisableAction, SIGNAL(triggered()), this, SLOT(enableDisableHardBPActionSlot()));
// Reset hit count
mHardBPResetHitCountAction = new QAction(tr("Reset hit count"), this);
mHardBPTable->addAction(mHardBPResetHitCountAction);
connect(mHardBPResetHitCountAction, SIGNAL(triggered()), this, SLOT(resetHardwareHitCountSlot()));
} }
void BreakpointsView::refreshShortcutsSlot() void BreakpointsView::refreshShortcutsSlot()
@ -268,6 +309,11 @@ void BreakpointsView::hardwareBPContextMenuSlot(const QPoint & pos)
if(wBPList.count) if(wBPList.count)
BridgeFree(wBPList.bp); BridgeFree(wBPList.bp);
// Conditional
CurrentType = 2;
wMenu->addMenu(mConditionalBreakpointMenu);
wMenu->addAction(mHardBPResetHitCountAction);
// Separator // Separator
wMenu->addSeparator(); wMenu->addSeparator();
@ -314,6 +360,13 @@ void BreakpointsView::doubleClickHardwareSlot()
emit showCpu(); emit showCpu();
} }
void BreakpointsView::resetHardwareHitCountSlot()
{
StdTable* table = mHardBPTable;
QString addrText = table->getCellContent(table->getInitialSelection(), 0);
DbgCmdExecDirect(QString("ResetHardwareBreakpointHitCount " + addrText).toUtf8().constData());
reloadData();
}
/************************************************************************************ /************************************************************************************
Software Context Menu Management Software Context Menu Management
@ -336,6 +389,11 @@ void BreakpointsView::setupSoftBPRightClickContextMenu()
mSoftBPTable->addAction(mSoftBPEnableDisableAction); mSoftBPTable->addAction(mSoftBPEnableDisableAction);
connect(mSoftBPEnableDisableAction, SIGNAL(triggered()), this, SLOT(enableDisableSoftBPActionSlot())); connect(mSoftBPEnableDisableAction, SIGNAL(triggered()), this, SLOT(enableDisableSoftBPActionSlot()));
// Reset hit count
mSoftBPResetHitCountAction = new QAction(tr("Reset hit count"), this);
mSoftBPTable->addAction(mSoftBPResetHitCountAction);
connect(mSoftBPResetHitCountAction, SIGNAL(triggered()), this, SLOT(resetSoftwareHitCountSlot()));
// Enable All // Enable All
mSoftBPEnableAllAction = new QAction(tr("Enable All"), this); mSoftBPEnableAllAction = new QAction(tr("Enable All"), this);
mSoftBPTable->addAction(mSoftBPEnableAllAction); mSoftBPTable->addAction(mSoftBPEnableAllAction);
@ -387,6 +445,11 @@ void BreakpointsView::softwareBPContextMenuSlot(const QPoint & pos)
if(wBPList.count) if(wBPList.count)
BridgeFree(wBPList.bp); BridgeFree(wBPList.bp);
// Conditional
CurrentType = 1;
wMenu->addMenu(mConditionalBreakpointMenu);
wMenu->addAction(mSoftBPResetHitCountAction);
// Separator // Separator
wMenu->addSeparator(); wMenu->addSeparator();
@ -449,6 +512,13 @@ void BreakpointsView::doubleClickSoftwareSlot()
emit showCpu(); emit showCpu();
} }
void BreakpointsView::resetSoftwareHitCountSlot()
{
StdTable* table = mSoftBPTable;
QString addrText = table->getCellContent(table->getInitialSelection(), 0);
DbgCmdExecDirect(QString("ResetSoftwareBreakpointHitCount " + addrText).toUtf8().constData());
reloadData();
}
/************************************************************************************ /************************************************************************************
Memory Context Menu Management Memory Context Menu Management
@ -470,6 +540,11 @@ void BreakpointsView::setupMemBPRightClickContextMenu()
mMemBPEnableDisableAction->setShortcutContext(Qt::WidgetShortcut); mMemBPEnableDisableAction->setShortcutContext(Qt::WidgetShortcut);
mMemBPTable->addAction(mMemBPEnableDisableAction); mMemBPTable->addAction(mMemBPEnableDisableAction);
connect(mMemBPEnableDisableAction, SIGNAL(triggered()), this, SLOT(enableDisableMemBPActionSlot())); connect(mMemBPEnableDisableAction, SIGNAL(triggered()), this, SLOT(enableDisableMemBPActionSlot()));
// Reset hit count
mMemBPResetHitCountAction = new QAction(tr("Reset hit count"), this);
mMemBPTable->addAction(mMemBPResetHitCountAction);
connect(mMemBPResetHitCountAction, SIGNAL(triggered()), this, SLOT(resetMemoryHitCountSlot()));
} }
void BreakpointsView::memoryBPContextMenuSlot(const QPoint & pos) void BreakpointsView::memoryBPContextMenuSlot(const QPoint & pos)
@ -512,6 +587,11 @@ void BreakpointsView::memoryBPContextMenuSlot(const QPoint & pos)
if(wBPList.count) if(wBPList.count)
BridgeFree(wBPList.bp); BridgeFree(wBPList.bp);
// Conditional
CurrentType = 3;
wMenu->addMenu(mConditionalBreakpointMenu);
wMenu->addAction(mMemBPResetHitCountAction);
// Separator // Separator
wMenu->addSeparator(); wMenu->addSeparator();
@ -557,3 +637,200 @@ void BreakpointsView::doubleClickMemorySlot()
DbgCmdExecDirect(QString("disasm " + addrText).toUtf8().constData()); DbgCmdExecDirect(QString("disasm " + addrText).toUtf8().constData());
emit showCpu(); emit showCpu();
} }
void BreakpointsView::resetMemoryHitCountSlot()
{
StdTable* table = mMemBPTable;
QString addrText = table->getCellContent(table->getInitialSelection(), 0);
DbgCmdExecDirect(QString("ResetMemoryBreakpointHitCount " + addrText).toUtf8().constData());
reloadData();
}
/************************************************************************************
Conditional Breakpoint Context Menu Management (Sub-menu only)
************************************************************************************/
void BreakpointsView::setupCondBPRightClickContextMenu()
{
mConditionalBreakpointMenu = new QMenu(tr("&Conditional/Logging"), this);
mConditionalSetCondition = new QAction(tr("&Condition..."), this);
connect(mConditionalSetCondition, SIGNAL(triggered()), this, SLOT(setConditionSlot()));
mConditionalBreakpointMenu->addAction(mConditionalSetCondition);
mConditionalSetFastResume = new QAction(tr("&Fast Resume"), this);
connect(mConditionalSetFastResume, SIGNAL(triggered()), this, SLOT(setFastResumeSlot()));
mConditionalBreakpointMenu->addAction(mConditionalSetFastResume);
mConditionalSetLog = new QAction(tr("&Log on hit..."), this);
connect(mConditionalSetLog, SIGNAL(triggered()), this, SLOT(setLogSlot()));
mConditionalBreakpointMenu->addAction(mConditionalSetLog);
mConditionalSetCmd = new QAction(tr("&Run command on hit..."), this);
connect(mConditionalSetCmd, SIGNAL(triggered()), this, SLOT(setCmdSlot()));
mConditionalBreakpointMenu->addAction(mConditionalSetCmd);
}
void BreakpointsView::setConditionSlot()
{
QString addrText;
QString currentText;
LineEditDialog mLineEdit(this);
switch(CurrentType)
{
case 1:
addrText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 0);
currentText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 6);
break;
case 2:
addrText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 0);
currentText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 6);
break;
case 3:
addrText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 0);
currentText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 6);
break;
default:
__debugbreak();
}
mLineEdit.setText(currentText);
mLineEdit.setWindowTitle(tr("Set break condition on ") + addrText);
if(mLineEdit.exec() != QDialog::Accepted)
return;
currentText = mLineEdit.editText;
switch(CurrentType)
{
case 1:
DbgCmdExecDirect(QString("bpcond " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
case 2:
DbgCmdExecDirect(QString("bphwcond " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
case 3:
DbgCmdExecDirect(QString("bpmcond " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
}
reloadData();
}
void BreakpointsView::setLogSlot()
{
QString addrText;
QString currentText;
LineEditDialog mLineEdit(this);
switch(CurrentType)
{
case 1:
addrText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 0);
currentText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 5);
break;
case 2:
addrText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 0);
currentText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 5);
break;
case 3:
addrText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 0);
currentText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 5);
break;
default:
__debugbreak();
}
mLineEdit.setText(currentText);
mLineEdit.setWindowTitle(tr("Set log string on ") + addrText);
if(mLineEdit.exec() != QDialog::Accepted)
return;
currentText = mLineEdit.editText;
switch(CurrentType)
{
case 1:
DbgCmdExecDirect(QString("bplog " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
case 2:
DbgCmdExecDirect(QString("bphwlog " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
case 3:
DbgCmdExecDirect(QString("bpmlog " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
}
reloadData();
}
void BreakpointsView::setCmdSlot()
{
QString addrText;
QString currentText;
LineEditDialog mLineEdit(this);
switch(CurrentType)
{
case 1:
addrText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 0);
currentText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 8);
break;
case 2:
addrText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 0);
currentText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 8);
break;
case 3:
addrText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 0);
currentText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 8);
break;
default:
__debugbreak();
}
mLineEdit.setText(currentText);
mLineEdit.setWindowTitle(tr("Set command to execute when hitting on ") + addrText);
if(mLineEdit.exec() != QDialog::Accepted)
return;
currentText = mLineEdit.editText;
switch(CurrentType)
{
case 1:
DbgCmdExecDirect(QString("SetBreakpointCommand " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
case 2:
DbgCmdExecDirect(QString("SetHardwareBreakpointCommand " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
case 3:
DbgCmdExecDirect(QString("SetMemoryBreakpointCommand " + addrText + " , \"" + currentText + "\"").toUtf8().constData());
break;
}
reloadData();
}
void BreakpointsView::setFastResumeSlot()
{
QString addrText;
QString currentText;
switch(CurrentType)
{
case 1:
addrText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 0);
currentText = mSoftBPTable->getCellContent(mSoftBPTable->getInitialSelection(), 7);
break;
case 2:
addrText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 0);
currentText = mHardBPTable->getCellContent(mHardBPTable->getInitialSelection(), 7);
break;
case 3:
addrText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 0);
currentText = mMemBPTable->getCellContent(mMemBPTable->getInitialSelection(), 7);
break;
default:
__debugbreak();
}
currentText = currentText == "X" ? "0" : "1";
switch(CurrentType)
{
case 1:
DbgCmdExecDirect(QString("SetBreakpointFastResume " + addrText + " , " + currentText).toUtf8().constData());
break;
case 2:
DbgCmdExecDirect(QString("SetHardwareBreakpointFastResume " + addrText + " , " + currentText).toUtf8().constData());
break;
case 3:
DbgCmdExecDirect(QString("SetMemoryBreakpointFastResume " + addrText + " , " + currentText).toUtf8().constData());
break;
}
reloadData();
}

View File

@ -14,6 +14,7 @@ public:
void setupHardBPRightClickContextMenu(); void setupHardBPRightClickContextMenu();
void setupSoftBPRightClickContextMenu(); void setupSoftBPRightClickContextMenu();
void setupMemBPRightClickContextMenu(); void setupMemBPRightClickContextMenu();
void setupCondBPRightClickContextMenu();
signals: signals:
void showCpu(); void showCpu();
@ -28,6 +29,7 @@ public slots:
void removeAllHardBPActionSlot(); void removeAllHardBPActionSlot();
void enableDisableHardBPActionSlot(); void enableDisableHardBPActionSlot();
void doubleClickHardwareSlot(); void doubleClickHardwareSlot();
void resetHardwareHitCountSlot();
// Software // Software
void softwareBPContextMenuSlot(const QPoint & pos); void softwareBPContextMenuSlot(const QPoint & pos);
@ -37,6 +39,7 @@ public slots:
void enableAllSoftBPActionSlot(); void enableAllSoftBPActionSlot();
void disableAllSoftBPActionSlot(); void disableAllSoftBPActionSlot();
void doubleClickSoftwareSlot(); void doubleClickSoftwareSlot();
void resetSoftwareHitCountSlot();
// Memory // Memory
void memoryBPContextMenuSlot(const QPoint & pos); void memoryBPContextMenuSlot(const QPoint & pos);
@ -44,6 +47,13 @@ public slots:
void removeAllMemBPActionSlot(); void removeAllMemBPActionSlot();
void enableDisableMemBPActionSlot(); void enableDisableMemBPActionSlot();
void doubleClickMemorySlot(); void doubleClickMemorySlot();
void resetMemoryHitCountSlot();
// Conditional
void setLogSlot();
void setCmdSlot();
void setFastResumeSlot();
void setConditionSlot();
private: private:
QVBoxLayout* mVertLayout; QVBoxLayout* mVertLayout;
@ -51,11 +61,19 @@ private:
StdTable* mHardBPTable; StdTable* mHardBPTable;
StdTable* mSoftBPTable; StdTable* mSoftBPTable;
StdTable* mMemBPTable; StdTable* mMemBPTable;
QMenu* mConditionalBreakpointMenu;
// Conditional BP Context Menu
int CurrentType;
QAction* mConditionalSetCondition;
QAction* mConditionalSetFastResume;
QAction* mConditionalSetLog;
QAction* mConditionalSetCmd;
// Hardware BP Context Menu // Hardware BP Context Menu
QAction* mHardBPRemoveAction; QAction* mHardBPRemoveAction;
QAction* mHardBPRemoveAllAction; QAction* mHardBPRemoveAllAction;
QAction* mHardBPEnableDisableAction; QAction* mHardBPEnableDisableAction;
QAction* mHardBPResetHitCountAction;
// Software BP Context Menu // Software BP Context Menu
QAction* mSoftBPRemoveAction; QAction* mSoftBPRemoveAction;
@ -63,11 +81,13 @@ private:
QAction* mSoftBPEnableDisableAction; QAction* mSoftBPEnableDisableAction;
QAction* mSoftBPEnableAllAction; QAction* mSoftBPEnableAllAction;
QAction* mSoftBPDisableAllAction; QAction* mSoftBPDisableAllAction;
QAction* mSoftBPResetHitCountAction;
// Memory BP Context Menu // Memory BP Context Menu
QAction* mMemBPRemoveAction; QAction* mMemBPRemoveAction;
QAction* mMemBPRemoveAllAction; QAction* mMemBPRemoveAllAction;
QAction* mMemBPEnableDisableAction; QAction* mMemBPEnableDisableAction;
QAction* mMemBPResetHitCountAction;
}; };
#endif // BREAKPOINTSVIEW_H #endif // BREAKPOINTSVIEW_H

View File

@ -802,12 +802,12 @@ void CPUDump::setLabelSlot()
char label_text[MAX_COMMENT_SIZE] = ""; char label_text[MAX_COMMENT_SIZE] = "";
if(DbgGetLabelAt((duint)wVA, SEG_DEFAULT, label_text)) if(DbgGetLabelAt((duint)wVA, SEG_DEFAULT, label_text))
mLineEdit.setText(QString(label_text)); mLineEdit.setText(QString(label_text));
mLineEdit.setWindowTitle("Add label at " + addr_text); mLineEdit.setWindowTitle(tr("Add label at ") + addr_text);
if(mLineEdit.exec() != QDialog::Accepted) if(mLineEdit.exec() != QDialog::Accepted)
return; return;
if(!DbgSetLabelAt(wVA, mLineEdit.editText.toUtf8().constData())) if(!DbgSetLabelAt(wVA, mLineEdit.editText.toUtf8().constData()))
{ {
QMessageBox msg(QMessageBox::Critical, "Error!", "DbgSetLabelAt failed!"); QMessageBox msg(QMessageBox::Critical, tr("Error!"), tr("DbgSetLabelAt failed!"));
msg.setWindowIcon(QIcon(":/icons/images/compile-error.png")); msg.setWindowIcon(QIcon(":/icons/images/compile-error.png"));
msg.setParent(this, Qt::Dialog); msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
@ -1698,4 +1698,3 @@ void CPUDump::gotoPrevSlot()
historyPrev(); historyPrev();
} }

View File

@ -124,7 +124,7 @@ void PageMemoryRights::on_btnSetrights_clicked()
emit refreshMemoryMap(); emit refreshMemoryMap();
if(one_right_changed) if(one_right_changed)
ui->LnEdStatus->setText("Pages Rights Changed to: " + rights); ui->LnEdStatus->setText(tr("Pages Rights Changed to: ") + rights);
else else
ui->LnEdStatus->setText("Error setting rights, read the MSDN to learn the valid rights of: " + pagetype); ui->LnEdStatus->setText(tr("Error setting rights, read the MSDN to learn the valid rights of: ") + pagetype);
} }