diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index 7966cf5c5f..c0b592f8eb 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -138,10 +138,17 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di threadList->setDialogItem(GetDlgItem(m_hDlg,IDC_THREADLIST)); threadList->reloadThreads(); + stackTraceView = new CtrlStackTraceView(); + stackTraceView->setCpu(cpu); + stackTraceView->setDisasm(ptr); + stackTraceView->setDialogItem(GetDlgItem(m_hDlg,IDC_STACKFRAMES)); + stackTraceView->loadStackTrace(); + // init memory/breakpoint "tab" ShowWindow(GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST), SW_HIDE); ShowWindow(GetDlgItem(m_hDlg, IDC_DEBUGMEMVIEW), SW_NORMAL); ShowWindow(GetDlgItem(m_hDlg, IDC_THREADLIST), SW_HIDE); + ShowWindow(GetDlgItem(m_hDlg, IDC_STACKFRAMES), SW_HIDE); // init status bar statusBarWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", m_hDlg, IDC_DISASMSTATUSBAR); @@ -206,6 +213,9 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) case IDC_THREADLIST: threadList->handleNotify(lParam); break; + case IDC_STACKFRAMES: + stackTraceView->handleNotify(lParam); + break; } break; case WM_COMMAND: @@ -283,6 +293,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) CtrlMemView::getFrom(GetDlgItem(m_hDlg,IDC_DEBUGMEMVIEW))->redraw(); threadList->reloadThreads(); + stackTraceView->loadStackTrace(); updateThreadLabel(false); } break; @@ -504,23 +515,34 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) HWND bp = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST); HWND mem = GetDlgItem(m_hDlg, IDC_DEBUGMEMVIEW); HWND threads = GetDlgItem(m_hDlg, IDC_THREADLIST); - + HWND stackFrames = GetDlgItem(m_hDlg, IDC_STACKFRAMES); + if (IsWindowVisible(bp)) { - ShowWindow(bp,SW_HIDE); ShowWindow(mem,SW_HIDE); + ShowWindow(bp,SW_HIDE); ShowWindow(threads,SW_NORMAL); + ShowWindow(stackFrames,SW_HIDE); SetFocus(threads); } else if (IsWindowVisible(threads)) { + ShowWindow(mem,SW_HIDE); ShowWindow(bp,SW_HIDE); - ShowWindow(mem,SW_NORMAL); ShowWindow(threads,SW_HIDE); + ShowWindow(stackFrames,SW_NORMAL); + SetFocus(stackFrames); + } else if (IsWindowVisible(stackFrames)) + { + ShowWindow(mem,SW_NORMAL); + ShowWindow(bp,SW_HIDE); + ShowWindow(threads,SW_HIDE); + ShowWindow(stackFrames,SW_HIDE); SetFocus(mem); } else { - ShowWindow(bp,SW_NORMAL); ShowWindow(mem,SW_HIDE); + ShowWindow(bp,SW_NORMAL); ShowWindow(threads,SW_HIDE); + ShowWindow(stackFrames,SW_HIDE); SetFocus(bp); } } @@ -590,6 +612,7 @@ void CDisasm::UpdateSize(WORD width, WORD height) HWND breakpointList = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST); HWND memView = GetDlgItem(m_hDlg, IDC_DEBUGMEMVIEW); HWND threads = GetDlgItem(m_hDlg, IDC_THREADLIST); + HWND stackFrame = GetDlgItem(m_hDlg,IDC_STACKFRAMES); if (g_Config.bDisplayStatusBar) { @@ -617,6 +640,7 @@ void CDisasm::UpdateSize(WORD width, WORD height) MoveWindow(breakpointList,8,breakpointTop,width-16,breakpointHeight,TRUE); MoveWindow(memView,8,breakpointTop,width-16,breakpointHeight,TRUE); MoveWindow(threads,8,breakpointTop,width-16,breakpointHeight,TRUE); + MoveWindow(stackFrame,8,breakpointTop,width-16,breakpointHeight,TRUE); GetWindowRect(GetDlgItem(m_hDlg, IDC_REGLIST),®Rect); GetWindowRect(GetDlgItem(m_hDlg, IDC_DISASMVIEW),&disRect); @@ -646,6 +670,7 @@ void CDisasm::SetDebugMode(bool _bDebug) CBreakPoints::ClearTemporaryBreakPoints(); breakpointList->update(); threadList->reloadThreads(); + stackTraceView->loadStackTrace(); updateThreadLabel(false); EnableWindow( GetDlgItem(hDlg, IDC_GO), TRUE); diff --git a/Windows/Debugger/Debugger_Disasm.h b/Windows/Debugger/Debugger_Disasm.h index e58ccba6d0..db4dd8f5eb 100644 --- a/Windows/Debugger/Debugger_Disasm.h +++ b/Windows/Debugger/Debugger_Disasm.h @@ -30,6 +30,7 @@ private: HWND statusBarWnd; CtrlBreakpointList* breakpointList; CtrlThreadList* threadList; + CtrlStackTraceView* stackTraceView; std::vector displayedBreakPoints_; std::vector displayedMemChecks_; diff --git a/Windows/Debugger/Debugger_Lists.cpp b/Windows/Debugger/Debugger_Lists.cpp index c96f7b19e1..51427d2c31 100644 --- a/Windows/Debugger/Debugger_Lists.cpp +++ b/Windows/Debugger/Debugger_Lists.cpp @@ -7,6 +7,7 @@ #include "Windows/resource.h" #include "Windows/main.h" #include "BreakpointWindow.h" +#include "../../Core/HLE/sceKernelThread.h" typedef struct { @@ -16,6 +17,7 @@ typedef struct enum { TL_NAME, TL_PROGRAMCOUNTER, TL_ENTRYPOINT, TL_PRIORITY, TL_STATE, TL_WAITTYPE, TL_COLUMNCOUNT }; enum { BPL_TYPE, BPL_OFFSET, BPL_SIZELABEL, BPL_OPCODE, BPL_CONDITION, BPL_HITS, BPL_ENABLED, BPL_COLUMNCOUNT }; +enum { SF_ENTRY, SF_ENTRYNAME, SF_CURPC, SF_CUROPCODE, SF_CURSP, SF_FRAMESIZE, SF_COLUMNCOUNT }; ListViewColumn threadColumns[TL_COLUMNCOUNT] = { { "Name", 0.20f }, @@ -36,6 +38,15 @@ ListViewColumn breakpointColumns[BPL_COLUMNCOUNT] = { { "Enabled", 0.08f } }; +ListViewColumn stackTraceColumns[SF_COLUMNCOUNT] = { + { "Entry", 0.12f }, + { "Name", 0.24f }, + { "PC", 0.12f }, + { "Opcode", 0.28f }, + { "SP", 0.12f }, + { "Frame Size", 0.12f } +}; + const int POPUP_SUBMENU_ID_BREAKPOINTLIST = 5; const int POPUP_SUBMENU_ID_THREADLIST = 6; const int POPUP_SUBMENU_ID_NEWBREAKPOINT = 7; @@ -710,3 +721,163 @@ void CtrlBreakpointList::showBreakpointMenu(int itemIndex, const POINT &pt) } } } + +// +// CtrlStackTraceView +// + +void CtrlStackTraceView::setDialogItem(HWND hwnd) +{ + wnd = hwnd; + + SetWindowLongPtr(wnd,GWLP_USERDATA,(LONG_PTR)this); + oldProc = (WNDPROC) SetWindowLongPtr(wnd,GWLP_WNDPROC,(LONG_PTR)wndProc); + + SendMessage(wnd, 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; + + RECT rect; + GetWindowRect(wnd,&rect); + + int totalListSize = (rect.right-rect.left-20); + for (int i = 0; i < SF_COLUMNCOUNT; i++) + { + lvc.cx = stackTraceColumns[i].size * totalListSize; + lvc.pszText = stackTraceColumns[i].name; + ListView_InsertColumn(wnd, i, &lvc); + } +} + +LRESULT CALLBACK CtrlStackTraceView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + CtrlStackTraceView* sv = (CtrlStackTraceView*) GetWindowLongPtr(hwnd,GWLP_USERDATA); + + switch (msg) + { + case WM_SIZE: + { + int width = LOWORD(lParam); + RECT rect; + GetWindowRect(hwnd,&rect); + + int totalListSize = (rect.right-rect.left-20); + for (int i = 0; i < SF_COLUMNCOUNT; i++) + { + ListView_SetColumnWidth(hwnd,i,stackTraceColumns[i].size * totalListSize); + } + } + break; + case WM_KEYDOWN: + if (wParam == VK_TAB) + { + SendMessage(GetParent(hwnd),WM_DEB_TABPRESSED,0,0); + return 0; + } + break; + case WM_GETDLGCODE: + if (lParam && ((MSG*)lParam)->message == WM_KEYDOWN) + { + if (wParam == VK_TAB) return DLGC_WANTMESSAGE; + } + break; + } + return (LRESULT)CallWindowProc((WNDPROC)sv->oldProc,hwnd,msg,wParam,lParam); +} + +void CtrlStackTraceView::handleNotify(LPARAM lParam) +{ + LPNMHDR mhdr = (LPNMHDR) lParam; + + if (mhdr->code == NM_DBLCLK) + { + LPNMITEMACTIVATE item = (LPNMITEMACTIVATE) lParam; + SendMessage(GetParent(wnd),WM_DEB_GOTOWPARAM,frames[item->iItem].pc,0); + return; + } + + if (mhdr->code == LVN_GETDISPINFO) + { + NMLVDISPINFO* dispInfo = (NMLVDISPINFO*)lParam; + int index = dispInfo->item.iItem; + + stringBuffer[0] = 0; + switch (dispInfo->item.iSubItem) + { + case SF_ENTRY: + sprintf(stringBuffer,"%08X",frames[index].entry); + break; + case SF_ENTRYNAME: + { + const char* sym = cpu->findSymbolForAddress(frames[index].entry); + if (sym != NULL) + { + strcpy(stringBuffer,sym); + } else { + strcpy(stringBuffer,"-"); + } + } + break; + case SF_CURPC: + sprintf(stringBuffer,"%08X",frames[index].pc); + break; + case SF_CUROPCODE: + disasm->getOpcodeText(frames[index].pc,stringBuffer); + break; + case SF_CURSP: + sprintf(stringBuffer,"%08X",frames[index].sp); + break; + case SF_FRAMESIZE: + sprintf(stringBuffer,"%08X",frames[index].stackSize); + break; + } + + if (stringBuffer[0] == 0) strcat(stringBuffer,"Invalid"); + dispInfo->item.pszText = stringBuffer; + } +} + +void CtrlStackTraceView::loadStackTrace() +{ + auto threads = GetThreadsInfo(); + + u32 entry, stackTop; + for (size_t i = 0; i < threads.size(); i++) + { + if (threads[i].isCurrent) + { + entry = threads[i].entrypoint; + stackTop = threads[i].initialStack; + break; + } + } + + frames = MIPSStackWalk::Walk(cpu->GetPC(),cpu->GetRegValue(0,31),cpu->GetRegValue(0,29),entry,stackTop); + + int items = ListView_GetItemCount(wnd); + while (items < (int)frames.size()) + { + 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(wnd, &lvI); + items++; + } + + while (items > (int)frames.size()) + { + ListView_DeleteItem(wnd,--items); + } + + InvalidateRect(wnd,NULL,true); + UpdateWindow(wnd); +} diff --git a/Windows/Debugger/Debugger_Lists.h b/Windows/Debugger/Debugger_Lists.h index cac7d0ea30..9431e6720b 100644 --- a/Windows/Debugger/Debugger_Lists.h +++ b/Windows/Debugger/Debugger_Lists.h @@ -3,6 +3,7 @@ #include "../../Core/Debugger/DebugInterface.h" #include "../../Core/HLE/sceKernelThread.h" #include "../../Core/Debugger/Breakpoints.h" +#include "../../Core/MIPS/MIPSStackWalk.h" class CtrlThreadList { @@ -53,4 +54,28 @@ public: void handleNotify(LPARAM lParam); void showMenu(int itemIndex, const POINT &pt); static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +}; + +class CtrlStackTraceView +{ + HWND wnd; + WNDPROC oldProc; + std::vector frames; + DebugInterface* cpu; + CtrlDisAsmView* disasm; + char stringBuffer[256]; + +public: + void setCpu(DebugInterface* cpu) + { + this->cpu = cpu; + }; + void setDisasm(CtrlDisAsmView* disasm) + { + this->disasm = disasm; + }; + void setDialogItem(HWND hwnd); + void loadStackTrace(); + void handleNotify(LPARAM lParam); + static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); }; \ No newline at end of file diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index ee58d15357..c287ade3ef 100644 Binary files a/Windows/ppsspp.rc and b/Windows/ppsspp.rc differ diff --git a/Windows/resource.h b/Windows/resource.h index fc180d7bb9..baede30ca5 100644 Binary files a/Windows/resource.h and b/Windows/resource.h differ