1
0
Fork 0

conditional exception breakpoint (#1073)

* temporary

* Exception breakpoints

* temporary

* temporary

* temporary

* fixes

* fully retire "error"
This commit is contained in:
Torusrxxx 2016-09-10 05:43:34 +00:00 committed by Duncan Ogilvie
parent ac0853ffec
commit 9288c910cb
25 changed files with 768 additions and 160 deletions

View File

@ -122,7 +122,8 @@ typedef enum
bp_normal = 1,
bp_hardware = 2,
bp_memory = 4,
bp_dll = 8
bp_dll = 8,
bp_exception = 16
} BPXTYPE;
typedef enum

View File

@ -235,6 +235,9 @@ static bool _getbridgebp(BPXTYPE type, duint addr, BRIDGEBP* bp)
bptype = BPDLL;
addr = ModHashFromName(reinterpret_cast<const char*>(addr));
break;
case bp_exception:
bptype = BPEXCEPTION;
break;
default:
return false;
}

View File

@ -25,7 +25,7 @@
#include "bookmark.h"
#include "function.h"
#include "loop.h"
#include "error.h"
#include "exception.h"
#include "x64_dbg.h"
#include "threading.h"
#include "stringformat.h"
@ -579,6 +579,9 @@ extern "C" DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* bpmap)
case bp_dll:
currentBpType = BPDLL;
break;
case bp_exception:
currentBpType = BPEXCEPTION;
break;
default:
return 0;
}

View File

