From d4214af7105af8ad371b757c16e450e10e139cb5 Mon Sep 17 00:00:00 2001 From: Kingcom Date: Thu, 27 Jun 2013 21:07:49 +0200 Subject: [PATCH] Breakpoint list at the bottom of the disassembly window --- Core/Debugger/Breakpoints.cpp | 5 + Core/Debugger/Breakpoints.h | 1 + Windows/Debugger/CtrlDisAsmView.cpp | 11 +- Windows/Debugger/CtrlDisAsmView.h | 3 +- Windows/Debugger/Debugger_Disasm.cpp | 357 ++++++++++++++++++++++-- Windows/Debugger/Debugger_Disasm.h | 16 +- Windows/Debugger/Debugger_MemoryDlg.cpp | 1 + Windows/debugger.txt | 4 + Windows/ppsspp.rc | Bin 40054 -> 40342 bytes Windows/resource.h | Bin 23168 -> 23260 bytes 10 files changed, 365 insertions(+), 33 deletions(-) diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 761e8c0cf1..7f83026abe 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -172,6 +172,11 @@ int CBreakPoints::GetNumBreakpoints() return (int)m_iBreakPoints.size(); } +BreakPoint CBreakPoints::GetBreakpoint(int i) +{ + return m_iBreakPoints[i]; +} + int CBreakPoints::GetBreakpointAddress(int i) { return m_iBreakPoints[i].iAddress; diff --git a/Core/Debugger/Breakpoints.h b/Core/Debugger/Breakpoints.h index 1c0512f1be..4e0b4ce8bf 100644 --- a/Core/Debugger/Breakpoints.h +++ b/Core/Debugger/Breakpoints.h @@ -87,6 +87,7 @@ public: static void InvalidateJit(); static int GetNumBreakpoints(); + static BreakPoint GetBreakpoint(int i); static int GetBreakpointAddress(int i); }; diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index f8f955d96c..1c869d63a7 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -357,7 +357,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam) if (debugger->isBreakpoint(address)) { textColor = 0x0000FF; - DrawIconEx(hdc,2,rowY1,breakPoint,32,32,0,0,DI_NORMAL); + DrawIconEx(hdc,2,rowY1+1,breakPoint,32,32,0,0,DI_NORMAL); } SetTextColor(hdc,textColor); @@ -892,4 +892,13 @@ void CtrlDisAsmView::disassembleToFile() fclose(output); MessageBox(wnd,"Finished!","Done",MB_OK); +} + +void CtrlDisAsmView::getOpcodeText(u32 address, char* dest) +{ + char addressText[64],opcode[64],arguments[256]; + const char *dis = debugger->disasm(address, instructionSize); + parseDisasm(dis,opcode,arguments); + + sprintf(dest,"%s %s",opcode,arguments); } \ No newline at end of file diff --git a/Windows/Debugger/CtrlDisAsmView.h b/Windows/Debugger/CtrlDisAsmView.h index 03cb2e1b37..eab8143532 100644 --- a/Windows/Debugger/CtrlDisAsmView.h +++ b/Windows/Debugger/CtrlDisAsmView.h @@ -83,7 +83,8 @@ public: void onMouseUp(WPARAM wParam, LPARAM lParam, int button); void onMouseMove(WPARAM wParam, LPARAM lParam, int button); void redraw(); - + + void getOpcodeText(u32 address, char* dest); int yToAddress(int y); void setDontRedraw(bool b) { dontRedraw = b; }; diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index 646b1050c5..f152e60418 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -29,6 +29,45 @@ #include #include +char* breakpointColumns[] = { + "Type", "Offset", "Size/Label", "Opcode", "Hits", "Enabled" +}; + +float breakpointColumnSizes[] = { + 0.12f, 0.2f, 0.2f, 0.3f, 0.1f, 0.08f +}; + +enum { BPL_TYPE, BPL_OFFSET, BPL_SIZELABEL, BPL_OPCODE, BPL_HITS, BPL_ENABLED, BPL_COLUMNCOUNT }; + +static FAR WNDPROC DefBreakpointListProc; + +static LRESULT CALLBACK BreakpointListProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_KEYDOWN: + if(wParam == VK_RETURN) + { + int index = ListView_GetSelectionMark(hDlg); + SendMessage(GetParent(hDlg),WM_USER+4,index,0); + return 0; + } else if (wParam == VK_DELETE) + { + int index = ListView_GetSelectionMark(hDlg); + SendMessage(GetParent(hDlg),WM_USER+5,index,0); + return 0; + } + default: + return (LRESULT)CallWindowProc((WNDPROC)DefBreakpointListProc,hDlg,message,wParam,lParam); + }; + + return 0; +} + + + + + CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Dialog((LPCSTR)IDD_DISASM, _hInstance, _hParent) { cpu = _cpu; @@ -62,6 +101,15 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di GetWindowRect(GetDlgItem(m_hDlg, IDC_REGLIST),®Rect); GetWindowRect(GetDlgItem(m_hDlg, IDC_DISASMVIEW),&disRect); + GetWindowRect(GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST),&breakpointRect); + + int minWidth = max((regRect.right-regRect.left)+(disRect.right-disRect.left)+24, + (breakpointRect.right-breakpointRect.left)+16); + if (w < minWidth) w = minWidth; + + int minHeight = max((disRect.bottom-disRect.top)+(breakpointRect.bottom-breakpointRect.top)+37, + (regRect.bottom-regRect.top)+(breakpointRect.bottom-breakpointRect.top)+150); + if (h < minHeight) h = minHeight; HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS); @@ -79,23 +127,35 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di ShowWindow(GetDlgItem(m_hDlg, IDC_REGLIST), SW_NORMAL); ShowWindow(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), SW_HIDE); SetTimer(m_hDlg,1,1000,0); - /* - DWORD intAddress[14] = - {0x100, 0x200,0x300,0x400,0x500,0x600,0x700,0x800,0x900,0xc00,0xd00,0xf00,0x1300,0x1700}; - char *intName[14] = - {"100 Reset","200 Mcheck", "300 DSI","400 ISI","500 External", - "600 Align","700 Program","800 FPU N/A","900 DEC","C00 SC", - "D00 Trace","F00 Perf","1300 Breakpt","1700 Thermal"};*/ - // - // --- activate debug mode --- - // + + // subclass the breakpoint list + HWND breakpointHwnd = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST); + DefBreakpointListProc = (WNDPROC)GetWindowLongPtr(breakpointHwnd,GWLP_WNDPROC); + SetWindowLongPtr(breakpointHwnd,GWLP_WNDPROC,(LONG_PTR)BreakpointListProc); + + // create columns for the breakpoint list + SendMessage(breakpointHwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); + + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.iSubItem = 0; + lvc.fmt = LVCFMT_LEFT; + + int totalListSize = (breakpointRect.right-breakpointRect.left-20); + for (int i = 0; i < BPL_COLUMNCOUNT; i++) + { + lvc.cx = breakpointColumnSizes[i] * totalListSize; + lvc.pszText = breakpointColumns[i]; + ListView_InsertColumn(breakpointHwnd, i, &lvc); + } + // Actually resize the window to the proper size (after the above setup.) if (w != -1 && h != -1) { + // this will also call UpdateSize SetWindowPos(m_hDlg, 0, x, y, w, h, 0); - UpdateSize(w, h); } SetDebugMode(true); @@ -105,6 +165,225 @@ CDisasm::~CDisasm() { } +int getTotalBreakpointCount() +{ + int count = CBreakPoints::MemChecks.size(); + for (int i = 0; i < CBreakPoints::GetNumBreakpoints(); i++) + { + if (!CBreakPoints::GetBreakpoint(i).bTemporary) count++; + } + + return count; +} + +void CDisasm::updateBreakpointList() +{ + HWND breakpointHwnd = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST); + int breakpointCount = getTotalBreakpointCount(); + int items = ListView_GetItemCount(breakpointHwnd); + + while (items < breakpointCount) + { + LVITEM lvI; + lvI.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message. + lvI.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE; + lvI.stateMask = 0; + lvI.iSubItem = 0; + lvI.state = 0; + lvI.iItem = items; + lvI.iImage = items; + + ListView_InsertItem(breakpointHwnd, &lvI); + items++; + } + + while (items > breakpointCount) + { + ListView_DeleteItem(breakpointHwnd,--items); + } + + InvalidateRect(breakpointHwnd,NULL,true); + UpdateWindow(breakpointHwnd); +} + +int getBreakpointIndex(int itemIndex, bool& isMemory) +{ + // memory breakpoints first + if (itemIndex < CBreakPoints::MemChecks.size()) + { + isMemory = true; + return itemIndex; + } + + itemIndex -= CBreakPoints::MemChecks.size(); + + int i = 0; + while (i < CBreakPoints::GetNumBreakpoints()) + { + if (CBreakPoints::GetBreakpoint(i).bTemporary) + { + i++; + continue; + } + + // the index is 0 when there are no more breakpoints to skip + if (itemIndex == 0) + { + isMemory = false; + return i; + } + + i++; + itemIndex--; + } + + return -1; +} + +void CDisasm::removeBreakpoint(int itemIndex) +{ + bool isMemory; + int index = getBreakpointIndex(itemIndex,isMemory); + if (index == -1) return; + + if (isMemory) + { + CBreakPoints::MemChecks.erase(CBreakPoints::MemChecks.begin()+index); + CBreakPoints::InvalidateJit(); + updateBreakpointList(); + } else { + u32 address = CBreakPoints::GetBreakpointAddress(index); + CBreakPoints::RemoveBreakPoint(address); + } +} + +void CDisasm::gotoBreakpointAddress(int itemIndex) +{ + bool isMemory; + int index = getBreakpointIndex(itemIndex,isMemory); + if (index == -1) return; + + if (isMemory) + { + u32 address = CBreakPoints::MemChecks[index].iStartAddress; + + for (int i=0; iGoto(address); + } else { + u32 address = CBreakPoints::GetBreakpointAddress(index); + Goto(address); + SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW)); + } +} + +static char breakpointText[256]; + +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; + std::vector& mem = CBreakPoints::MemChecks; + + 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) + { + if (mem[index].bOnRead) + { + strcpy(breakpointText,"Read"); + if (mem[index].bOnWrite) strcat(breakpointText,"/"); + } + if (mem[index].bOnWrite) strcat(breakpointText,"Write"); + } else { + strcpy(breakpointText,"Execute"); + } + } + break; + case BPL_OFFSET: + { + if (isMemory) + { + sprintf(breakpointText,"0x%08X",mem[index].iStartAddress); + } else { + sprintf(breakpointText,"0x%08X",CBreakPoints::GetBreakpointAddress(index)); + } + } + break; + case BPL_SIZELABEL: + { + if (isMemory) + { + if (mem[index].bRange == false) sprintf(breakpointText,"0x%08X",1); + else sprintf(breakpointText,"0x%08X",mem[index].iEndAddress-mem[index].iStartAddress); + } else { + const char* sym = cpu->findSymbolForAddress(CBreakPoints::GetBreakpointAddress(index)); + if (sym != NULL) + { + if (memcmp(sym,"z_",2) == 0) sym += 2; + if (memcmp(sym,"zz_",3) == 0) sym += 3; + 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(CBreakPoints::GetBreakpointAddress(index),breakpointText); + } + } + break; + case BPL_HITS: + { + if (isMemory) + { + sprintf(breakpointText,"0x%08X",mem[index].numHits); + } else { + strcpy(breakpointText,"-"); + } + } + break; + case BPL_ENABLED: + { + if (isMemory) + { + strcpy(breakpointText,mem[index].bBreak == true ? "True" : "False"); + } else { + strcpy(breakpointText,CBreakPoints::GetBreakpoint(index).bOn ? "True" : "False"); + } + } + break; + default: + return; + } + + if (breakpointText[0] == 0) strcat(breakpointText,"Invalid"); + dispInfo->item.pszText = breakpointText; + } +} + BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { //if (!m_hDlg) return FALSE; @@ -125,19 +404,26 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) break; case WM_NOTIFY: + switch (wParam) { - HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS); - NMHDR* pNotifyMessage = NULL; - pNotifyMessage = (LPNMHDR)lParam; - if (pNotifyMessage->hwndFrom == tabs) + case IDC_LEFTTABS: { - 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); + 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; } - + break; case WM_COMMAND: { CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); @@ -299,6 +585,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) check.bRange = false; CBreakPoints::MemChecks.push_back(check); CBreakPoints::InvalidateJit(); + updateBreakpointList(); } if (isRunning) @@ -353,13 +640,15 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) case IDC_GOTOPC: { - ptr->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; @@ -396,6 +685,12 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) Core_EnableStepping(false); break; } + case WM_USER+4: + gotoBreakpointAddress(wParam); + break; + case WM_USER+5: + removeBreakpoint(wParam); + break; case WM_SIZE: { UpdateSize(LOWORD(lParam), HIWORD(lParam)); @@ -427,13 +722,20 @@ void CDisasm::UpdateSize(WORD width, WORD height) HWND disasm = GetDlgItem(m_hDlg, IDC_DISASMVIEW); HWND funclist = GetDlgItem(m_hDlg, IDC_FUNCTIONLIST); HWND regList = GetDlgItem(m_hDlg, IDC_REGLIST); - int wf = regRect.right - regRect.left; - int top = 138; - MoveWindow(regList, 8, top, wf, height - top - 8, TRUE); - MoveWindow(funclist, 8, top, wf, height - top - 8, TRUE); - int w = width - wf; - top = 25; - MoveWindow(disasm, wf + 15,top, w - 20, height - top - 8, TRUE); + HWND breakpointList = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST); + + int breakpointHeight = breakpointRect.bottom-breakpointRect.top; + int breakpointTop = height-breakpointHeight-8; + int regWidth = regRect.right - regRect.left; + int regTop = 138; + int disasmWidth = width-regWidth; + int disasmTop = 25; + + MoveWindow(regList, 8, regTop, regWidth, height-regTop-breakpointHeight-12, TRUE); + MoveWindow(funclist, 8, regTop, regWidth, height-regTop-breakpointHeight-12, TRUE); + MoveWindow(disasm,regWidth+15,disasmTop,disasmWidth-20,height-disasmTop-breakpointHeight-12,TRUE); + MoveWindow(breakpointList,8,breakpointTop,width-16,breakpointHeight,TRUE); + } void CDisasm::SavePosition() @@ -456,6 +758,7 @@ void CDisasm::SetDebugMode(bool _bDebug) if (_bDebug) { CBreakPoints::ClearTemporaryBreakPoints(); + updateBreakpointList(); EnableWindow( GetDlgItem(hDlg, IDC_GO), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STEP), TRUE); diff --git a/Windows/Debugger/Debugger_Disasm.h b/Windows/Debugger/Debugger_Disasm.h index ee6c6a1e28..66f8a54bd9 100644 --- a/Windows/Debugger/Debugger_Disasm.h +++ b/Windows/Debugger/Debugger_Disasm.h @@ -18,13 +18,17 @@ private: RECT minRect; RECT regRect; RECT disRect; - + RECT breakpointRect; + DebugInterface *cpu; BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam); void UpdateSize(WORD width, WORD height); void SavePosition(); - + void updateBreakpointList(); + void handleBreakpointNotify(LPARAM lParam); + void gotoBreakpointAddress(int itemIndex); + void removeBreakpoint(int itemIndex); public: int index; //helper @@ -33,8 +37,12 @@ public: // // --- tools --- // - // Update Dialog - virtual void Update() { UpdateDialog(true); }; + + virtual void Update() + { + UpdateDialog(true); + updateBreakpointList(); + }; void UpdateDialog(bool _bComplete = false); // SetDebugMode void SetDebugMode(bool _bDebug); diff --git a/Windows/Debugger/Debugger_MemoryDlg.cpp b/Windows/Debugger/Debugger_MemoryDlg.cpp index b5089589ee..60b59baa33 100644 --- a/Windows/Debugger/Debugger_MemoryDlg.cpp +++ b/Windows/Debugger/Debugger_MemoryDlg.cpp @@ -181,6 +181,7 @@ void CMemoryDlg::Goto(u32 addr) Show(true); CtrlMemView *mv = CtrlMemView::getFrom(GetDlgItem(CMemoryDlg::m_hDlg,IDC_MEMVIEW)); mv->gotoAddr(addr); + SetFocus(GetDlgItem(CMemoryDlg::m_hDlg,IDC_MEMVIEW)); } diff --git a/Windows/debugger.txt b/Windows/debugger.txt index eb5c0dcb38..2bda0fe5d2 100644 --- a/Windows/debugger.txt +++ b/Windows/debugger.txt @@ -17,6 +17,10 @@ Key bindings: -Ctrl+C will continue the previous search -Ctrl+X will disassemble to a file you specify. First you enter the size (in bytes, hexadecimal) of the code to be disassembled, then you select a file name. It will start at the cursor +All breakpoints are listed in the table at the bottom of the disassembly view. Doube clicking an execute breakpoint will move the disassembly view to that position, double clicking a memory breakpoint will open the memory viewer and move it to the start of the breakpoint range. Pressing delete will remove the selected breakpoint. +If there is a symbol defined for the position of an execute breakpoint, that will also be displayed. + + ########### Memory View ########### diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index e0ef0a5c5c850a690e15e1e2211a5b82c709d629..4e1675bce067356aebb65000a5997d4a80a97c14 100644 GIT binary patch delta 222 zcmZ9GKMMh20EeHhOlIqK+2mb#Ic!dyKY6?3-iu5o!<9ju5-H!na`8FTEy}0i3)sv$ z%3%IIzo+MQHO@EVVq3Wyl4|m7SJI`m%O{VLedrM2;xJ@{&j61Q#Q;r+ponHmj3Odt z&4h>rn@mFyfntJYj`R8S@KCsP39;B?{dP?spD7v_^`WOY%+Tf^n8jov!B>&o$A#qB VFbe{Sq=}$T1&N@AOz-8>>J2LgD>?uG delta 29 lcmbQXo9WvQrVVBati}w+3`UdroeVeUC{%H8X49Qe005PX31$EQ diff --git a/Windows/resource.h b/Windows/resource.h index 8f89f7bf44e487ab256c1ca4435deb715594d69e..465aad2e8b2052c2c71f44cf5e2e0141b9194f4a 100644 GIT binary patch delta 35 rcmZqJ%6MlhOUX delta 21 dcmcb!m9b$fA7EnHT%eI-1ORJz2)O_N