Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/Debugger/BreakpointWindow.cpp
3185 views
1
#include <cstdio>
2
3
#include "Common/Data/Encoding/Utf8.h"
4
#include "Common/Math/expression_parser.h"
5
6
#include "Core/Debugger/Breakpoints.h"
7
#include "BreakpointWindow.h"
8
#include "../resource.h"
9
10
INT_PTR CALLBACK BreakpointWindow::StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
11
BreakpointWindow *thiz;
12
if (iMsg == WM_INITDIALOG) {
13
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam);
14
thiz = (BreakpointWindow *)lParam;
15
}
16
else {
17
thiz = (BreakpointWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
18
}
19
20
if (!thiz)
21
return FALSE;
22
return thiz->DlgFunc(hWnd, iMsg, wParam, lParam);
23
}
24
25
INT_PTR BreakpointWindow::DlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
26
{
27
char str[128];
28
29
switch (iMsg)
30
{
31
case WM_INITDIALOG:
32
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_EXECUTE), BM_SETCHECK, memory ? BST_UNCHECKED : BST_CHECKED, 0);
33
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_MEMORY), BM_SETCHECK, memory ? BST_CHECKED : BST_UNCHECKED, 0);
34
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), BM_SETCHECK, read ? BST_CHECKED : BST_UNCHECKED, 0);
35
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), BM_SETCHECK, write ? BST_CHECKED : BST_UNCHECKED, 0);
36
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), BM_SETCHECK, onChange ? BST_CHECKED : BST_UNCHECKED, 0);
37
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_ENABLED), BM_SETCHECK, enabled ? BST_CHECKED : BST_UNCHECKED, 0);
38
SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG), BM_SETCHECK, log ? BST_CHECKED : BST_UNCHECKED, 0);
39
40
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);
41
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);
42
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);
43
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);
44
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), log);
45
46
if (address != -1) {
47
snprintf(str, sizeof(str), "0x%08X", address);
48
SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str);
49
}
50
51
snprintf(str, sizeof(str), "0x%08X", size);
52
SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str);
53
54
SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), ConvertUTF8ToWString(condition).c_str());
55
SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), ConvertUTF8ToWString(logFormat).c_str());
56
return TRUE;
57
case WM_COMMAND:
58
switch (LOWORD(wParam))
59
{
60
case IDC_BREAKPOINT_EXECUTE:
61
switch (HIWORD(wParam))
62
{
63
case BN_CLICKED:
64
memory = false;
65
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);
66
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);
67
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);
68
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);
69
break;
70
}
71
break;
72
case IDC_BREAKPOINT_MEMORY:
73
switch (HIWORD(wParam))
74
{
75
case BN_CLICKED:
76
memory = true;
77
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);
78
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);
79
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);
80
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);
81
break;
82
}
83
break;
84
case IDC_BREAKPOINT_LOG:
85
switch (HIWORD(wParam))
86
{
87
case BN_CLICKED:
88
EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), GetCheckState(hwnd, IDC_BREAKPOINT_LOG));
89
break;
90
}
91
break;
92
case IDC_BREAKPOINT_OK:
93
switch (HIWORD(wParam))
94
{
95
case BN_CLICKED:
96
if (fetchDialogData(hwnd)) {
97
EndDialog(hwnd, true);
98
}
99
break;
100
};
101
break;
102
case IDC_BREAKPOINT_CANCEL:
103
switch (HIWORD(wParam))
104
{
105
case BN_CLICKED:
106
EndDialog(hwnd, false);
107
break;
108
};
109
break;
110
case IDOK:
111
if (fetchDialogData(hwnd)) {
112
EndDialog(hwnd, true);
113
}
114
break;
115
case IDCANCEL:
116
EndDialog(hwnd, false);
117
break;
118
}
119
}
120
121
return FALSE;
122
}
123
124
bool BreakpointWindow::fetchDialogData(HWND hwnd)
125
{
126
char str[256], errorMessage[512];
127
PostfixExpression exp;
128
129
memory = GetCheckState(hwnd, IDC_BREAKPOINT_MEMORY);
130
read = GetCheckState(hwnd, IDC_BREAKPOINT_READ);
131
write = GetCheckState(hwnd, IDC_BREAKPOINT_WRITE);
132
enabled = GetCheckState(hwnd, IDC_BREAKPOINT_ENABLED);
133
log = GetCheckState(hwnd, IDC_BREAKPOINT_LOG);
134
onChange = GetCheckState(hwnd, IDC_BREAKPOINT_ONCHANGE);
135
136
// parse address
137
GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str, 256);
138
if (initExpression(cpu, str, exp) == false)
139
{
140
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
141
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
142
return false;
143
}
144
145
if (parseExpression(cpu, exp, address) == false)
146
{
147
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
148
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
149
return false;
150
}
151
152
if (memory)
153
{
154
// parse size
155
GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str, 256);
156
if (initExpression(cpu, str, exp) == false)
157
{
158
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
159
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
160
return false;
161
}
162
163
if (parseExpression(cpu, exp, size) == false)
164
{
165
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());
166
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
167
return false;
168
}
169
}
170
171
// condition
172
wchar_t tempCond[512];
173
GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), tempCond, 512);
174
condition = ConvertWStringToUTF8(tempCond);
175
compiledCondition.clear();
176
if (!condition.empty())
177
{
178
if (initExpression(cpu, condition.c_str(), compiledCondition) == false)
179
{
180
snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", condition.c_str(), getExpressionError());
181
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
182
return false;
183
}
184
}
185
186
wchar_t tempLogFormat[512];
187
GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), tempLogFormat, 512);
188
logFormat = ConvertWStringToUTF8(tempLogFormat);
189
if (!g_breakpoints.ValidateLogFormat(cpu, logFormat)) {
190
snprintf(errorMessage, sizeof(errorMessage), "Invalid log format (example: \"{a1}\").");
191
MessageBoxA(hwnd, errorMessage, "Error", MB_OK);
192
return false;
193
}
194
195
return true;
196
}
197
198
bool BreakpointWindow::GetCheckState(HWND hwnd, int dlgItem) {
199
return SendMessage(GetDlgItem(hwnd, dlgItem), BM_GETCHECK, 0, 0) != 0;
200
}
201
202
bool BreakpointWindow::exec() {
203
return DialogBoxParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_BREAKPOINT), parentHwnd, StaticDlgFunc, (LPARAM)this) != 0;
204
}
205
206
void BreakpointWindow::addBreakpoint() {
207
BreakAction result = BREAK_ACTION_IGNORE;
208
if (log)
209
result |= BREAK_ACTION_LOG;
210
if (enabled)
211
result |= BREAK_ACTION_PAUSE;
212
213
if (memory) {
214
// add memcheck
215
int cond = 0;
216
if (read)
217
cond |= MEMCHECK_READ;
218
if (write)
219
cond |= MEMCHECK_WRITE;
220
if (onChange)
221
cond |= MEMCHECK_WRITE_ONCHANGE;
222
223
g_breakpoints.AddMemCheck(address, address + size, (MemCheckCondition)cond, result);
224
225
if (!condition.empty()) {
226
BreakPointCond cond;
227
cond.debug = cpu;
228
cond.expressionString = condition;
229
cond.expression = compiledCondition;
230
g_breakpoints.ChangeMemCheckAddCond(address, address + size, cond);
231
}
232
233
g_breakpoints.ChangeMemCheckLogFormat(address, address + size, logFormat);
234
}
235
else {
236
// add breakpoint
237
g_breakpoints.AddBreakPoint(address, false);
238
239
if (!condition.empty()) {
240
BreakPointCond cond;
241
cond.debug = cpu;
242
cond.expressionString = condition;
243
cond.expression = compiledCondition;
244
g_breakpoints.ChangeBreakPointAddCond(address, cond);
245
}
246
247
g_breakpoints.ChangeBreakPoint(address, result);
248
g_breakpoints.ChangeBreakPointLogFormat(address, logFormat);
249
}
250
}
251
252
void BreakpointWindow::loadFromMemcheck(const MemCheck &memcheck) {
253
memory = true;
254
255
read = (memcheck.cond & MEMCHECK_READ) != 0;
256
write = (memcheck.cond & MEMCHECK_WRITE) != 0;
257
onChange = (memcheck.cond & MEMCHECK_WRITE_ONCHANGE) != 0;
258
259
log = (memcheck.result & BREAK_ACTION_LOG) != 0;
260
enabled = (memcheck.result & BREAK_ACTION_PAUSE) != 0;
261
262
address = memcheck.start;
263
size = memcheck.end - address;
264
265
if (memcheck.hasCondition) {
266
condition = memcheck.condition.expressionString;
267
}
268
else {
269
condition.clear();
270
}
271
272
logFormat = memcheck.logFormat;
273
}
274
275
void BreakpointWindow::loadFromBreakpoint(const BreakPoint& breakpoint) {
276
memory = false;
277
278
log = (breakpoint.result & BREAK_ACTION_LOG) != 0;
279
enabled = (breakpoint.result & BREAK_ACTION_PAUSE) != 0;
280
address = breakpoint.addr;
281
size = 1;
282
283
if (breakpoint.hasCond) {
284
condition = breakpoint.cond.expressionString;
285
}
286
else {
287
condition.clear();
288
}
289
290
logFormat = breakpoint.logFormat;
291
}
292
293
void BreakpointWindow::initBreakpoint(u32 _address) {
294
memory = false;
295
enabled = true;
296
address = _address;
297
size = 1;
298
condition.clear();
299
}
300
301