void CtrlBreakpointList::handleNotify(LPARAM lParam) { const LPNMHDR header = (LPNMHDR)lParam; if (header->code == NM_DBLCLK) { const LPNMITEMACTIVATE item = (LPNMITEMACTIVATE) lParam; gotoBreakpointAddress(item->iItem); return; } if (header->code == NM_RCLICK) { const LPNMITEMACTIVATE item = (LPNMITEMACTIVATE)lParam; showBreakpointMenu(item->iItem, item->ptAction); return; } if (header->code == LVN_GETDISPINFO) { NMLVDISPINFO *dispInfo = (NMLVDISPINFO *)lParam; bool isMemory; int index = getBreakpointIndex(dispInfo->item.iItem,isMemory); if (index == -1) return; breakpointText = L""; switch (dispInfo->item.iSubItem) { case BPL_TYPE: { if (isMemory) { switch (displayedMemChecks_[index].cond) { case MEMCHECK_READ: breakpointText = L"Read"; break; case MEMCHECK_WRITE: breakpointText = L"Write"; break; case MEMCHECK_READWRITE: breakpointText = L"Read/Write"; break; } } else { breakpointText = L"Execute"; } } break; case BPL_OFFSET: { wchar_t temp[256]; if (isMemory) { wsprintf(temp,L"0x%08X",displayedMemChecks_[index].start); } else { wsprintf(temp,L"0x%08X",displayedBreakPoints_[index].addr); } breakpointText = temp; } break; case BPL_SIZELABEL: { if (isMemory) { auto mc = displayedMemChecks_[index]; wchar_t temp[256]; if (mc.end == 0) wsprintf(temp,L"0x%08X",1); else wsprintf(temp,L"0x%08X",mc.end-mc.start); breakpointText = temp; } else { const char* sym = cpu->findSymbolForAddress(displayedBreakPoints_[index].addr); if (sym != NULL) { breakpointText = ConvertUTF8ToWString(sym); } else { breakpointText = L"-"; } } } break; case BPL_OPCODE: { if (isMemory) { breakpointText = L"-"; } else { char temp[256]; disasm->getOpcodeText(displayedBreakPoints_[index].addr, temp); breakpointText = ConvertUTF8ToWString(temp); } } break; case BPL_CONDITION: { if (isMemory || displayedBreakPoints_[index].hasCond == false) { breakpointText = L"-"; } else { breakpointText = ConvertUTF8ToWString(displayedBreakPoints_[index].cond.expressionString); } } break; case BPL_HITS: { if (isMemory) { wchar_t temp[256]; wsprintf(temp,L"%d",displayedMemChecks_[index].numHits); breakpointText = temp; } else { breakpointText = L"-"; } } break; case BPL_ENABLED: { if (isMemory) { breakpointText = displayedMemChecks_[index].result & MEMCHECK_BREAK ? L"True" : L"False"; } else { breakpointText = displayedBreakPoints_[index].enabled ? L"True" : L"False"; } } break; default: return; } if (breakpointText.empty()) breakpointText = L"Invalid"; dispInfo->item.pszText = &breakpointText[0]; } }
BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { //if (!m_hDlg) return FALSE; switch(message) { case WM_INITDIALOG: { return TRUE; } break; case WM_TIMER: { int iPage = TabCtrl_GetCurSel (GetDlgItem(m_hDlg, IDC_LEFTTABS)); ShowWindow(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), iPage?SW_NORMAL:SW_HIDE); ShowWindow(GetDlgItem(m_hDlg, IDC_REGLIST), iPage?SW_HIDE:SW_NORMAL); } break; case WM_NOTIFY: switch (wParam) { case IDC_LEFTTABS: { HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS); NMHDR* pNotifyMessage = NULL; pNotifyMessage = (LPNMHDR)lParam; if (pNotifyMessage->hwndFrom == tabs) { int iPage = TabCtrl_GetCurSel (tabs); ShowWindow(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), iPage?SW_NORMAL:SW_HIDE); ShowWindow(GetDlgItem(m_hDlg, IDC_REGLIST), iPage?SW_HIDE:SW_NORMAL); } } break; case IDC_BREAKPOINTLIST: handleBreakpointNotify(lParam); break; case IDC_THREADLIST: threadList->handleNotify(lParam); break; } break; case WM_COMMAND: { CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); CtrlRegisterList *reglist = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg,IDC_REGLIST)); switch(LOWORD(wParam)) { case IDC_SHOWVFPU: vfpudlg->Show(true); break; case IDC_FUNCTIONLIST: switch (HIWORD(wParam)) { case CBN_DBLCLK: { HWND lb = GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ListBox_GetCurSel(lb); if (n!=-1) { unsigned int addr = (unsigned int)ListBox_GetItemData(lb,n); ptr->gotoAddr(addr); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } } break; }; break; case IDC_GOTOINT: switch (HIWORD(wParam)) { case LBN_SELCHANGE: { HWND lb =GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ComboBox_GetCurSel(lb); unsigned int addr = (unsigned int)ComboBox_GetItemData(lb,n); if (addr != 0xFFFFFFFF) { ptr->gotoAddr(addr); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } } break; }; break; case IDC_GO: { lastTicks = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); SetDebugMode(false); Core_EnableStepping(false); } break; case IDC_STEP: { if (Core_IsActive()) break; lastTicks = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); Core_DoSingleStep(); Sleep(1); _dbg_update_(); ptr->gotoPC(); UpdateDialog(); vfpudlg->Update(); CtrlMemView::getFrom(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW))->redraw(); threadList->reloadThreads(); updateThreadLabel(false); } break; case IDC_STEPOVER: { if (Core_IsActive()) break; lastTicks = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); const char* dis = cpu->disasm(cpu->GetPC(),4); const char* pos = strstr(dis,"->$"); const char* reg = strstr(dis,"->"); ptr->setDontRedraw(true); u32 breakpointAddress = cpu->GetPC()+cpu->getInstructionSize(0); if (memcmp(dis,"jal\t",4) == 0 || memcmp(dis,"jalr\t",5) == 0) { // it's a function call with a delay slot - skip that too breakpointAddress += cpu->getInstructionSize(0); } else if (memcmp(dis,"j\t",2) == 0 || memcmp(dis,"b\t",2) == 0) { // in case of absolute branches, set the breakpoint at the branch target sscanf(pos+3,"%08x",&breakpointAddress); } else if (memcmp(dis,"jr\t",3) == 0) { // the same for jumps to registers int regNum = -1; for (int i = 0; i < 32; i++) { if (strcasecmp(reg+2,cpu->GetRegName(0,i)) == 0) { regNum = i; break; } } if (regNum == -1) break; breakpointAddress = cpu->GetRegValue(0,regNum); } else if (pos != NULL) { // get branch target sscanf(pos+3,"%08x",&breakpointAddress); CBreakPoints::AddBreakPoint(breakpointAddress,true); // also add a breakpoint after the delay slot breakpointAddress = cpu->GetPC()+2*cpu->getInstructionSize(0); } SetDebugMode(false); CBreakPoints::AddBreakPoint(breakpointAddress,true); _dbg_update_(); Core_EnableStepping(false); Sleep(1); ptr->gotoAddr(breakpointAddress); UpdateDialog(); } break; case IDC_STEPHLE: { if (Core_IsActive()) break; lastTicks = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); hleDebugBreak(); SetDebugMode(false); _dbg_update_(); Core_EnableStepping(false); } break; case IDC_STOP: { ptr->setDontRedraw(false); SetDebugMode(true); Core_EnableStepping(true); _dbg_update_(); Sleep(1); //let cpu catch up ptr->gotoPC(); UpdateDialog(); vfpudlg->Update(); } break; case IDC_SKIP: { cpu->SetPC(cpu->GetPC() + cpu->getInstructionSize(0)); Sleep(1); ptr->gotoPC(); UpdateDialog(); } break; case IDC_MEMCHECK: { bool isRunning = Core_IsActive(); if (isRunning) { SetDebugMode(true); Core_EnableStepping(true); Core_WaitInactive(200); } BreakpointWindow bpw(m_hDlg,cpu); if (bpw.exec()) bpw.addBreakpoint(); if (isRunning) { SetDebugMode(false); Core_EnableStepping(false); } } break; case IDC_UPDATECALLSTACK: { HWND hDlg = m_hDlg; HWND list = GetDlgItem(hDlg,IDC_CALLSTACK); ComboBox_ResetContent(list); u32 pc = currentMIPS->pc; u32 ra = currentMIPS->r[MIPS_REG_RA]; DWORD addr = Memory::ReadUnchecked_U32(pc); int count=1; ComboBox_SetItemData(list,ComboBox_AddString(list,symbolMap.GetDescription(pc)),pc); if (symbolMap.GetDescription(pc) != symbolMap.GetDescription(ra)) { ComboBox_SetItemData(list,ComboBox_AddString(list,symbolMap.GetDescription(ra)),ra); count++; } //walk the stack chain while (addr != 0xFFFFFFFF && addr!=0 && count++<20) { DWORD fun = Memory::ReadUnchecked_U32(addr+4); const char *str = symbolMap.GetDescription(fun); if (strlen(str)==0) str = "(unknown)"; ComboBox_SetItemData(list, ComboBox_AddString(list,str), fun); addr = Memory::ReadUnchecked_U32(addr); } ComboBox_SetCurSel(list,0); } break; case IDC_GOTOPC: { ptr->gotoPC(); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); UpdateDialog(); } break; case IDC_GOTOLR: { ptr->gotoAddr(cpu->GetLR()); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } break; case IDC_BACKWARDLINKS: { HWND box = GetDlgItem(m_hDlg, IDC_FUNCTIONLIST); int funcnum = symbolMap.GetSymbolNum(ListBox_GetItemData(box,ListBox_GetCurSel(box))); if (funcnum!=-1) symbolMap.FillListBoxBLinks(box,funcnum); break; } case IDC_ALLFUNCTIONS: { symbolMap.FillSymbolListBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST),ST_FUNCTION); break; } default: return FALSE; } return TRUE; } case WM_DEB_MAPLOADED: NotifyMapLoaded(); break; case WM_DEB_RUNTOWPARAM: { lastTicks = CoreTiming::GetTicks(); CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); ptr->setDontRedraw(true); SetDebugMode(false); CBreakPoints::AddBreakPoint(wParam,true); _dbg_update_(); Core_EnableStepping(false); break; } case WM_DEB_GOTOWPARAM: { CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); ptr->gotoAddr(wParam); SetFocus(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); break; } case WM_DEB_GOTOBREAKPOINT: gotoBreakpointAddress(wParam); break; case WM_DEB_REMOVEBREAKPOINT: removeBreakpoint(wParam); break; case WM_DEB_GOTOADDRESSEDIT: { char szBuffer[256]; CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); GetWindowText(GetDlgItem(m_hDlg,IDC_ADDRESS),szBuffer,256); u32 addr; if (parseExpression(szBuffer,cpu,addr) == false) { displayExpressionError(GetDlgItem(m_hDlg,IDC_ADDRESS)); } else { ptr->gotoAddr(addr); SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); } UpdateDialog(); } break; case WM_DEB_SETDEBUGLPARAM: SetDebugMode(lParam != 0); return TRUE; case WM_DEB_UPDATE: Update(); return TRUE; case WM_DEB_TABPRESSED: { HWND bp = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST); HWND mem = GetDlgItem(m_hDlg, IDC_DEBUGMEMVIEW); HWND threads = GetDlgItem(m_hDlg, IDC_THREADLIST); if (IsWindowVisible(bp)) { ShowWindow(bp,SW_HIDE); ShowWindow(mem,SW_HIDE); ShowWindow(threads,SW_NORMAL); SetFocus(threads); } else if (IsWindowVisible(threads)) { ShowWindow(bp,SW_HIDE); ShowWindow(mem,SW_NORMAL); ShowWindow(threads,SW_HIDE); SetFocus(mem); } else { ShowWindow(bp,SW_NORMAL); ShowWindow(mem,SW_HIDE); ShowWindow(threads,SW_HIDE); SetFocus(bp); } } break; case WM_SIZE: { UpdateSize(LOWORD(lParam), HIWORD(lParam)); SavePosition(); return TRUE; } case WM_MOVE: SavePosition(); break; case WM_GETMINMAXINFO: { MINMAXINFO *m = (MINMAXINFO *)lParam; // Reduce the minimum size slightly, so they can size it however they like. m->ptMinTrackSize.x = defaultRect.right - defaultRect.left - 100; //m->ptMaxTrackSize.x = m->ptMinTrackSize.x; m->ptMinTrackSize.y = defaultRect.bottom - defaultRect.top - 200; } return TRUE; case WM_CLOSE: Show(false); return TRUE; } return FALSE; }
void CtrlBreakpointList::OnDoubleClick(int itemIndex, int column) { gotoBreakpointAddress(itemIndex); }
void CDisasm::handleBreakpointNotify(LPARAM lParam) { if (((LPNMHDR)lParam)->code == NM_DBLCLK) { LPNMITEMACTIVATE item = (LPNMITEMACTIVATE) lParam; gotoBreakpointAddress(item->iItem); return; } if (((LPNMHDR)lParam)->code == LVN_GETDISPINFO) { NMLVDISPINFO* dispInfo = (NMLVDISPINFO*)lParam; bool isMemory; int index = getBreakpointIndex(dispInfo->item.iItem,isMemory); if (index == -1) return; breakpointText[0] = 0; switch (dispInfo->item.iSubItem) { case BPL_TYPE: { if (isMemory) { switch (displayedMemChecks_[index].cond) { case MEMCHECK_READ: strcpy(breakpointText, "Read"); break; case MEMCHECK_WRITE: strcpy(breakpointText, "Write"); break; case MEMCHECK_READWRITE: strcpy(breakpointText, "Read/Write"); break; } } else { strcpy(breakpointText,"Execute"); } } break; case BPL_OFFSET: { if (isMemory) { sprintf(breakpointText,"0x%08X",displayedMemChecks_[index].start); } else { sprintf(breakpointText,"0x%08X",displayedBreakPoints_[index].addr); } } break; case BPL_SIZELABEL: { if (isMemory) { auto mc = displayedMemChecks_[index]; if (mc.end == 0) sprintf(breakpointText,"0x%08X",1); else sprintf(breakpointText,"0x%08X",mc.end-mc.start); } else { const char* sym = cpu->findSymbolForAddress(displayedBreakPoints_[index].addr); if (sym != NULL) { strcpy(breakpointText,sym); } else { strcpy(breakpointText,"-"); } } } break; case BPL_OPCODE: { if (isMemory) { strcpy(breakpointText,"-"); } else { CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); ptr->getOpcodeText(displayedBreakPoints_[index].addr,breakpointText); } } break; case BPL_HITS: { if (isMemory) { sprintf(breakpointText,"%d",displayedMemChecks_[index].numHits); } else { strcpy(breakpointText,"-"); } } break; case BPL_ENABLED: { if (isMemory) { strcpy(breakpointText,displayedMemChecks_[index].result & MEMCHECK_BREAK ? "True" : "False"); } else { strcpy(breakpointText,displayedBreakPoints_[index].enabled ? "True" : "False"); } } break; default: return; } if (breakpointText[0] == 0) strcat(breakpointText,"Invalid"); dispInfo->item.pszText = breakpointText; } }