Debugger: Allow logging on CPU breakpoints.

This commit is contained in:
Unknown W. Brackets 2016-08-04 12:39:29 -07:00
parent a9ad0cd471
commit 9972e5b10a
7 changed files with 96 additions and 58 deletions

View file

@ -114,7 +114,7 @@ size_t CBreakPoints::FindBreakpoint(u32 addr, bool matchTemp, bool temp)
const auto &bp = breakPoints_[i];
if (bp.addr == addr && (!matchTemp || bp.temporary == temp))
{
if (bp.enabled)
if (bp.IsEnabled())
return i;
// Hold out until the first enabled one.
if (found == INVALID_BREAKPOINT)
@ -139,14 +139,15 @@ size_t CBreakPoints::FindMemCheck(u32 start, u32 end)
bool CBreakPoints::IsAddressBreakPoint(u32 addr)
{
size_t bp = FindBreakpoint(addr);
return bp != INVALID_BREAKPOINT && breakPoints_[bp].enabled;
return bp != INVALID_BREAKPOINT && breakPoints_[bp].result != BREAK_ACTION_IGNORE;
}
bool CBreakPoints::IsAddressBreakPoint(u32 addr, bool* enabled)
{
size_t bp = FindBreakpoint(addr);
if (bp == INVALID_BREAKPOINT) return false;
if (enabled != NULL) *enabled = breakPoints_[bp].enabled;
if (enabled != nullptr)
*enabled = breakPoints_[bp].IsEnabled();
return true;
}
@ -174,16 +175,16 @@ void CBreakPoints::AddBreakPoint(u32 addr, bool temp)
if (bp == INVALID_BREAKPOINT)
{
BreakPoint pt;
pt.enabled = true;
pt.result |= BREAK_ACTION_PAUSE;
pt.temporary = temp;
pt.addr = addr;
breakPoints_.push_back(pt);
Update(addr);
}
else if (!breakPoints_[bp].enabled)
else if (!breakPoints_[bp].IsEnabled())
{
breakPoints_[bp].enabled = true;
breakPoints_[bp].result |= BREAK_ACTION_PAUSE;
breakPoints_[bp].hasCond = false;
Update(addr);
}
@ -210,7 +211,20 @@ void CBreakPoints::ChangeBreakPoint(u32 addr, bool status)
size_t bp = FindBreakpoint(addr);
if (bp != INVALID_BREAKPOINT)
{
breakPoints_[bp].enabled = status;
if (status)
breakPoints_[bp].result |= BREAK_ACTION_PAUSE;
else
breakPoints_[bp].result = BreakAction(breakPoints_[bp].result & ~BREAK_ACTION_PAUSE);
Update(addr);
}
}
void CBreakPoints::ChangeBreakPoint(u32 addr, BreakAction result)
{
size_t bp = FindBreakpoint(addr);
if (bp != INVALID_BREAKPOINT)
{
breakPoints_[bp].result = result;
Update(addr);
}
}
@ -272,6 +286,30 @@ BreakPointCond *CBreakPoints::GetBreakPointCondition(u32 addr)
return NULL;
}
BreakAction CBreakPoints::ExecBreakPoint(u32 addr) {
size_t bp = FindBreakpoint(addr, false);
if (bp != INVALID_BREAKPOINT) {
if (breakPoints_[bp].hasCond) {
// Evaluate the breakpoint and abort if necessary.
auto cond = CBreakPoints::GetBreakPointCondition(currentMIPS->pc);
if (cond && !cond->Evaluate())
return BREAK_ACTION_IGNORE;
}
if (breakPoints_[bp].result & BREAK_ACTION_LOG) {
NOTICE_LOG(JIT, "BKP PC=%08x (%s)", addr, g_symbolMap->GetDescription(addr).c_str());
}
if (breakPoints_[bp].result & BREAK_ACTION_PAUSE) {
Core_EnableStepping(true);
host->SetDebugMode(true);
}
return breakPoints_[bp].result;
}
return BREAK_ACTION_IGNORE;
}
void CBreakPoints::AddMemCheck(u32 start, u32 end, MemCheckCondition cond, BreakAction result)
{
// This will ruin any pending memchecks.

View file

@ -26,10 +26,17 @@ enum BreakAction
BREAK_ACTION_IGNORE = 0x00,
BREAK_ACTION_LOG = 0x01,
BREAK_ACTION_PAUSE = 0x02,
BREAK_ACTION_BOTH = 0x03,
};
static inline BreakAction &operator |= (BreakAction &lhs, const BreakAction &rhs) {
lhs = BreakAction(lhs | rhs);
return lhs;
}
static inline BreakAction operator | (const BreakAction &lhs, const BreakAction &rhs) {
return BreakAction((u32)lhs | (u32)rhs);
}
struct BreakPointCond
{
DebugInterface *debug;
@ -54,12 +61,17 @@ struct BreakPoint
BreakPoint() : hasCond(false) {}
u32 addr;
bool enabled;
bool temporary;
BreakAction result;
bool hasCond;
BreakPointCond cond;
bool IsEnabled() const {
return (result & BREAK_ACTION_PAUSE) != 0;
}
bool operator == (const BreakPoint &other) const {
return addr == other.addr;
}
@ -100,6 +112,10 @@ struct MemCheck
void Log(u32 addr, bool write, int size, u32 pc);
bool IsEnabled() const {
return (result & BREAK_ACTION_PAUSE) != 0;
}
bool operator == (const MemCheck &other) const {
return start == other.start && end == other.end;
}
@ -121,6 +137,7 @@ public:
static void AddBreakPoint(u32 addr, bool temp = false);
static void RemoveBreakPoint(u32 addr);
static void ChangeBreakPoint(u32 addr, bool enable);
static void ChangeBreakPoint(u32 addr, BreakAction result);
static void ClearAllBreakPoints();
static void ClearTemporaryBreakPoints();
@ -129,6 +146,8 @@ public:
static void ChangeBreakPointRemoveCond(u32 addr);
static BreakPointCond *GetBreakPointCondition(u32 addr);
static BreakAction ExecBreakPoint(u32 addr);
static void AddMemCheck(u32 start, u32 end, MemCheckCondition cond, BreakAction result);
static void RemoveMemCheck(u32 start, u32 end);
static void ChangeMemCheck(u32 start, u32 end, MemCheckCondition cond, BreakAction result);

View file

@ -37,14 +37,8 @@ u32 RunBreakpoint(u32 pc) {
if (CBreakPoints::CheckSkipFirst() == pc)
return 0;
auto cond = CBreakPoints::GetBreakPointCondition(pc);
if (cond && !cond->Evaluate())
return 0;
Core_EnableStepping(true);
host->SetDebugMode(true);
return 1;
CBreakPoints::ExecBreakPoint(currentMIPS->pc);
return coreState != CORE_RUNNING ? 1 : 0;
}
u32 RunMemCheck(u32 pc, u32 addr) {

View file

@ -73,13 +73,10 @@ u32 JitBreakpoint()
if (CBreakPoints::CheckSkipFirst() == currentMIPS->pc)
return 0;
auto cond = CBreakPoints::GetBreakPointCondition(currentMIPS->pc);
if (cond && !cond->Evaluate())
BreakAction result = CBreakPoints::ExecBreakPoint(currentMIPS->pc);
if ((result & BREAK_ACTION_PAUSE) == 0)
return 0;
Core_EnableStepping(true);
host->SetDebugMode(true);
// There's probably a better place for this.
if (USE_JIT_MISSMAP) {
std::map<u32, std::string> notJitSorted;

View file

@ -28,7 +28,6 @@ INT_PTR CALLBACK BreakpointWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam,
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_ONCHANGE),bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),bp->memory);
if (bp->address != -1)
@ -55,7 +54,6 @@ INT_PTR CALLBACK BreakpointWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam,
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_ONCHANGE),bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),bp->memory);
break;
}
break;
@ -69,7 +67,6 @@ INT_PTR CALLBACK BreakpointWindow::dlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam,
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_ONCHANGE),bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_SIZE),bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_CONDITION),!bp->memory);
EnableWindow(GetDlgItem(hwnd,IDC_BREAKPOINT_LOG),bp->memory);
break;
}
break;
@ -183,6 +180,12 @@ bool BreakpointWindow::exec()
void BreakpointWindow::addBreakpoint()
{
BreakAction result = BREAK_ACTION_IGNORE;
if (log)
result |= BREAK_ACTION_LOG;
if (enabled)
result |= BREAK_ACTION_PAUSE;
if (memory)
{
// add memcheck
@ -194,13 +197,7 @@ void BreakpointWindow::addBreakpoint()
if (onChange)
cond |= MEMCHECK_WRITE_ONCHANGE;
int result = BREAK_ACTION_IGNORE;
if (log)
result |= BREAK_ACTION_LOG;
if (enabled)
result |= BREAK_ACTION_PAUSE;
CBreakPoints::AddMemCheck(address, address + size, (MemCheckCondition)cond, (BreakAction)result);
CBreakPoints::AddMemCheck(address, address + size, (MemCheckCondition)cond, result);
} else {
// add breakpoint
CBreakPoints::AddBreakPoint(address,false);
@ -214,10 +211,7 @@ void BreakpointWindow::addBreakpoint()
CBreakPoints::ChangeBreakPointAddCond(address,cond);
}
if (enabled == false)
{
CBreakPoints::ChangeBreakPoint(address,false);
}
CBreakPoints::ChangeBreakPoint(address, result);
}
}
@ -240,12 +234,12 @@ void BreakpointWindow::loadFromBreakpoint(BreakPoint& breakpoint)
{
memory = false;
enabled = breakpoint.enabled;
log = (breakpoint.result & BREAK_ACTION_LOG) != 0;
enabled = (breakpoint.result & BREAK_ACTION_PAUSE) != 0;
address = breakpoint.addr;
size = 1;
if (breakpoint.hasCond)
{
if (breakpoint.hasCond) {
strcpy(condition,breakpoint.cond.expressionString);
} else {
condition[0] = 0;

View file

@ -1,4 +1,4 @@
// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
#include "Windows/resource.h"
#include "Core/MemMap.h"
@ -550,7 +550,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
if (isInInterval(address,line.totalSize,debugger->getPC()))
{
TextOut(hdc,pixelPositions.opcodeStart-8,rowY1,L"",1);
TextOut(hdc,pixelPositions.opcodeStart-8,rowY1,L"\x25A0",1);
}
// display whether the condition of a branch is met
@ -834,22 +834,18 @@ void CtrlDisAsmView::redraw()
void CtrlDisAsmView::toggleBreakpoint(bool toggleEnabled)
{
bool enabled;
if (CBreakPoints::IsAddressBreakPoint(curAddress,&enabled))
{
if (!enabled)
{
if (CBreakPoints::IsAddressBreakPoint(curAddress, &enabled)) {
if (!enabled) {
// enable disabled breakpoints
CBreakPoints::ChangeBreakPoint(curAddress,true);
} else if (!toggleEnabled && CBreakPoints::GetBreakPointCondition(curAddress) != NULL)
{
CBreakPoints::ChangeBreakPoint(curAddress, true);
} else if (!toggleEnabled && CBreakPoints::GetBreakPointCondition(curAddress) != nullptr) {
// don't just delete a breakpoint with a custom condition
int ret = MessageBox(wnd,L"This breakpoint has a custom condition.\nDo you want to remove it?",L"Confirmation",MB_YESNO);
if (ret == IDYES)
CBreakPoints::RemoveBreakPoint(curAddress);
} else if (toggleEnabled)
{
} else if (toggleEnabled) {
// disable breakpoint
CBreakPoints::ChangeBreakPoint(curAddress,false);
CBreakPoints::ChangeBreakPoint(curAddress, false);
} else {
// otherwise just remove breakpoint
CBreakPoints::RemoveBreakPoint(curAddress);

View file

@ -324,9 +324,9 @@ void CtrlBreakpointList::reloadBreakpoints()
continue;
if (isMemory)
SetCheckState(i, (displayedMemChecks_[index].result & BREAK_ACTION_PAUSE) != 0);
SetCheckState(i, displayedMemChecks_[index].IsEnabled());
else
SetCheckState(i, displayedBreakPoints_[index].enabled);
SetCheckState(i, displayedBreakPoints_[index].IsEnabled());
}
}
@ -368,7 +368,7 @@ void CtrlBreakpointList::toggleEnabled(int itemIndex)
CBreakPoints::ChangeMemCheck(mcPrev.start, mcPrev.end, mcPrev.cond, BreakAction(mcPrev.result ^ BREAK_ACTION_PAUSE));
} else {
BreakPoint bpPrev = displayedBreakPoints_[index];
CBreakPoints::ChangeBreakPoint(bpPrev.addr, !bpPrev.enabled);
CBreakPoints::ChangeBreakPoint(bpPrev.addr, BreakAction(bpPrev.result ^ BREAK_ACTION_PAUSE));
}
}
@ -605,9 +605,9 @@ void CtrlBreakpointList::showBreakpointMenu(int itemIndex, const POINT &pt)
HMENU subMenu = GetSubMenu(g_hPopupMenus, POPUP_SUBMENU_ID_BREAKPOINTLIST);
if (isMemory) {
CheckMenuItem(subMenu, ID_DISASM_DISABLEBREAKPOINT, MF_BYCOMMAND | (mcPrev.result & BREAK_ACTION_PAUSE ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(subMenu, ID_DISASM_DISABLEBREAKPOINT, MF_BYCOMMAND | (mcPrev.IsEnabled() ? MF_CHECKED : MF_UNCHECKED));
} else {
CheckMenuItem(subMenu, ID_DISASM_DISABLEBREAKPOINT, MF_BYCOMMAND | (bpPrev.enabled ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(subMenu, ID_DISASM_DISABLEBREAKPOINT, MF_BYCOMMAND | (bpPrev.IsEnabled() ? MF_CHECKED : MF_UNCHECKED));
}
switch (TrackPopupMenuEx(subMenu, TPM_RIGHTBUTTON | TPM_RETURNCMD, screenPt.x, screenPt.y, GetHandle(), 0))
@ -616,7 +616,7 @@ void CtrlBreakpointList::showBreakpointMenu(int itemIndex, const POINT &pt)
if (isMemory) {
CBreakPoints::ChangeMemCheck(mcPrev.start, mcPrev.end, mcPrev.cond, BreakAction(mcPrev.result ^ BREAK_ACTION_PAUSE));
} else {
CBreakPoints::ChangeBreakPoint(bpPrev.addr, !bpPrev.enabled);
CBreakPoints::ChangeBreakPoint(bpPrev.addr, BreakAction(bpPrev.result ^ BREAK_ACTION_PAUSE));
}
break;
case ID_DISASM_EDITBREAKPOINT: