Path: blob/master/Windows/Debugger/BreakpointWindow.cpp
3185 views
#include <cstdio>12#include "Common/Data/Encoding/Utf8.h"3#include "Common/Math/expression_parser.h"45#include "Core/Debugger/Breakpoints.h"6#include "BreakpointWindow.h"7#include "../resource.h"89INT_PTR CALLBACK BreakpointWindow::StaticDlgFunc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {10BreakpointWindow *thiz;11if (iMsg == WM_INITDIALOG) {12SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam);13thiz = (BreakpointWindow *)lParam;14}15else {16thiz = (BreakpointWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);17}1819if (!thiz)20return FALSE;21return thiz->DlgFunc(hWnd, iMsg, wParam, lParam);22}2324INT_PTR BreakpointWindow::DlgFunc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)25{26char str[128];2728switch (iMsg)29{30case WM_INITDIALOG:31SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_EXECUTE), BM_SETCHECK, memory ? BST_UNCHECKED : BST_CHECKED, 0);32SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_MEMORY), BM_SETCHECK, memory ? BST_CHECKED : BST_UNCHECKED, 0);33SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), BM_SETCHECK, read ? BST_CHECKED : BST_UNCHECKED, 0);34SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), BM_SETCHECK, write ? BST_CHECKED : BST_UNCHECKED, 0);35SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), BM_SETCHECK, onChange ? BST_CHECKED : BST_UNCHECKED, 0);36SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_ENABLED), BM_SETCHECK, enabled ? BST_CHECKED : BST_UNCHECKED, 0);37SendMessage(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG), BM_SETCHECK, log ? BST_CHECKED : BST_UNCHECKED, 0);3839EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);40EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);41EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);42EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);43EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), log);4445if (address != -1) {46snprintf(str, sizeof(str), "0x%08X", address);47SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str);48}4950snprintf(str, sizeof(str), "0x%08X", size);51SetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str);5253SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), ConvertUTF8ToWString(condition).c_str());54SetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), ConvertUTF8ToWString(logFormat).c_str());55return TRUE;56case WM_COMMAND:57switch (LOWORD(wParam))58{59case IDC_BREAKPOINT_EXECUTE:60switch (HIWORD(wParam))61{62case BN_CLICKED:63memory = false;64EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);65EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);66EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);67EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);68break;69}70break;71case IDC_BREAKPOINT_MEMORY:72switch (HIWORD(wParam))73{74case BN_CLICKED:75memory = true;76EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_READ), memory);77EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_WRITE), memory);78EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_ONCHANGE), memory);79EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), memory);80break;81}82break;83case IDC_BREAKPOINT_LOG:84switch (HIWORD(wParam))85{86case BN_CLICKED:87EnableWindow(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), GetCheckState(hwnd, IDC_BREAKPOINT_LOG));88break;89}90break;91case IDC_BREAKPOINT_OK:92switch (HIWORD(wParam))93{94case BN_CLICKED:95if (fetchDialogData(hwnd)) {96EndDialog(hwnd, true);97}98break;99};100break;101case IDC_BREAKPOINT_CANCEL:102switch (HIWORD(wParam))103{104case BN_CLICKED:105EndDialog(hwnd, false);106break;107};108break;109case IDOK:110if (fetchDialogData(hwnd)) {111EndDialog(hwnd, true);112}113break;114case IDCANCEL:115EndDialog(hwnd, false);116break;117}118}119120return FALSE;121}122123bool BreakpointWindow::fetchDialogData(HWND hwnd)124{125char str[256], errorMessage[512];126PostfixExpression exp;127128memory = GetCheckState(hwnd, IDC_BREAKPOINT_MEMORY);129read = GetCheckState(hwnd, IDC_BREAKPOINT_READ);130write = GetCheckState(hwnd, IDC_BREAKPOINT_WRITE);131enabled = GetCheckState(hwnd, IDC_BREAKPOINT_ENABLED);132log = GetCheckState(hwnd, IDC_BREAKPOINT_LOG);133onChange = GetCheckState(hwnd, IDC_BREAKPOINT_ONCHANGE);134135// parse address136GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_ADDRESS), str, 256);137if (initExpression(cpu, str, exp) == false)138{139snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());140MessageBoxA(hwnd, errorMessage, "Error", MB_OK);141return false;142}143144if (parseExpression(cpu, exp, address) == false)145{146snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());147MessageBoxA(hwnd, errorMessage, "Error", MB_OK);148return false;149}150151if (memory)152{153// parse size154GetWindowTextA(GetDlgItem(hwnd, IDC_BREAKPOINT_SIZE), str, 256);155if (initExpression(cpu, str, exp) == false)156{157snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());158MessageBoxA(hwnd, errorMessage, "Error", MB_OK);159return false;160}161162if (parseExpression(cpu, exp, size) == false)163{164snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", str, getExpressionError());165MessageBoxA(hwnd, errorMessage, "Error", MB_OK);166return false;167}168}169170// condition171wchar_t tempCond[512];172GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_CONDITION), tempCond, 512);173condition = ConvertWStringToUTF8(tempCond);174compiledCondition.clear();175if (!condition.empty())176{177if (initExpression(cpu, condition.c_str(), compiledCondition) == false)178{179snprintf(errorMessage, sizeof(errorMessage), "Invalid expression \"%s\": %s", condition.c_str(), getExpressionError());180MessageBoxA(hwnd, errorMessage, "Error", MB_OK);181return false;182}183}184185wchar_t tempLogFormat[512];186GetWindowTextW(GetDlgItem(hwnd, IDC_BREAKPOINT_LOG_FORMAT), tempLogFormat, 512);187logFormat = ConvertWStringToUTF8(tempLogFormat);188if (!g_breakpoints.ValidateLogFormat(cpu, logFormat)) {189snprintf(errorMessage, sizeof(errorMessage), "Invalid log format (example: \"{a1}\").");190MessageBoxA(hwnd, errorMessage, "Error", MB_OK);191return false;192}193194return true;195}196197bool BreakpointWindow::GetCheckState(HWND hwnd, int dlgItem) {198return SendMessage(GetDlgItem(hwnd, dlgItem), BM_GETCHECK, 0, 0) != 0;199}200201bool BreakpointWindow::exec() {202return DialogBoxParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_BREAKPOINT), parentHwnd, StaticDlgFunc, (LPARAM)this) != 0;203}204205void BreakpointWindow::addBreakpoint() {206BreakAction result = BREAK_ACTION_IGNORE;207if (log)208result |= BREAK_ACTION_LOG;209if (enabled)210result |= BREAK_ACTION_PAUSE;211212if (memory) {213// add memcheck214int cond = 0;215if (read)216cond |= MEMCHECK_READ;217if (write)218cond |= MEMCHECK_WRITE;219if (onChange)220cond |= MEMCHECK_WRITE_ONCHANGE;221222g_breakpoints.AddMemCheck(address, address + size, (MemCheckCondition)cond, result);223224if (!condition.empty()) {225BreakPointCond cond;226cond.debug = cpu;227cond.expressionString = condition;228cond.expression = compiledCondition;229g_breakpoints.ChangeMemCheckAddCond(address, address + size, cond);230}231232g_breakpoints.ChangeMemCheckLogFormat(address, address + size, logFormat);233}234else {235// add breakpoint236g_breakpoints.AddBreakPoint(address, false);237238if (!condition.empty()) {239BreakPointCond cond;240cond.debug = cpu;241cond.expressionString = condition;242cond.expression = compiledCondition;243g_breakpoints.ChangeBreakPointAddCond(address, cond);244}245246g_breakpoints.ChangeBreakPoint(address, result);247g_breakpoints.ChangeBreakPointLogFormat(address, logFormat);248}249}250251void BreakpointWindow::loadFromMemcheck(const MemCheck &memcheck) {252memory = true;253254read = (memcheck.cond & MEMCHECK_READ) != 0;255write = (memcheck.cond & MEMCHECK_WRITE) != 0;256onChange = (memcheck.cond & MEMCHECK_WRITE_ONCHANGE) != 0;257258log = (memcheck.result & BREAK_ACTION_LOG) != 0;259enabled = (memcheck.result & BREAK_ACTION_PAUSE) != 0;260261address = memcheck.start;262size = memcheck.end - address;263264if (memcheck.hasCondition) {265condition = memcheck.condition.expressionString;266}267else {268condition.clear();269}270271logFormat = memcheck.logFormat;272}273274void BreakpointWindow::loadFromBreakpoint(const BreakPoint& breakpoint) {275memory = false;276277log = (breakpoint.result & BREAK_ACTION_LOG) != 0;278enabled = (breakpoint.result & BREAK_ACTION_PAUSE) != 0;279address = breakpoint.addr;280size = 1;281282if (breakpoint.hasCond) {283condition = breakpoint.cond.expressionString;284}285else {286condition.clear();287}288289logFormat = breakpoint.logFormat;290}291292void BreakpointWindow::initBreakpoint(u32 _address) {293memory = false;294enabled = true;295address = _address;296size = 1;297condition.clear();298}299300301