@ -10,6 +10,7 @@
#include "module.h"
#include "value.h"
#include "debugger.h"
#include "exception.h"
typedef std::pair<BP_TYPE, duint> BreakpointKey;
std::map<BreakpointKey, BREAKPOINT> breakpoints;
@ -18,7 +19,7 @@ static void setBpActive(BREAKPOINT & bp)
{
if(bp.type == BPHARDWARE) //TODO: properly implement this (check debug registers)
bp.active = true;
else if(bp.type == BPDLL)
else if(bp.type == BPDLL || bp.type == BPEXCEPTION)
bp.active = true;
else
bp.active = MemIsValidReadPtr(bp.addr);
@ -30,7 +31,7 @@ BREAKPOINT* BpInfoFromAddr(BP_TYPE Type, duint Address)
// NOTE: THIS DOES _NOT_ USE LOCKS
//
std::map<BreakpointKey, BREAKPOINT>::iterator found;
if(Type != BPDLL)
if(Type != BPDLL && Type != BPEXCEPTION)
found = breakpoints.find(BreakpointKey(Type, ModHashFromAddr(Address)));
else
found = breakpoints.find(BreakpointKey(Type, Address)); // Address = ModHashFromName(ModuleName)
@ -54,7 +55,7 @@ int BpGetList(std::vector<BREAKPOINT>* List)
for(auto & i : breakpoints)
{
BREAKPOINT currentBp = i.second;
if(currentBp.type != BPDLL)
if(currentBp.type != BPDLL && currentBp.type != BPEXCEPTION)
currentBp.addr += ModBaseFromName(currentBp.mod);
setBpActive(currentBp);
@ -70,8 +71,11 @@ bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE
ASSERT_DEBUGGING("Export call");
// Fail if the address is a bad memory region
if(!MemIsValidReadPtr(Address))
return false;
if(Type != BPDLL && Type != BPEXCEPTION)
{
if(!MemIsValidReadPtr(Address))
return false;
}
// Fail if the breakpoint already exists
if(BpGet(Address, Type, Name, nullptr))
@ -84,11 +88,17 @@ bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE
BREAKPOINT bp;
memset(&bp, 0, sizeof(BREAKPOINT));
ModNameFromAddr(Address, bp.mod, true);
if(Type != BPDLL && Type != BPEXCEPTION)
{
ModNameFromAddr(Address, bp.mod, true);
}
strncpy_s(bp.name, Name, _TRUNCATE);
bp.active = true;
bp.addr = Address - ModBaseFromAddr(Address);
if(Type != BPDLL && Type != BPEXCEPTION)
bp.addr = Address - ModBaseFromAddr(Address);
else
bp.addr = Address;
bp.enabled = Enable;
bp.oldbytes = OldBytes;
bp.singleshoot = Singleshot;
@ -98,7 +108,14 @@ bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE
// Insert new entry to the global list
EXCLUSIVE_ACQUIRE(LockBreakpoints);
return breakpoints.insert(std::make_pair(BreakpointKey(Type, ModHashFromAddr(Address)), bp)).second;
if(Type != BPDLL && Type != BPEXCEPTION)
{
return breakpoints.insert(std::make_pair(BreakpointKey(Type, ModHashFromAddr(Address)), bp)).second;
}
else
{
return breakpoints.insert(std::make_pair(BreakpointKey(Type, Address), bp)).second;
}
}
bool BpNewDll(const char* module, bool Enable, bool Singleshot, DWORD TitanType, const char* Name)
@ -144,7 +161,7 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
return true;
*Bp = *bpInfo;
if(bpInfo->type != BPDLL)
if(bpInfo->type != BPDLL && bpInfo->type != BPEXCEPTION)
Bp->addr += ModBaseFromAddr(Address);
setBpActive(*Bp);
return true;
@ -161,7 +178,7 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
if(Bp)
{
*Bp = i.second;
if(i.second.type != BPDLL)
if(i.second.type != BPDLL && i.second.type != BPEXCEPTION)
Bp->addr += ModBaseFromAddr(Address);
setBpActive(*Bp);
}
@ -183,6 +200,13 @@ bool BpGetAny(BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
if(valfromstring(Name, &addr))
if(BpGet(addr, Type, 0, Bp))
return true;
if(Type == BPEXCEPTION)
{
addr = 0;
if(ExceptionNameToCode(Name, reinterpret_cast<unsigned int*>(&addr)))
if(BpGet(addr, BPEXCEPTION, 0, Bp))
return true;
}
}
else
{
@ -198,7 +222,7 @@ bool BpUpdateDllPath(const char* module1, BREAKPOINT** newBpInfo)
EXCLUSIVE_ACQUIRE(LockBreakpoints);
for(auto & i : breakpoints)
{
if(i.second.type == BPDLL)
if(i.second.type == BPDLL && i.second.enabled)
{
if(_stricmp(i.second.mod, module1) == 0)
{
@ -452,7 +476,7 @@ bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module, duint base)
}
BREAKPOINT bpInfo = j->second;
if(bpInfo.type != BPDLL)
if(bpInfo.type != BPDLL && bpInfo.type != BPEXCEPTION)
{
if(base) //workaround for some Windows bullshit with compatibility mode
bpInfo.addr += base;
@ -596,6 +620,10 @@ void BpToBridge(const BREAKPOINT* Bp, BRIDGEBP* BridgeBp)
break;
}
break;
case BPEXCEPTION:
BridgeBp->type = bp_exception;
BridgeBp->slot = Bp->titantype; //1:First-chance, 2:Second-chance, 3:Both
break;
default:
BridgeBp->type = bp_none;
break;
@ -629,7 +657,8 @@ void BpCacheSave(JSON Root)
json_object_set_new(jsonObj, "type", json_integer(breakpoint.type));
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, "module", json_string(breakpoint.mod));
if(breakpoint.type != BPEXCEPTION)
json_object_set_new(jsonObj, "module", json_string(breakpoint.mod));
json_object_set_new(jsonObj, "breakCondition", json_string(breakpoint.breakCondition));
json_object_set_new(jsonObj, "logText", json_string(breakpoint.logText));
json_object_set_new(jsonObj, "logCondition", json_string(breakpoint.logCondition));
@ -685,7 +714,8 @@ void BpCacheLoad(JSON Root)
// String values
loadStringValue(value, breakpoint.name, "name");
loadStringValue(value, breakpoint.mod, "module");
if(breakpoint.type != BPEXCEPTION)
loadStringValue(value, breakpoint.mod, "module");
loadStringValue(value, breakpoint.breakCondition, "breakCondition");
loadStringValue(value, breakpoint.logText, "logText");
loadStringValue(value, breakpoint.logCondition, "logCondition");

View File

@ -15,7 +15,8 @@ enum BP_TYPE
BPNORMAL = 0,
BPHARDWARE = 1,
BPMEMORY = 2,
BPDLL = 3
BPDLL = 3,
BPEXCEPTION = 4
};
struct BREAKPOINT

View File

@ -3,6 +3,18 @@
#include "console.h"
#include "memory.h"
#include "variable.h"
#include "exception.h"
inline bool IsArgumentsLessThan(int argc, int minimumCount)
{
if(argc < minimumCount)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Not enough arguments! At least %d arguments must be specified.\n"), minimumCount - 1);
return true;
}
else
return false;
}
// breakpoint enumeration callbacks
static bool cbDeleteAllBreakpoints(const BREAKPOINT* bp)
@ -192,6 +204,45 @@ static bool cbDeleteAllDllBreakpoints(const BREAKPOINT* bp)
return true;
}
static bool cbEnableAllExceptionBreakpoints(const BREAKPOINT* bp)
{
if(bp->type != BPEXCEPTION || bp->enabled)
return true;
if(!BpEnable(bp->addr, BPEXCEPTION, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable exception breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
return true;
}
static bool cbDisableAllExceptionBreakpoints(const BREAKPOINT* bp)
{
if(bp->type != BPEXCEPTION || !bp->enabled)
return true;
if(!BpEnable(bp->addr, BPEXCEPTION, false))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable exception breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
return true;
}
static bool cbDeleteAllExceptionBreakpoints(const BREAKPOINT* bp)
{
if(bp->type != BPEXCEPTION)
return true;
if(!BpDelete(bp->addr, BPEXCEPTION))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete exception breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
return true;
}
static bool cbBreakpointList(const BREAKPOINT* bp)
{
const char* type = 0;
@ -208,6 +259,8 @@ static bool cbBreakpointList(const BREAKPOINT* bp)
type = "GP";
else if(bp->type == BPDLL)
type = "DLL";
else if(bp->type == BPEXCEPTION)
type = "EX";
bool enabled = bp->enabled;
if(bp->type == BPDLL)
{
@ -262,11 +315,8 @@ static bool cbDeleteAllHardwareBreakpoints(const BREAKPOINT* bp)
// command callbacks
CMDRESULT cbDebugSetBPXOptions(int argc, char* argv[])
{
if(argc < 2)
{
dputs(QT_TRANSLATE_NOOP("DBG", "Not enough arguments!"));
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
}
DWORD type = 0;
const char* strType = 0;
duint setting_type;
@ -301,11 +351,8 @@ CMDRESULT cbDebugSetBPXOptions(int argc, char* argv[])
CMDRESULT cbDebugSetBPX(int argc, char* argv[]) //bp addr [,name [,type]]
{
if(argc < 2)
{
dputs(QT_TRANSLATE_NOOP("DBG", "Not enough arguments!"));
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
}
char argaddr[deflen] = "";
strcpy_s(argaddr, argv[1]);
char argname[deflen] = "";
@ -562,14 +609,192 @@ CMDRESULT cbDebugDisableBPX(int argc, char* argv[])
return STATUS_CONTINUE;
}
CMDRESULT cbDebugSetExceptionBPX(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
duint ExceptionCode;
if(!valfromstring(argv[1], &ExceptionCode))
{
ExceptionCode = 0;
if(!ExceptionNameToCode(argv[1], reinterpret_cast<unsigned int*>(&ExceptionCode)))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid exception code: %s.\n"), argv[1]);
return STATUS_ERROR;
}
}
const String & ExceptionName = ExceptionCodeToName(ExceptionCode);
if(BpGet(ExceptionCode, BPEXCEPTION, nullptr, nullptr))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Exception breakpoint %X(%s) already exists!\n"), ExceptionCode, ExceptionName.c_str());
return STATUS_ERROR;
}
duint chance = 1;
if(argc > 2)
{
if(!valfromstring(argv[2], &chance))
{
dputs(QT_TRANSLATE_NOOP("DBG", "Invalid expression!"));
return STATUS_ERROR;
}
// range limit
// chance: 1=first chance, 2=second chance, 3=all
if(chance > 3)
chance = 3;
if(chance == 0)
chance = 1;
}
if(!BpNew(ExceptionCode, true, false, 0, BPEXCEPTION, chance, ""))
{
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to set exception breakpoint! (BpNew)"));
return STATUS_ERROR;
}
DebugUpdateBreakpointsViewAsync();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDeleteExceptionBPX(int argc, char* argv[])
{
if(argc < 2)
{
// delete all exception breakpoints
if(!BpGetCount(BPEXCEPTION))
{
dputs(QT_TRANSLATE_NOOP("DBG", "No exception breakpoints to delete!"));
return STATUS_CONTINUE;
}
if(!BpEnumAll(cbDeleteAllExceptionBreakpoints)) //at least one enable failed
return STATUS_ERROR;
dputs(QT_TRANSLATE_NOOP("DBG", "All exception breakpoints deleted!"));
DebugUpdateBreakpointsViewAsync();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(BpGet(0, BPEXCEPTION, argv[1], &found)) //found a breakpoint with name
{
if(!BpDelete(found.addr, BPEXCEPTION))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete exception breakpoint failed (bpdel): %p\n"), found.addr);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
duint addr = 0;
if((!ExceptionNameToCode(argv[1], reinterpret_cast<unsigned int*>(&addr)) && !valfromstring(argv[1], &addr)) || !BpGet(addr, BPEXCEPTION, 0, &found)) //invalid breakpoint
{
dprintf(QT_TRANSLATE_NOOP("DBG", "No such exception breakpoint \"%s\"\n"), argv[1]);
return STATUS_ERROR;
}
if(!BpDelete(found.addr, BPEXCEPTION))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete exception breakpoint failed (bpdel): %p\n"), found.addr);
return STATUS_ERROR;
}
dputs(QT_TRANSLATE_NOOP("DBG", "Exception breakpoint deleted!"));
DebugUpdateBreakpointsViewAsync();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugEnableExceptionBPX(int argc, char* argv[])
{
if(argc < 2) //enable all breakpoints
{
if(!BpGetCount(BPEXCEPTION))
{
dputs(QT_TRANSLATE_NOOP("DBG", "No exception breakpoints to enable!"));
return STATUS_CONTINUE;
}
if(!BpEnumAll(cbEnableAllExceptionBreakpoints)) //at least one enable failed
return STATUS_ERROR;
dputs(QT_TRANSLATE_NOOP("DBG", "All exception breakpoints enabled!"));
DebugUpdateBreakpointsViewAsync();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(BpGet(0, BPEXCEPTION, argv[1], &found)) //found a breakpoint with name
{
if(!BpEnable(found.addr, BPEXCEPTION, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable exception breakpoint %p (BpEnable)\n"), found.addr);
return STATUS_ERROR;
}
DebugUpdateBreakpointsViewAsync();
return STATUS_CONTINUE;
}
duint addr = 0;
if((!ExceptionNameToCode(argv[1], reinterpret_cast<unsigned int*>(&addr)) && !valfromstring(argv[1], &addr)) || !BpGet(addr, BPEXCEPTION, 0, &found)) //invalid breakpoint
{
dprintf(QT_TRANSLATE_NOOP("DBG", "No such exception breakpoint \"%s\"\n"), argv[1]);
return STATUS_ERROR;
}
if(found.enabled)
{
dputs(QT_TRANSLATE_NOOP("DBG", "Exception breakpoint already enabled!"));
DebugUpdateBreakpointsViewAsync();
return STATUS_CONTINUE;
}
if(!BpEnable(found.addr, BPEXCEPTION, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable exception breakpoint %p (BpEnable)\n"), found.addr);
return STATUS_ERROR;
}
DebugUpdateBreakpointsViewAsync();
dputs(QT_TRANSLATE_NOOP("DBG", "Exception breakpoint enabled!"));
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDisableExceptionBPX(int argc, char* argv[])
{
if(argc < 2) //disable all breakpoints
{
if(!BpGetCount(BPEXCEPTION))
{
dputs(QT_TRANSLATE_NOOP("DBG", "No exception breakpoints to disable!"));
return STATUS_CONTINUE;
}
if(!BpEnumAll(cbDisableAllExceptionBreakpoints)) //at least one deletion failed
return STATUS_ERROR;
dputs(QT_TRANSLATE_NOOP("DBG", "All exception breakpoints disabled!"));
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(BpGet(0, BPEXCEPTION, argv[1], &found)) //found a breakpoint with name
{
if(!BpEnable(found.addr, BPEXCEPTION, false))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable exception breakpoint %p (BpEnable)\n"), found.addr);
return STATUS_ERROR;
}
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
duint addr = 0;
if((!ExceptionNameToCode(argv[1], reinterpret_cast<unsigned int*>(&addr)) && !valfromstring(argv[1], &addr)) || !BpGet(addr, BPEXCEPTION, 0, &found)) //invalid breakpoint
{
dprintf(QT_TRANSLATE_NOOP("DBG", "No such exception breakpoint \"%s\"\n"), argv[1]);
return STATUS_ERROR;
}
if(!found.enabled)
{
dputs(QT_TRANSLATE_NOOP("DBG", "Exception breakpoint already disabled!"));
return STATUS_CONTINUE;
}
if(!BpEnable(found.addr, BPEXCEPTION, false))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable exception breakpoint %p (BpEnable)\n"), found.addr);
return STATUS_ERROR;
}
dputs(QT_TRANSLATE_NOOP("DBG", "Exception breakpoint disabled!"));
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
static CMDRESULT cbDebugSetBPXTextCommon(BP_TYPE Type, int argc, char* argv[], const String & description, std::function<bool(duint, BP_TYPE, const char*)> setFunction)
{
BREAKPOINT bp;
if(argc < 2)
{
dputs(QT_TRANSLATE_NOOP("DBG", "not enough arguments!\n"));
if(IsArgumentsLessThan(argc, 2))
return STATUS_ERROR;
}
char* value = "";
if(argc > 2)
value = argv[2];
@ -957,6 +1182,61 @@ CMDRESULT cbDebugGetBPXDLLHitCount(int argc, char* argv[])
return cbDebugGetBPXHitCountCommon(BPDLL, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionName(int argc, char* argv[])
{
return cbDebugSetBPXNameCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionCondition(int argc, char* argv[])
{
return cbDebugSetBPXConditionCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionLog(int argc, char* argv[])
{
return cbDebugSetBPXLogCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionLogCondition(int argc, char* argv[])
{
return cbDebugSetBPXLogConditionCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionCommand(int argc, char* argv[])
{
return cbDebugSetBPXCommandCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionCommandCondition(int argc, char* argv[])
{
return cbDebugSetBPXCommandConditionCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugResetBPXExceptionHitCount(int argc, char* argv[])
{
return cbDebugResetBPXHitCountCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionFastResume(int argc, char* argv[])
{
return cbDebugSetBPXFastResumeCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionSingleshoot(int argc, char* argv[])
{
return cbDebugSetBPXSingleshootCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPXExceptionSilent(int argc, char* argv[])
{
return cbDebugSetBPXSilentCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugGetBPXExceptionHitCount(int argc, char* argv[])
{
return cbDebugGetBPXHitCountCommon(BPEXCEPTION, argc, argv);
}
CMDRESULT cbDebugSetBPGoto(int argc, char* argv[])
{
if(argc != 3)

View File

@ -19,7 +19,6 @@
#include "variable.h"
#include "x64_dbg.h"
#include "exception.h"
#include "error.h"
#include "module.h"
#include "commandline.h"
#include "stackinfo.h"
@ -600,6 +599,14 @@ static void printDllBpInfo(const BREAKPOINT & bp)
free(bptype);
}
static void printExceptionBpInfo(const BREAKPOINT & bp, duint CIP)
{
if(*bp.name != 0)
dprintf(QT_TRANSLATE_NOOP("DBG", "Exception Breakpoint %s(%p) at %p!\n"), bp.name, bp.addr, CIP);
else
dprintf(QT_TRANSLATE_NOOP("DBG", "Exception Breakpoint %s(%p) at %p!\n"), ExceptionCodeToName(bp.addr).c_str(), bp.addr, CIP);
}
static bool getConditionValue(const char* expression)
{
auto word = *(uint16*)expression;
@ -659,6 +666,9 @@ static void handleBreakCondition(const BREAKPOINT & bp, const void* ExceptionAdd
case BPDLL:
printDllBpInfo(bp);
break;
case BPEXCEPTION:
printExceptionBpInfo(bp, CIP);
break;
default:
break;
}
@ -680,17 +690,20 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
switch(bptype)
{
case BPNORMAL:
bpPtr = BpInfoFromAddr(bptype, CIP);
bpPtr = BpInfoFromAddr(BPNORMAL, CIP);
break;
case BPHARDWARE:
bpPtr = BpInfoFromAddr(bptype, duint(ExceptionAddress));
bpPtr = BpInfoFromAddr(BPHARDWARE, duint(ExceptionAddress));
break;
case BPMEMORY:
bpPtr = BpInfoFromAddr(bptype, MemFindBaseAddr(duint(ExceptionAddress), nullptr, true));
bpPtr = BpInfoFromAddr(BPMEMORY, MemFindBaseAddr(duint(ExceptionAddress), nullptr, true));
break;
case BPDLL:
bpPtr = BpInfoFromAddr(BPDLL, BpGetDLLBpAddr(reinterpret_cast<const char*>(ExceptionAddress)));
break;
case BPEXCEPTION:
bpPtr = BpInfoFromAddr(BPEXCEPTION, ((EXCEPTION_DEBUG_INFO*)ExceptionAddress)->ExceptionRecord.ExceptionCode);
break;
default:
break;
}
@ -717,7 +730,8 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
auto bp = *bpPtr;
SHARED_RELEASE();
bp.addr += ModBaseFromAddr(CIP);
if(bptype != BPDLL && bptype != BPEXCEPTION)
bp.addr += ModBaseFromAddr(CIP);
bp.active = true; //a breakpoint that has been hit is active
varset("$breakpointcounter", bp.hitcount, false); //save the breakpoint counter as a variable
@ -1659,6 +1673,14 @@ static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
lastExceptionInfo = *ExceptionData;
duint addr = (duint)ExceptionData->ExceptionRecord.ExceptionAddress;
{
BREAKPOINT bp;
if(BpGet(ExceptionCode, BPEXCEPTION, nullptr, &bp) && bp.enabled && ((bp.titantype == 1 && ExceptionData->dwFirstChance) || (bp.titantype == 2 && !ExceptionData->dwFirstChance) || bp.titantype == 3))
{
cbGenericBreakpoint(BPEXCEPTION, ExceptionData);
return;
}
}
if(ExceptionData->ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
{
if(isDetachedByUser)

View File

@ -32,6 +32,10 @@ CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugEnableHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugDisableHardwareBreakpoint(int argc, char* argv[]);
CMDRESULT cbDebugSetExceptionBPX(int argc, char* argv[]);
CMDRESULT cbDebugDeleteExceptionBPX(int argc, char* argv[]);
CMDRESULT cbDebugEnableExceptionBPX(int argc, char* argv[]);
CMDRESULT cbDebugDisableExceptionBPX(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXHardwareName(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXHardwareCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXHardwareLog(int argc, char* argv[]);
@ -69,6 +73,17 @@ CMDRESULT cbDebugSetBPXDLLFastResume(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLSingleshoot(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXDLLSilent(int argc, char* argv[]);
CMDRESULT cbDebugResetBPXDLLHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionName(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionLog(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionLogCondition(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionCommand(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionCommandCondition(int argc, char* argv[]);
CMDRESULT cbDebugGetBPXExceptionHitCount(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionFastResume(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionSingleshoot(int argc, char* argv[]);
CMDRESULT cbDebugSetBPXExceptionSilent(int argc, char* argv[]);
CMDRESULT cbDebugResetBPXExceptionHitCount(int argc, char* argv[]);
CMDRESULT cbDebugBpDllDisable(int argc, char* argv[]);
CMDRESULT cbDebugBpDllEnable(int argc, char* argv[]);
CMDRESULT cbDebugBplist(int argc, char* argv[]);

View File

@ -1,45 +0,0 @@
#include <unordered_map>
#include "error.h"
#include "filehelper.h"
#include "value.h"
#include "console.h"
static std::unordered_map<unsigned int, String> ErrorNames;
bool ErrorCodeInit(const String & errorFile)
{
ErrorNames.clear();
std::vector<String> lines;
if(!FileHelper::ReadAllLines(errorFile, lines))
return false;
auto parseLine = [](const String & line)
{
auto split = StringUtils::Split(line, ' ');
if(int(split.size()) < 2)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid line: \"%s\"\n"), line.c_str());
return false;
}
duint code;
if(!convertNumber(split[0].c_str(), code, 10))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to convert number \"%s\"\n"), split[0].c_str());
return false;
}
ErrorNames.insert({ (unsigned int)code, split[1] });
return true;
};
auto result = true;
for(const auto & line : lines)
if(!parseLine(line))
result = false;
return result;
}
String ErrorCodeToName(unsigned int ErrorCode)
{
if(ErrorNames.find(ErrorCode) == ErrorNames.end())
return "";
return ErrorNames[ErrorCode];
}

View File

@ -1,9 +0,0 @@
#ifndef _ERROR_H
#define _ERROR_H
#include "_global.h"
bool ErrorCodeInit(const String & errorFile);
String ErrorCodeToName(unsigned int ErrorCode);
#endif // _ERROR_H

View File

@ -6,59 +6,102 @@
static std::unordered_map<unsigned int, String> ExceptionNames;
static std::unordered_map<unsigned int, String> NtStatusNames;
static std::unordered_map<unsigned int, String> ErrorNames;
bool UniversalCodeInit(const String & file, std::unordered_map<unsigned int, String> & names)
static bool UniversalCodeInit(const String & file, std::unordered_map<unsigned int, String> & names, unsigned char radix)
{
names.clear();
std::vector<String> lines;
if(!FileHelper::ReadAllLines(file, lines))
return false;
auto parseLine = [&names](const String & line)
{
auto split = StringUtils::Split(line, ' ');
if(int(split.size()) < 2)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid line: \"%s\"\n"), line.c_str());
return false;
}
duint code;
if(!convertNumber(split[0].c_str(), code, 16))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to convert number \"%s\"\n"), split[0].c_str());
return false;
}
names.insert({ (unsigned int)code, split[1] });
return true;
};
auto result = true;
for(const auto & line : lines)
if(!parseLine(line))
{
auto split = StringUtils::Split(line, ' ');
if(split.size() < 2)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid line in exception database: \"%s\"\n"), line.c_str());
result = false;
break;
}
duint code;
if(!convertNumber(split[0].c_str(), code, radix))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to convert number in exception database \"%s\"\n"), split[0].c_str());
result = false;
break;
}
names.insert({ (unsigned int)code, split[1] });
}
return result;
}
bool ErrorCodeInit(const String & errorFile)
{
return UniversalCodeInit(errorFile, ErrorNames, 10);
}
bool ExceptionCodeInit(const String & exceptionFile)
{
return UniversalCodeInit(exceptionFile, ExceptionNames);
return UniversalCodeInit(exceptionFile, ExceptionNames, 16);
}
String ExceptionCodeToName(unsigned int ExceptionCode)
static bool ExceptionDatabaseNameToCode(const std::unordered_map<unsigned int, String>* db, const char* Name, unsigned int* ErrorCode)
{
if(ExceptionNames.find(ExceptionCode) == ExceptionNames.end())
return NtStatusCodeToName(ExceptionCode); //try NTSTATUS codes next
for(const auto & i : *db)
{
if(i.second.compare(Name) == 0)
{
*ErrorCode = i.first;
return true;
}
}
return false;
}
return ExceptionNames[ExceptionCode];
bool ExceptionNameToCode(const char* Name, unsigned int* ErrorCode)
{
if(!ExceptionDatabaseNameToCode(&ExceptionNames, Name, ErrorCode))
return ExceptionDatabaseNameToCode(&NtStatusNames, Name, ErrorCode);
return true;
}
bool NtStatusCodeInit(const String & ntStatusFile)
{
return UniversalCodeInit(ntStatusFile, NtStatusNames);
return UniversalCodeInit(ntStatusFile, NtStatusNames, 16);
}
String NtStatusCodeToName(unsigned NtStatusCode)
static const String emptyString("");
static const String & ExceptionDatabaseCodeToName(std::unordered_map<unsigned int, String>* db, unsigned int ErrorCode, bool* success)
{
if(NtStatusNames.find(NtStatusCode) == NtStatusNames.end())
return "";
return NtStatusNames[NtStatusCode];
auto i = db->find(ErrorCode);
if(i == db->end())
{
*success = false;
return emptyString;
}
*success = true;
return i->second;
}
const String & ExceptionCodeToName(unsigned int ExceptionCode)
{
bool success;
const String & name = ExceptionDatabaseCodeToName(&ExceptionNames, ExceptionCode, &success);
if(!success)
return ExceptionDatabaseCodeToName(&NtStatusNames, ExceptionCode, &success);
else
return name;
}
const String & NtStatusCodeToName(unsigned int NtStatusCode)
{
bool success;
return ExceptionDatabaseCodeToName(&NtStatusNames, NtStatusCode, &success);
}
const String & ErrorCodeToName(unsigned int ErrorCode)
{
bool success;
return ExceptionDatabaseCodeToName(&ErrorNames, ErrorCode, &success);
}

View File

@ -4,10 +4,14 @@
#define MS_VC_EXCEPTION 0x406D1388
#include "_global.h"
#include "stringutils.h"
bool ExceptionCodeInit(const String & exceptionFile);
String ExceptionCodeToName(unsigned int ExceptionCode);
const String & ExceptionCodeToName(unsigned int ExceptionCode);
bool NtStatusCodeInit(const String & ntStatusFile);
String NtStatusCodeToName(unsigned int NtStatusCode);
const String & NtStatusCodeToName(unsigned int NtStatusCode);
bool ErrorCodeInit(const String & errorFile);
const String & ErrorCodeToName(unsigned int ErrorCode);
bool ExceptionNameToCode(const char* Name, unsigned int* ErrorCode);
#endif // _EXCEPTION_H

View File

@ -1,6 +1,6 @@
#include "handles.h"
#include "undocumented.h"
#include "error.h"
#include "exception.h"
typedef struct _OBJECT_NAME_INFORMATION
{
@ -152,7 +152,7 @@ bool HandlesGetName(HANDLE hProcess, HANDLE remoteHandle, String & name, String
if(result != WAIT_OBJECT_0)
{
TerminateThread(hThread, 0);
name = ErrorCodeToName(result);
name = String(ErrorCodeToName(result));
}
else
CloseHandle(hThread);
@ -160,6 +160,6 @@ bool HandlesGetName(HANDLE hProcess, HANDLE remoteHandle, String & name, String
CloseHandle(hLocalHandle);
}
else
name = ErrorCodeToName(GetLastError());
name = String(ErrorCodeToName(GetLastError()));
return true;
}

View File

@ -34,7 +34,6 @@
#include "_scriptapi_stack.h"
#include "threading.h"
#include "mnemonichelp.h"
#include "error.h"
#include "recursiveanalysis.h"
#include "xrefsanalysis.h"
#include "advancedanalysis.h"

View File

@ -1,5 +1,4 @@
#include "stringutils.h"
#include "memory.h"
#include "value.h"
#include "dynamicmem.h"
#include <windows.h>

View File

@ -5,7 +5,6 @@
#include <vector>
#include <sstream>
#include <iomanip>
#include "_global.h"
typedef std::string String;
typedef std::wstring WString;

View File

@ -24,7 +24,6 @@
#include "database.h"
#include "mnemonichelp.h"
#include "datainst_helper.h"
#include "error.h"
#include "exception.h"
#include "expressionfunctions.h"
#include "historycontext.h"
@ -44,7 +43,7 @@ static CMDRESULT cbStrLen(int argc, char* argv[])
dputs(QT_TRANSLATE_NOOP("DBG", "not enough arguments!"));
return STATUS_ERROR;
}
dprintf("\"%s\"[%d]\n", argv[1], strlen(argv[1]));
dprintf_untranslated("\"%s\"[%d]\n", argv[1], strlen(argv[1]));
return STATUS_CONTINUE;
}
@ -75,6 +74,9 @@ static CMDRESULT cbScriptDll(int argc, char* argv[])
return DbgScriptDllExec(argv[1]) ? STATUS_CONTINUE : STATUS_ERROR;
}
/**
\brief register the all the commands
*/
static void registercommands()
{
cmdinit();
@ -138,8 +140,12 @@ static void registercommands()
dbgcmdnew("DisableMemoryBreakpoint\1membpd\1bpmd", cbDebugDisableMemoryBreakpoint, true); //enable memory breakpoint
dbgcmdnew("LibrarianSetBreakPoint\1bpdll", cbDebugBpDll, true); //set dll breakpoint
dbgcmdnew("LibrarianRemoveBreakPoint\1bcdll", cbDebugBcDll, true); //remove dll breakpoint
dbgcmdnew("LibrarianDisableBreakPoint", cbDebugBpDllDisable, true);
dbgcmdnew("LibrarianEnableBreakPoint", cbDebugBpDllEnable, true);
dbgcmdnew("LibrarianDisableBreakPoint\1bpddll", cbDebugBpDllDisable, true);
dbgcmdnew("LibrarianEnableBreakPoint\1bpedll", cbDebugBpDllEnable, true);
dbgcmdnew("SetExceptionBPX", cbDebugSetExceptionBPX, true); //set exception breakpoint
dbgcmdnew("DeleteExceptionBPX", cbDebugDeleteExceptionBPX, true); //delete exception breakpoint
dbgcmdnew("EnableExceptionBPX", cbDebugEnableExceptionBPX, true);
dbgcmdnew("DisableExceptionBPX", cbDebugDisableExceptionBPX, true);
//breakpoints (conditional)
dbgcmdnew("SetBreakpointName\1bpname", cbDebugSetBPXName, true); //set breakpoint name
@ -186,6 +192,17 @@ static void registercommands()
dbgcmdnew("SetLibrarianBreakpointSilent", cbDebugSetBPXDLLSilent, true); //set breakpoint fast resume
dbgcmdnew("SetLibrarianGetBreakpointHitCount", cbDebugGetBPXDLLHitCount, true); //get breakpoint hit count
dbgcmdnew("ResetLibrarianBreakpointHitCount", cbDebugResetBPXDLLHitCount, true); //reset breakpoint hit count
dbgcmdnew("SetExceptionBreakpointName", cbDebugSetBPXExceptionName, true); //set breakpoint name
dbgcmdnew("SetExceptionBreakpointCondition", cbDebugSetBPXExceptionCondition, true); //set breakpoint breakCondition
dbgcmdnew("SetExceptionBreakpointLog", cbDebugSetBPXExceptionLog, true); //set breakpoint log
dbgcmdnew("SetExceptionBreakpointLogCondition", cbDebugSetBPXExceptionLogCondition, true); //set breakpoint logCondition
dbgcmdnew("SetExceptionBreakpointCommand", cbDebugSetBPXExceptionCommand, true); //set breakpoint command on hit
dbgcmdnew("SetExceptionBreakpointCommandCondition", cbDebugSetBPXExceptionCommandCondition, true); //set breakpoint commandCondition
dbgcmdnew("SetExceptionBreakpointFastResume", cbDebugSetBPXExceptionFastResume, true); //set breakpoint fast resume
dbgcmdnew("SetExceptionBreakpointSingleshoot", cbDebugSetBPXExceptionSingleshoot, true); //set breakpoint singleshoot
dbgcmdnew("SetExceptionBreakpointSilent", cbDebugSetBPXExceptionSilent, true); //set breakpoint fast resume
dbgcmdnew("SetExceptionGetBreakpointHitCount", cbDebugGetBPXExceptionHitCount, true); //get breakpoint hit count
dbgcmdnew("ResetExceptionBreakpointHitCount", cbDebugResetBPXExceptionHitCount, true); //reset breakpoint hit count
dbgcmdnew("bpgoto", cbDebugSetBPGoto, true);
@ -271,7 +288,7 @@ static void registercommands()
//general purpose
dbgcmdnew("cmp", cbInstrCmp, false); //compare
dbgcmdnew("gpa", cbInstrGpa, true);
dbgcmdnew("gpa", cbInstrGpa, true); //get proc address
dbgcmdnew("add", cbInstrAdd, false);
dbgcmdnew("and", cbInstrAnd, false);
dbgcmdnew("dec", cbInstrDec, false);
@ -381,6 +398,9 @@ static bool cbCommandProvider(char* cmd, int maxlen)
return true;
}
/**
\brief Execute command asynchronized.
*/
extern "C" DLL_EXPORT bool _dbg_dbgcmdexec(const char* cmd)
{
int len = (int)strlen(cmd);

View File

@ -54,7 +54,6 @@
<ClCompile Include="expressionfunctions.cpp" />
<ClCompile Include="exprfunc.cpp" />
<ClCompile Include="handles.cpp" />
<ClCompile Include="error.cpp" />
<ClCompile Include="exception.cpp" />
<ClCompile Include="exhandlerinfo.cpp" />
<ClCompile Include="expressionparser.cpp" />
@ -150,7 +149,6 @@
<ClInclude Include="expressionfunctions.h" />
<ClInclude Include="exprfunc.h" />
<ClInclude Include="handles.h" />
<ClInclude Include="error.h" />
<ClInclude Include="exception.h" />
<ClInclude Include="exhandlerinfo.h" />
<ClInclude Include="expressionparser.h" />

View File

@ -182,9 +182,6 @@
<ClCompile Include="loop.cpp">
<Filter>Source Files\Information</Filter>
</ClCompile>
<ClCompile Include="error.cpp">
<Filter>Source Files\Information</Filter>
</ClCompile>
<ClCompile Include="exception.cpp">
<Filter>Source Files\Information</Filter>
</ClCompile>
@ -496,9 +493,6 @@
<ClInclude Include="patches.h">
<Filter>Header Files\Information</Filter>
</ClInclude>
<ClInclude Include="error.h">
<Filter>Header Files\Information</Filter>
</ClInclude>
<ClInclude Include="exception.h">
<Filter>Header Files\Information</Filter>
</ClInclude>

View File

@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "utils.h"
#include "limits.h"
#include "error.h"
#include "exception.h"
#include "exec.h"
#include "types.h"
#include "object.h"

View File

@ -68,12 +68,26 @@ BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
mDLLBPTable->addColumnAt(8 + wCharWidth * 16, tr("Command on hit"), false);
mDLLBPTable->loadColumnFromConfig("DLLBreakpoint");
// Exception
mExceptionBPTable = new StdTable(this);
mExceptionBPTable->setContextMenuPolicy(Qt::CustomContextMenu);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 2 * sizeof(duint), tr("Excetion Code"), false);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 32, tr("Name"), false);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 8, tr("State"), false);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 10, tr("Hit count"), false);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 32, tr("Log text"), false);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 32, tr("Condition"), false);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 2, tr("Chance"), false);
mExceptionBPTable->addColumnAt(8 + wCharWidth * 16, tr("Command on hit"), false);
mExceptionBPTable->loadColumnFromConfig("ExceptionBreakpoint");
// Splitter
mSplitter = new LabeledSplitter(this);
mSplitter->addWidget(mSoftBPTable, tr("Software breakpoint"));
mSplitter->addWidget(mHardBPTable, tr("Hardware breakpoint"));
mSplitter->addWidget(mMemBPTable, tr("Memory breakpoint"));
mSplitter->addWidget(mDLLBPTable, tr("DLL breakpoint"));
mSplitter->addWidget(mExceptionBPTable, tr("Exception breakpoint"));
mSplitter->collapseLowerTabs();
// Layout
@ -105,7 +119,8 @@ BreakpointsView::BreakpointsView(QWidget* parent) : QWidget(parent)
connect(mMemBPTable, SIGNAL(selectionChangedSignal(int)), this, SLOT(selectionChangedMemorySlot()));
connect(mDLLBPTable, SIGNAL(contextMenuSignal(const QPoint &)), this, SLOT(DLLBPContextMenuSlot(const QPoint &)));
connect(mDLLBPTable, SIGNAL(selectionChangedSignal(int)), this, SLOT(selectionChangedDLLSlot()));
connect(mExceptionBPTable, SIGNAL(contextMenuSignal(const QPoint &)), this, SLOT(ExceptionBPContextMenuSlot(const QPoint &)));
connect(mExceptionBPTable, SIGNAL(selectionChangedSignal(int)), this, SLOT(selectionChangedExceptionSlot()));
mCurrentType = bp_normal;
}
@ -140,10 +155,10 @@ void BreakpointsView::reloadData()
mHardBPTable->setCellContent(wI, 3, tr("Disabled"));
mHardBPTable->setCellContent(wI, 4, QString("%1").arg(wBPList.bp[wI].hitCount));
mHardBPTable->setCellContent(wI, 5, QString().fromUtf8(wBPList.bp[wI].logText));
mHardBPTable->setCellContent(wI, 6, QString().fromUtf8(wBPList.bp[wI].breakCondition));
mHardBPTable->setCellContent(wI, 5, QString::fromUtf8(wBPList.bp[wI].logText));
mHardBPTable->setCellContent(wI, 6, QString::fromUtf8(wBPList.bp[wI].breakCondition));
mHardBPTable->setCellContent(wI, 7, wBPList.bp[wI].fastResume ? "X" : "");
mHardBPTable->setCellContent(wI, 8, QString().fromUtf8(wBPList.bp[wI].commandText));
mHardBPTable->setCellContent(wI, 8, QString::fromUtf8(wBPList.bp[wI].commandText));
QString comment;
if(GetCommentFormat(wBPList.bp[wI].addr, comment))
@ -181,10 +196,10 @@ void BreakpointsView::reloadData()
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].logText));
mSoftBPTable->setCellContent(wI, 6, QString().fromUtf8(wBPList.bp[wI].breakCondition));
mSoftBPTable->setCellContent(wI, 5, QString::fromUtf8(wBPList.bp[wI].logText));
mSoftBPTable->setCellContent(wI, 6, QString::fromUtf8(wBPList.bp[wI].breakCondition));
mSoftBPTable->setCellContent(wI, 7, wBPList.bp[wI].fastResume ? "X" : "");
mSoftBPTable->setCellContent(wI, 8, QString().fromUtf8(wBPList.bp[wI].commandText));
mSoftBPTable->setCellContent(wI, 8, QString::fromUtf8(wBPList.bp[wI].commandText));
QString comment;
if(GetCommentFormat(wBPList.bp[wI].addr, comment))
@ -221,10 +236,10 @@ void BreakpointsView::reloadData()
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].logText));
mMemBPTable->setCellContent(wI, 6, QString().fromUtf8(wBPList.bp[wI].breakCondition));
mMemBPTable->setCellContent(wI, 5, QString::fromUtf8(wBPList.bp[wI].logText));
mMemBPTable->setCellContent(wI, 6, QString::fromUtf8(wBPList.bp[wI].breakCondition));
mMemBPTable->setCellContent(wI, 7, wBPList.bp[wI].fastResume ? "X" : "");
mMemBPTable->setCellContent(wI, 8, QString().fromUtf8(wBPList.bp[wI].commandText));
mMemBPTable->setCellContent(wI, 8, QString::fromUtf8(wBPList.bp[wI].commandText));
QString comment;
if(GetCommentFormat(wBPList.bp[wI].addr, comment))
@ -250,15 +265,41 @@ void BreakpointsView::reloadData()
mDLLBPTable->setCellContent(wI, 2, tr("Disabled"));
mDLLBPTable->setCellContent(wI, 3, QString("%1").arg(wBPList.bp[wI].hitCount));
mDLLBPTable->setCellContent(wI, 4, QString().fromUtf8(wBPList.bp[wI].logText));
mDLLBPTable->setCellContent(wI, 5, QString().fromUtf8(wBPList.bp[wI].breakCondition));
mDLLBPTable->setCellContent(wI, 4, QString::fromUtf8(wBPList.bp[wI].logText));
mDLLBPTable->setCellContent(wI, 5, QString::fromUtf8(wBPList.bp[wI].breakCondition));
mDLLBPTable->setCellContent(wI, 6, wBPList.bp[wI].fastResume ? "X" : "");
mDLLBPTable->setCellContent(wI, 7, QString().fromUtf8(wBPList.bp[wI].commandText));
mDLLBPTable->setCellContent(wI, 7, QString::fromUtf8(wBPList.bp[wI].commandText));
}
mDLLBPTable->reloadData();
// Exception
DbgGetBpList(bp_exception, &wBPList);
mExceptionBPTable->setRowCount(wBPList.count);
for(wI = 0; wI < wBPList.count; wI++)
{
mExceptionBPTable->setCellContent(wI, 0, ToPtrString(wBPList.bp[wI].addr));
mExceptionBPTable->setCellContent(wI, 1, QString::fromUtf8(wBPList.bp[wI].name));
if(wBPList.bp[wI].active == false)
mExceptionBPTable->setCellContent(wI, 2, tr("Inactive"));
else if(wBPList.bp[wI].enabled == true)
mExceptionBPTable->setCellContent(wI, 2, tr("Enabled"));
else
mExceptionBPTable->setCellContent(wI, 2, tr("Disabled"));
mExceptionBPTable->setCellContent(wI, 3, QString("%1").arg(wBPList.bp[wI].hitCount));
mExceptionBPTable->setCellContent(wI, 4, QString::fromUtf8(wBPList.bp[wI].logText));
mExceptionBPTable->setCellContent(wI, 5, QString::fromUtf8(wBPList.bp[wI].breakCondition));
if(wBPList.bp[wI].slot == 1)
mExceptionBPTable->setCellContent(wI, 6, tr("First-chance"));
else if(wBPList.bp[wI].slot == 2)
mExceptionBPTable->setCellContent(wI, 6, tr("Second-chance"));
else if(wBPList.bp[wI].slot == 3)
mExceptionBPTable->setCellContent(wI, 6, tr("All")); // both first-chance and second-chance
mExceptionBPTable->setCellContent(wI, 7, QString::fromUtf8(wBPList.bp[wI].commandText));
}
if(wBPList.count)
BridgeFree(wBPList.bp);
mExceptionBPTable->reloadData();
}
void BreakpointsView::setupRightClickContextMenu()
@ -271,6 +312,7 @@ void BreakpointsView::setupRightClickContextMenu()
setupHardBPRightClickContextMenu();
setupMemBPRightClickContextMenu();
setupDLLBPRightClickContextMenu();
setupExceptionBPRightClickContextMenu();
}
/************************************************************************************
@ -936,6 +978,171 @@ void BreakpointsView::removeAllDLLBPActionSlot()
DbgCmdExec("LibrarianRemoveBreakPoint");
}
/************************************************************************************
Exception Context Menu Management
************************************************************************************/
void BreakpointsView::setupExceptionBPRightClickContextMenu()
{
// Add
mExceptionBPAddAction = new QAction(tr("&Add"), this);
connect(mExceptionBPAddAction, SIGNAL(triggered()), this, SLOT(addExceptionBPActionSlot()));
// Remove
mExceptionBPRemoveAction = new QAction(tr("&Remove"), this);
mExceptionBPRemoveAction->setShortcutContext(Qt::WidgetShortcut);
mExceptionBPTable->addAction(mExceptionBPRemoveAction);
connect(mExceptionBPRemoveAction, SIGNAL(triggered()), this, SLOT(removeExceptionBPActionSlot()));
// Remove All
mExceptionBPRemoveAllAction = new QAction(tr("Remove All"), this);
connect(mExceptionBPRemoveAllAction, SIGNAL(triggered()), this, SLOT(removeAllExceptionBPActionSlot()));
// Enable/Disable
mExceptionBPEnableDisableAction = new QAction(tr("E&nable"), this);
mExceptionBPEnableDisableAction->setShortcutContext(Qt::WidgetShortcut);
mExceptionBPTable->addAction(mExceptionBPEnableDisableAction);
connect(mExceptionBPEnableDisableAction, SIGNAL(triggered()), this, SLOT(enableDisableExceptionBPActionSlot()));
// Reset hit count
mExceptionBPResetHitCountAction = new QAction(tr("Reset hit count"), this);
mExceptionBPTable->addAction(mExceptionBPResetHitCountAction);
connect(mExceptionBPResetHitCountAction, SIGNAL(triggered()), this, SLOT(resetExceptionHitCountSlot()));
// Enable All
mExceptionBPEnableAllAction = new QAction(tr("Enable All"), this);
mExceptionBPTable->addAction(mExceptionBPEnableAllAction);
connect(mExceptionBPEnableAllAction, SIGNAL(triggered()), this, SLOT(enableAllExceptionBPActionSlot()));
// Disable All
mExceptionBPDisableAllAction = new QAction(tr("Disable All"), this);
mExceptionBPTable->addAction(mExceptionBPDisableAllAction);
connect(mExceptionBPDisableAllAction, SIGNAL(triggered()), this, SLOT(disableAllExceptionBPActionSlot()));
}
void BreakpointsView::ExceptionBPContextMenuSlot(const QPoint & pos)
{
if(!DbgIsDebugging())
return;
StdTable* table = mExceptionBPTable;
QMenu wMenu(this);
wMenu.addAction(mExceptionBPAddAction);
if(table->getRowCount() != 0)
{
int wI = 0;
duint wExceptionCode = table->getCellContent(table->getInitialSelection(), 0).toULongLong(0, 16);
BPMAP wBPList;
// Remove
wMenu.addAction(mExceptionBPRemoveAction);
// Enable/Disable
DbgGetBpList(bp_exception, &wBPList);
for(wI = 0; wI < wBPList.count; wI++)
{
if(wBPList.bp[wI].addr == wExceptionCode)
{
if(wBPList.bp[wI].active == false)
{
mExceptionBPEnableDisableAction->setText(tr("E&nable"));
wMenu.addAction(mExceptionBPEnableDisableAction);
}
else if(wBPList.bp[wI].enabled == true)
{
mExceptionBPEnableDisableAction->setText(tr("&Disable"));
wMenu.addAction(mExceptionBPEnableDisableAction);
}
else
{
mExceptionBPEnableDisableAction->setText(tr("E&nable"));
wMenu.addAction(mExceptionBPEnableDisableAction);
}
}
}
if(wBPList.count)
BridgeFree(wBPList.bp);
// Conditional
mCurrentType = bp_exception;
wMenu.addAction(mEditBreakpointAction);
wMenu.addAction(mExceptionBPResetHitCountAction);
// Separator
wMenu.addSeparator();
// Enable All
wMenu.addAction(mExceptionBPEnableAllAction);
// Disable All
wMenu.addAction(mExceptionBPDisableAllAction);
// Remove All
wMenu.addAction(mExceptionBPRemoveAllAction);
//Copy
QMenu wCopyMenu(tr("&Copy"), this);
table->setupCopyMenu(&wCopyMenu);
if(wCopyMenu.actions().length())
{
wMenu.addSeparator();
wMenu.addMenu(&wCopyMenu);
}
}
wMenu.exec(table->mapToGlobal(pos));
}
void BreakpointsView::removeExceptionBPActionSlot()
{
StdTable* table = mExceptionBPTable;
Breakpoints::removeBP(bp_exception, table->getCellContent(table->getInitialSelection(), 0).toULongLong(0, 16));
}
void BreakpointsView::enableDisableExceptionBPActionSlot()
{
StdTable* table = mExceptionBPTable;
Breakpoints::toggleBPByDisabling(bp_exception, table->getCellContent(table->getInitialSelection(), 0).toULongLong(0, 16));
table->selectNext();
}
void BreakpointsView::selectionChangedExceptionSlot()
{
mCurrentType = bp_exception;
}
void BreakpointsView::resetExceptionHitCountSlot()
{
StdTable* table = mExceptionBPTable;
QString addrText = table->getCellContent(table->getInitialSelection(), 0);
DbgCmdExecDirect(QString("ResetExceptionBreakpointHitCount \"%1\"").arg(addrText).toUtf8().constData());
reloadData();
}
void BreakpointsView::addExceptionBPActionSlot()
{
QString fileName;
if(SimpleInputBox(this, tr("Enter the exception code"), "", fileName, tr("Example: EXCEPTION_ACCESS_VIOLATION"), &DIcon("breakpoint.png")) && !fileName.isEmpty())
{
DbgCmdExec((QString("SetExceptionBPX ") + fileName).toUtf8().constData());
}
}
void BreakpointsView::enableAllExceptionBPActionSlot()
{
DbgCmdExec("EnableExceptionBPX");
}
void BreakpointsView::disableAllExceptionBPActionSlot()
{
DbgCmdExec("DisableExceptionBPX");
}
void BreakpointsView::removeAllExceptionBPActionSlot()
{
DbgCmdExec("DeleteExceptionBPX");
}
/************************************************************************************
Conditional Breakpoint Context Menu Management (Sub-menu only)
************************************************************************************/
@ -957,6 +1164,9 @@ void BreakpointsView::editBreakpointSlot()
table = mDLLBPTable;
Breakpoints::editBP(mCurrentType, table->getCellContent(table->getInitialSelection(), 1), this);
return;
case bp_exception:
table = mExceptionBPTable;
break;
default:
return;
}

