conditional exception breakpoint (#1073)
* temporary * Exception breakpoints * temporary * temporary * temporary * fixes * fully retire "error"
This commit is contained in:
parent
ac0853ffec
commit
9288c910cb
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ enum BP_TYPE
|
|||
BPNORMAL = 0,
|
||||
BPHARDWARE = 1,
|
||||
BPMEMORY = 2,
|
||||
BPDLL = 3
|
||||
BPDLL = 3,
|
||||
BPEXCEPTION = 4
|
||||
};
|
||||
|
||||
struct BREAKPOINT
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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[]);
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#include "stringutils.h"
|
||||
#include "memory.h"
|
||||
#include "value.h"
|
||||
#include "dynamicmem.h"
|
||||
#include <windows.h>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include "_global.h"
|
||||
|
||||
typedef std::string String;
|
||||
typedef std::wstring WString;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
Loading…
Reference in New Issue