WIP: refactor the breakpoint system

This commit is contained in:
Duncan Ogilvie 2022-09-10 02:10:26 +02:00
parent b833538632
commit 26a776cca5
4 changed files with 84 additions and 50 deletions

View File

@ -25,19 +25,20 @@ static void setBpActive(BREAKPOINT & bp)
return;
}
// Breakpoints without modules need a valid address
if(!*bp.mod)
// If the breakpoint wasn't set by the engine it won't be active
if(!bp.active)
return;
if(bp.mod[0] == '\0')
{
// Breakpoints without modules need a valid address
bp.active = MemIsValidReadPtr(bp.addr);
return;
}
else
{
auto modLoaded = ModBaseFromName(bp.mod) != 0;
if(bp.type == BPHARDWARE)
bp.active = modLoaded;
else
bp.active = modLoaded && MemIsValidReadPtr(bp.addr);
// If the module unloaded the breakpoint is no longer active
bp.active = ModBaseFromName(bp.mod) != 0;
}
}
@ -73,7 +74,6 @@ int BpGetList(std::vector<BREAKPOINT>* List)
BREAKPOINT currentBp = i.second;
if(currentBp.type != BPDLL && currentBp.type != BPEXCEPTION)
currentBp.addr += ModBaseFromName(currentBp.mod);
setBpActive(currentBp);
List->push_back(currentBp);
}
@ -114,12 +114,20 @@ bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE
}
strncpy_s(bp.name, Name, _TRUNCATE);
bp.active = true;
if(Type != BPDLL && Type != BPEXCEPTION)
bp.addr = Address - ModBaseFromAddr(Address);
else
if(Type == BPDLL || Type == BPEXCEPTION)
{
// These types of breakpoints are always active
bp.active = true;
bp.addr = Address;
}
else
{
bp.addr = Address - ModBaseFromAddr(Address);
}
bp.enabled = Enable;
// TODO: a little hacky
if(Enable)
bp.active = true;
bp.oldbytes = OldBytes;
bp.singleshoot = Singleshot;
bp.titantype = TitanType;
@ -184,7 +192,6 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
*Bp = *bpInfo;
if(bpInfo->type != BPDLL && bpInfo->type != BPEXCEPTION)
Bp->addr += ModBaseFromAddr(Address);
setBpActive(*Bp);
return true;
}
@ -230,7 +237,6 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
*Bp = *bpInfo;
Bp->addr = Address;
setBpActive(*Bp);
return true;
}
free(DLLName);
@ -251,7 +257,6 @@ bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
*Bp = i.second;
if(i.second.type != BPDLL && i.second.type != BPEXCEPTION)
Bp->addr += ModBaseFromAddr(Address);
setBpActive(*Bp);
}
// Return true if the name was found at all
@ -365,6 +370,7 @@ bool BpEnable(duint Address, BP_TYPE Type, bool Enable)
return false;
bpInfo->enabled = Enable;
bpInfo->active = Enable;
//Re-read oldbytes
if(Enable && Type == BPNORMAL)
@ -409,6 +415,20 @@ bool BpSetTitanType(duint Address, BP_TYPE Type, int TitanType)
return true;
}
bool BpSetActive(duint Address, BP_TYPE Type, bool Active)
{
ASSERT_DEBUGGING("Command function call");
EXCLUSIVE_ACQUIRE(LockBreakpoints);
BREAKPOINT* bpInfo = BpInfoFromAddr(Type, Address);
if(!bpInfo)
return false;
bpInfo->active = Active;
return true;
}
bool BpSetBreakCondition(duint Address, BP_TYPE Type, const char* Condition)
{
ASSERT_DEBUGGING("Command function call");
@ -578,12 +598,17 @@ bool BpEnumAll(BPENUMCALLBACK EnumCallback, const char* Module, duint base)
BREAKPOINT bpInfo = j->second;
if(bpInfo.type != BPDLL && bpInfo.type != BPEXCEPTION)
{
if(base) //workaround for some Windows bullshit with compatibility mode
if(base) //workaround for some Windows bullshit with compatibility mode
bpInfo.addr += base;
else
bpInfo.addr += ModBaseFromName(bpInfo.mod);
{
char arg[deflen];
sprintf_s(arg, "%s:$%X", bpInfo.mod, bpInfo.addr);
BREAKPOINT found;
if(BpGet(0, bpInfo.type, arg, &found)) //found a breakpoint with name
bpInfo = found;
}
}
setBpActive(bpInfo);
// Lock must be released due to callback sub-locks
SHARED_RELEASE();

View File

@ -26,7 +26,7 @@ struct BREAKPOINT
duint addr; // address of the breakpoint (rva relative to base of mod)
bool enabled; // whether the breakpoint is enabled
bool singleshoot; // whether the breakpoint should be deleted on first hit
bool active; // whether the breakpoint is active or not
bool active; // whether the breakpoint is active (enabled + actually set) or not
bool silent; // whether the breakpoint diplays a default message when hit
unsigned short oldbytes; // original bytes (for software breakpoitns)
BP_TYPE type; // breakpoint type
@ -56,6 +56,7 @@ bool BpDelete(duint Address, BP_TYPE Type);
bool BpEnable(duint Address, BP_TYPE Type, bool Enable);
bool BpSetName(duint Address, BP_TYPE Type, const char* Name);
bool BpSetTitanType(duint Address, BP_TYPE Type, int TitanType);
bool BpSetActive(duint Address, BP_TYPE Type, bool Active);
bool BpSetBreakCondition(duint Address, BP_TYPE Type, const char* Condition);
bool BpSetLogText(duint Address, BP_TYPE Type, const char* Log);
bool BpSetLogCondition(duint Address, BP_TYPE Type, const char* Condition);

View File

@ -15,7 +15,7 @@ static bool cbDeleteAllBreakpoints(const BREAKPOINT* bp)
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete breakpoint failed (BpDelete): %p\n"), bp->addr);
return false;
}
if(bp->enabled && !DeleteBPX(bp->addr))
if(bp->active && !DeleteBPX(bp->addr))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete breakpoint failed (DeleteBPX): %p\n"), bp->addr);
return false;
@ -53,7 +53,7 @@ static bool cbDisableAllBreakpoints(const BREAKPOINT* bp)
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
if(!DeleteBPX(bp->addr))
if(bp->active && !DeleteBPX(bp->addr))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable breakpoint %p (DeleteBPX)\n"), bp->addr);
return false;
@ -192,7 +192,7 @@ bool cbDebugDeleteBPX(int argc, char* argv[])
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete breakpoint failed (bpdel): %p\n"), found.addr);
return false;
}
if(found.enabled && !DeleteBPX(found.addr))
if(found.active && !DeleteBPX(found.addr))
{
GuiUpdateAllViews();
if(!MemIsValidReadPtr(found.addr))
@ -286,7 +286,7 @@ bool cbDebugDisableBPX(int argc, char* argv[])
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable breakpoint %p (BpEnable)\n"), found.addr);
return false;
}
if(!DeleteBPX(found.addr))
if(found.active && !DeleteBPX(found.addr))
{
GuiUpdateAllViews();
if(!MemIsValidReadPtr(found.addr))
@ -313,7 +313,7 @@ bool cbDebugDisableBPX(int argc, char* argv[])
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable breakpoint %p (BpEnable)\n"), found.addr);
return false;
}
if(!DeleteBPX(found.addr))
if(found.active && !DeleteBPX(found.addr))
{
GuiUpdateAllViews();
if(!MemIsValidReadPtr(found.addr))
@ -357,16 +357,16 @@ static bool cbEnableAllHardwareBreakpoints(const BREAKPOINT* bp)
int titantype = bp->titantype;
TITANSETDRX(titantype, drx);
BpSetTitanType(bp->addr, BPHARDWARE, titantype);
if(!BpEnable(bp->addr, BPHARDWARE, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable hardware breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
if(!SetHardwareBreakPoint(bp->addr, drx, TITANGETTYPE(bp->titantype), TITANGETSIZE(bp->titantype), cbHardwareBreakpoint))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable hardware breakpoint %p (SetHardwareBreakPoint)\n"), bp->addr);
return false;
}
if(!BpEnable(bp->addr, BPHARDWARE, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable hardware breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
return true;
}
@ -641,7 +641,7 @@ static bool cbDeleteAllMemoryBreakpoints(const BREAKPOINT* bp)
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete memory breakpoint failed (BpDelete): %p\n"), bp->addr);
return false;
}
if(bp->enabled && !RemoveMemoryBPX(bp->addr, size))
if(bp->active && !RemoveMemoryBPX(bp->addr, size))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete memory breakpoint failed (RemoveMemoryBPX): %p\n"), bp->addr);
return false;
@ -655,16 +655,16 @@ static bool cbEnableAllMemoryBreakpoints(const BREAKPOINT* bp)
return true;
duint size = 0;
MemFindBaseAddr(bp->addr, &size);
if(!BpEnable(bp->addr, BPMEMORY, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable memory breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
if(!SetMemoryBPXEx(bp->addr, size, bp->titantype, !bp->singleshoot, cbMemoryBreakpoint))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable memory breakpoint %p (SetMemoryBPXEx)\n"), bp->addr);
return false;
}
if(!BpEnable(bp->addr, BPMEMORY, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable memory breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
return true;
}
@ -677,7 +677,7 @@ static bool cbDisableAllMemoryBreakpoints(const BREAKPOINT* bp)
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable memory breakpoint %p (BpEnable)\n"), bp->addr);
return false;
}
if(!RemoveMemoryBPX(bp->addr, 0))
if(bp->active && !RemoveMemoryBPX(bp->addr, 0))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable memory breakpoint %p (RemoveMemoryBPX)\n"), bp->addr);
return false;
@ -780,7 +780,7 @@ bool cbDebugDeleteMemoryBreakpoint(int argc, char* argv[])
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete memory breakpoint failed: %p (BpDelete)\n"), found.addr);
return false;
}
if(!RemoveMemoryBPX(found.addr, size))
if(found.active && !RemoveMemoryBPX(found.addr, size))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete memory breakpoint failed: %p (RemoveMemoryBPX)\n"), found.addr);
return false;
@ -801,7 +801,7 @@ bool cbDebugDeleteMemoryBreakpoint(int argc, char* argv[])
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete memory breakpoint failed: %p (BpDelete)\n"), found.addr);
return false;
}
if(!RemoveMemoryBPX(found.addr, size))
if(found.active && !RemoveMemoryBPX(found.addr, size))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Delete memory breakpoint failed: %p (RemoveMemoryBPX)\n"), found.addr);
return false;
@ -885,7 +885,7 @@ bool cbDebugDisableMemoryBreakpoint(int argc, char* argv[])
}
duint size = 0;
MemFindBaseAddr(found.addr, &size);
if(!RemoveMemoryBPX(found.addr, size))
if(found.active && !RemoveMemoryBPX(found.addr, size))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable memory breakpoint %p (RemoveMemoryBPX)\n"), found.addr);
return false;
@ -923,16 +923,16 @@ static bool cbEnableAllDllBreakpoints(const BREAKPOINT* bp)
if(bp->type != BPDLL || bp->enabled)
return true;
if(!BpEnable(bp->addr, BPDLL, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), bp->mod);
return false;
}
if(!dbgsetdllbreakpoint(bp->mod, bp->titantype, bp->singleshoot))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), bp->mod);
return false;
}
if(!BpEnable(bp->addr, BPDLL, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), bp->mod);
return false;
}
return true;
}
@ -1059,15 +1059,15 @@ bool cbDebugBpDllEnable(int argc, char* argv[])
dputs(QT_TRANSLATE_NOOP("DBG", "DLL breakpoint already enabled!"));
return true;
}
if(!dbgsetdllbreakpoint(found.mod, found.titantype, found.singleshoot))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), found.mod);
}
if(!BpEnable(found.addr, BPDLL, true))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), found.mod);
return false;
}
if(!dbgsetdllbreakpoint(found.mod, found.titantype, found.singleshoot))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), found.mod);
}
dputs(QT_TRANSLATE_NOOP("DBG", "DLL breakpoint enable!"));
GuiUpdateAllViews();
return true;