View File

@ -19,6 +19,7 @@ public:
void setupSoftBPRightClickContextMenu();
void setupMemBPRightClickContextMenu();
void setupDLLBPRightClickContextMenu();
void setupExceptionBPRightClickContextMenu();
public slots:
void refreshShortcutsSlot();
@ -68,6 +69,17 @@ public slots:
void selectionChangedDLLSlot();
void resetDLLHitCountSlot();
// Exception
void ExceptionBPContextMenuSlot(const QPoint & pos);
void addExceptionBPActionSlot();
void removeExceptionBPActionSlot();
void removeAllExceptionBPActionSlot();
void enableDisableExceptionBPActionSlot();
void enableAllExceptionBPActionSlot();
void disableAllExceptionBPActionSlot();
void selectionChangedExceptionSlot();
void resetExceptionHitCountSlot();
// Conditional
void editBreakpointSlot();
@ -78,6 +90,7 @@ private:
StdTable* mSoftBPTable;
StdTable* mMemBPTable;
StdTable* mDLLBPTable;
StdTable* mExceptionBPTable;
// Conditional BP Context Menu
BPXTYPE mCurrentType;
QAction* mEditBreakpointAction;
@ -114,6 +127,15 @@ private:
QAction* mDLLBPResetHitCountAction;
QAction* mDLLBPEnableAllAction;
QAction* mDLLBPDisableAllAction;
// Exception BP Context Menu
QAction* mExceptionBPAddAction;
QAction* mExceptionBPRemoveAction;
QAction* mExceptionBPRemoveAllAction;
QAction* mExceptionBPEnableDisableAction;
QAction* mExceptionBPResetHitCountAction;
QAction* mExceptionBPEnableAllAction;
QAction* mExceptionBPDisableAllAction;
};
#endif // BREAKPOINTSVIEW_H

