GE Debugger: Add address breakpoint conditions.

This commit is contained in:
Unknown W. Brackets
2022-09-05 13:13:09 -07:00
parent f595299fe5
commit 0b30b723bb
7 changed files with 102 additions and 7 deletions

View File

@@ -16,19 +16,28 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <functional>
#include <map>
#include <mutex>
#include <set>
#include <vector>
#include "Common/CommonFuncs.h"
#include "Common/Math/expression_parser.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Debugger/Breakpoints.h"
#include "GPU/GPUState.h"
namespace GPUBreakpoints {
struct BreakpointInfo {
bool isConditional;
PostfixExpression expression;
std::string expressionString;
};
static std::mutex breaksLock;
static bool breakCmds[256];
static std::set<u32> breakPCs;
static std::map<u32, BreakpointInfo> breakPCs;
static std::set<u32> breakTextures;
static std::set<u32> breakRenderTargets;
// Small optimization to avoid a lock/lookup for the common case.
@@ -158,8 +167,26 @@ bool IsRenderTargetCmdBreakpoint(u32 op) {
return false;
}
static bool HitAddressBreakpoint(u32 pc) {
if (breakPCsCount == 0)
return false;
std::lock_guard<std::mutex> guard(breaksLock);
auto entry = breakPCs.find(pc);
if (entry == breakPCs.end())
return false;
if (entry->second.isConditional) {
u32 result = 1;
if (!GPUDebugExecExpression(gpuDebug, breakPCs[pc].expression, result))
return false;
return result != 0;
}
return true;
}
bool IsBreakpoint(u32 pc, u32 op) {
if (IsAddressBreakpoint(pc) || IsOpBreakpoint(op)) {
if (HitAddressBreakpoint(pc) || IsOpBreakpoint(op)) {
return true;
}
@@ -275,13 +302,13 @@ void AddAddressBreakpoint(u32 addr, bool temp) {
if (temp) {
if (breakPCs.find(addr) == breakPCs.end()) {
breakPCsTemp.insert(addr);
breakPCs.insert(addr);
breakPCs[addr].isConditional = false;
}
// Already normal breakpoint, let's not make it temporary.
} else {
// Remove the temporary marking.
breakPCsTemp.erase(addr);
breakPCs.insert(addr);
breakPCs[addr].isConditional = false;
}
breakPCsCount = breakPCs.size();
@@ -398,6 +425,44 @@ void RemoveTextureChangeTempBreakpoint() {
notifyBreakpoints(HasAnyBreakpoints());
}
static bool SetupCond(BreakpointInfo &bp, const std::string &expression, std::string *error) {
bool success = true;
if (expression.length() != 0) {
if (GPUDebugInitExpression(gpuDebug, expression.c_str(), bp.expression)) {
bp.isConditional = true;
bp.expressionString = expression;
} else {
bp.isConditional = false;
if (error)
*error = getExpressionError();
success = false;
}
} else {
bp.isConditional = false;
}
return success;
}
bool SetAddressBreakpointCond(u32 addr, const std::string &expression, std::string *error) {
// Must have one in the first place, make sure it's not temporary.
AddAddressBreakpoint(addr);
std::lock_guard<std::mutex> guard(breaksLock);
auto &bp = breakPCs[addr];
return SetupCond(breakPCs[addr], expression, error);
}
bool GetAddressBreakpointCond(u32 addr, std::string *expression) {
std::lock_guard<std::mutex> guard(breaksLock);
auto entry = breakPCs.find(addr);
if (entry != breakPCs.end() && entry->second.isConditional) {
if (expression)
*expression = entry->second.expressionString;
return true;
}
return false;
}
void UpdateLastTexture(u32 addr) {
lastTexture = addr;
}

View File

@@ -47,6 +47,9 @@ namespace GPUBreakpoints {
void RemoveTextureChangeTempBreakpoint();
void RemoveRenderTargetBreakpoint(u32 addr);
bool SetAddressBreakpointCond(u32 addr, const std::string &expression, std::string *error);
bool GetAddressBreakpointCond(u32 addr, std::string *expression);
void UpdateLastTexture(u32 addr);
void ClearAllBreakpoints();

View File

@@ -267,6 +267,17 @@ void CtrlDisplayListView::toggleBreakpoint()
SendMessage(GetParent(wnd),WM_GEDBG_TOGGLEPCBREAKPOINT,curAddress,0);
}
void CtrlDisplayListView::PromptBreakpointCond() {
std::string expression;
GPUBreakpoints::GetAddressBreakpointCond(curAddress, &expression);
if (!InputBox_GetString(GetModuleHandle(NULL), wnd, L"Expression", expression, expression))
return;
std::string error;
if (!GPUBreakpoints::SetAddressBreakpointCond(curAddress, expression, &error))
MessageBox(wnd, ConvertUTF8ToWString(error).c_str(), L"Invalid expression", MB_OK | MB_ICONEXCLAMATION);
}
void CtrlDisplayListView::onMouseDown(WPARAM wParam, LPARAM lParam, int button)
{
int y = HIWORD(lParam);
@@ -298,6 +309,9 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
{
if (button == 2)
{
HMENU menu = GetContextMenu(ContextMenuID::DISPLAYLISTVIEW);
EnableMenuItem(menu, ID_GEDBG_SETCOND, GPUBreakpoints::IsAddressBreakpoint(curAddress) ? MF_ENABLED : MF_GRAYED);
switch (TriggerContextMenu(ContextMenuID::DISPLAYLISTVIEW, wnd, ContextPoint::FromEvent(lParam)))
{
case ID_DISASM_GOTOINMEMORYVIEW:
@@ -308,6 +322,9 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
toggleBreakpoint();
redraw();
break;
case ID_GEDBG_SETCOND:
PromptBreakpointCond();
break;
case ID_DISASM_COPYINSTRUCTIONDISASM:
{
int space = 256 * (selectRangeEnd - selectRangeStart) / instructionSize;

View File

@@ -30,6 +30,8 @@ class CtrlDisplayListView
} pixelPositions;
void toggleBreakpoint();
void PromptBreakpointCond();
public:
CtrlDisplayListView(HWND _wnd);
~CtrlDisplayListView();

View File

@@ -21,7 +21,7 @@
#include <string>
#include <vector>
#include <windowsx.h>
#include "Common/CommonWindows.h"
#include <commctrl.h>
#include "Common/Data/Convert/ColorConv.h"
@@ -1114,7 +1114,13 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
bool temp;
bool isBreak = IsAddressBreakpoint(pc, temp);
if (isBreak && !temp) {
RemoveAddressBreakpoint(pc);
if (GetAddressBreakpointCond(pc, nullptr)) {
int ret = MessageBox(m_hDlg, L"This breakpoint has a custom condition.\nDo you want to remove it?", L"Confirmation", MB_YESNO);
if (ret == IDYES)
RemoveAddressBreakpoint(pc);
} else {
RemoveAddressBreakpoint(pc);
}
} else {
AddAddressBreakpoint(pc);
}

View File

@@ -763,6 +763,7 @@ BEGIN
MENUITEM "Jump to Cursor", ID_DISASM_SETPCTOHERE
MENUITEM "Set Stall", ID_GEDBG_SETSTALLADDR
MENUITEM "Toggle Breakpoint", ID_DISASM_TOGGLEBREAKPOINT
MENUITEM "Set Breakpoint Condition", ID_GEDBG_SETCOND
MENUITEM SEPARATOR
MENUITEM "Go to Displaylist PC", ID_GEDBG_GOTOPC
MENUITEM "Go to Address...", ID_GEDBG_GOTOADDR

View File

@@ -332,6 +332,7 @@
#define ID_GEDBG_SHOWONRIGHT 40220
#define ID_GEDBG_SHOWONTOPRIGHT 40221
#define IDC_GEDBG_STEPVSYNC 40222
#define ID_GEDBG_SETCOND 40223
// Dummy option to let the buffered rendering hotkey cycle through all the options.
@@ -345,7 +346,7 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 256
#define _APS_NEXT_COMMAND_VALUE 40223
#define _APS_NEXT_COMMAND_VALUE 40224
#define _APS_NEXT_CONTROL_VALUE 1202
#define _APS_NEXT_SYMED_VALUE 101
#endif