View File

@ -1098,10 +1098,12 @@ bool cbSetModuleBreakpoints(const BREAKPOINT* bp)
bp->addr,
((unsigned char*)&bp->oldbytes)[0], ((unsigned char*)&bp->oldbytes)[1],
((unsigned char*)&oldbytes)[0], ((unsigned char*)&oldbytes)[1]);
BpEnable(bp->addr, BPNORMAL, false);
BpEnable(bp->addr, bp->type, false);
}
else if(!SetBPX(bp->addr, bp->titantype, cbUserBreakpoint))
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not set breakpoint %p! (SetBPX)\n"), bp->addr);
else
BpSetActive(bp->addr, bp->type, true);
}
else
dprintf(QT_TRANSLATE_NOOP("DBG", "MemRead failed on breakpoint address %p!\n"), bp->addr);
@ -1114,6 +1116,8 @@ bool cbSetModuleBreakpoints(const BREAKPOINT* bp)
MemFindBaseAddr(bp->addr, &size);
if(!SetMemoryBPXEx(bp->addr, size, bp->titantype, !bp->singleshoot, cbMemoryBreakpoint))
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not set memory breakpoint %p! (SetMemoryBPXEx)\n"), bp->addr);
else
BpSetActive(bp->addr, bp->type, true);
}
break;
@ -1127,11 +1131,14 @@ bool cbSetModuleBreakpoints(const BREAKPOINT* bp)
}
int titantype = bp->titantype;
TITANSETDRX(titantype, drx);
BpSetTitanType(bp->addr, BPHARDWARE, titantype);
BpSetTitanType(bp->addr, bp->type, titantype);
if(!SetHardwareBreakPoint(bp->addr, drx, TITANGETTYPE(bp->titantype), TITANGETSIZE(bp->titantype), cbHardwareBreakpoint))
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not set hardware breakpoint %p! (SetHardwareBreakPoint)\n"), bp->addr);
else
{
BpSetActive(bp->addr, bp->type, true);
dprintf(QT_TRANSLATE_NOOP("DBG", "Set hardware breakpoint on %p!\n"), bp->addr);
}
}
break;
@ -1177,6 +1184,7 @@ static bool cbRemoveModuleBreakpoints(const BREAKPOINT* bp)
default:
break;
}
BpSetActive(bp->addr, bp->type, false);
return true;
}