View File

@ -74,7 +74,10 @@ void Breakpoints::enableBP(const BRIDGEBP & bp)
{
wCmd = QString("LibrarianEnableBreakPoint \"%1\"").arg(QString(bp.mod));
}
else if(bp.type == bp_exception)
{
wCmd = QString("EnableExceptionBPX \"%1\"").arg(ToPtrString(bp.addr));
}
DbgCmdExec(wCmd.toUtf8().constData());
}
@ -136,6 +139,10 @@ void Breakpoints::disableBP(const BRIDGEBP & bp)
{
wCmd = QString("LibrarianDisableBreakPoint \"%1\"").arg(QString(bp.mod));
}
else if(bp.type == bp_exception)
{
wCmd = QString("DisableExceptionBPX \"%1\"").arg(ToPtrString(bp.addr));
}
DbgCmdExec(wCmd.toUtf8().constData());
}
@ -199,11 +206,12 @@ void Breakpoints::removeBP(const BRIDGEBP & bp)
wCmd = QString("bcdll \"%1\"").arg(QString(bp.mod));
break;
default:
{
case bp_exception:
wCmd = QString("DeleteExceptionBPX \"%1\"").arg(ToPtrString(bp.addr));
break;
}
break;
default:
break;
}
DbgCmdExec(wCmd.toUtf8().constData());
@ -522,6 +530,18 @@ void Breakpoints::editBP(BPXTYPE type, const QString & addrText, QWidget* widget
exec(QString("SetLibrarianBreakpointSilent \"%1\", %2").arg(addrText).arg(bp.silent));
exec(QString("SetLibrarianBreakpointSingleshoot \"%1\", %2").arg(addrText).arg(bp.singleshoot));
break;
case bp_exception:
exec(QString("SetExceptionBreakpointName %1, \"%2\"").arg(addrText).arg(bp.name));
exec(QString("SetExceptionBreakpointCondition %1, \"%2\"").arg(addrText).arg(bp.breakCondition));
exec(QString("SetExceptionBreakpointLog %1, \"%2\"").arg(addrText).arg(bp.logText));
exec(QString("SetExceptionBreakpointLogCondition %1, \"%2\"").arg(addrText).arg(bp.logCondition));
exec(QString("SetExceptionBreakpointCommand %1, \"%2\"").arg(addrText).arg(bp.commandText));
exec(QString("SetExceptionBreakpointCommandCondition %1, \"%2\"").arg(addrText).arg(bp.commandCondition));
exec(QString("ResetExceptionBreakpointHitCount %1, %2").arg(addrText).arg(ToPtrString(bp.hitCount)));
exec(QString("SetExceptionBreakpointFastResume %1, %2").arg(addrText).arg(bp.fastResume));
exec(QString("SetExceptionBreakpointSilent %1, %2").arg(addrText).arg(bp.silent));
exec(QString("SetExceptionBreakpointSingleshoot %1, %2").arg(addrText).arg(bp.singleshoot));
break;
default:
return;
}

View File

@ -219,6 +219,7 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "HardwareBreakpoint", 10);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "MemoryBreakpoint", 10);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "DLLBreakpoint", 8);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "ExceptionBreakpoint", 8);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "MemoryMap", 7);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "CallStack", 4);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "SEH", 4);

View File

@ -107,7 +107,6 @@ SOURCES += \
dbg/disasm_fast.cpp \
dbg/disasm_helper.cpp \
dbg/encodemap.cpp \
dbg/error.cpp \
dbg/exception.cpp \
dbg/exhandlerinfo.cpp \
dbg/expressionfunctions.cpp \
@ -306,7 +305,6 @@ HEADERS += \
dbg/disasm_helper.h \
dbg/dynamicmem.h \
dbg/encodemap.h \
dbg/error.h \
dbg/exception.h \
dbg/exhandlerinfo.h \
dbg/expressionfunctions.h \