Merge pull request #1367 from pj64d-merge/master

Debugger: Add stack trace window
This commit is contained in:
zilmar 2017-08-30 18:10:23 +10:00 committed by GitHub
commit f5acfd1184
11 changed files with 199 additions and 85 deletions

View File

@ -305,8 +305,6 @@ void CInterpreterCPU::ExecuteCPU()
continue;
}
g_Debugger->CPUStep();
/* if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER < 0x80380000)
{
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER));
@ -317,6 +315,8 @@ void CInterpreterCPU::ExecuteCPU()
m_R4300i_Opcode[Opcode.op]();
NextTimer -= CountPerOp;
g_Debugger->CPUStep();
PROGRAM_COUNTER += 4;
switch (R4300iOp::m_NextInstruction)
{

View File

@ -136,6 +136,7 @@ LRESULT CDebugCommandsView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARA
LRESULT CDebugCommandsView::OnDestroy(void)
{
UnhookWindowsHookEx(hWinMessageHook);
return 0;
}
@ -1068,6 +1069,7 @@ void CDebugCommandsView::CPUSkip()
void CDebugCommandsView::CPUStepInto()
{
m_Debugger->Debug_RefreshStackWindow();
m_Debugger->Debug_RefreshStackTraceWindow();
m_Breakpoints->KeepDebugging();
m_Breakpoints->Resume();
}
@ -1075,6 +1077,7 @@ void CDebugCommandsView::CPUStepInto()
void CDebugCommandsView::CPUResume()
{
m_Debugger->Debug_RefreshStackWindow();
m_Debugger->Debug_RefreshStackTraceWindow();
m_Breakpoints->StopDebugging();
m_Breakpoints->Resume();
m_RegisterTabs.SetColorsEnabled(false);

View File

@ -12,9 +12,11 @@
#include "stdafx.h"
#include "DebuggerUI.h"
#include "Symbols.h"
CDebugStackTrace::CDebugStackTrace(CDebuggerUI* debugger) :
CDebugDialog<CDebugStackTrace>(debugger)
CDebugDialog<CDebugStackTrace>(debugger),
m_EntriesIndex(0)
{
}
@ -22,18 +24,43 @@ CDebugStackTrace::~CDebugStackTrace()
{
}
void CDebugStackTrace::PushEntry(uint32_t routineAddress, uint32_t callingAddress)
{
if (m_EntriesIndex < STACKTRACE_MAX_ENTRIES)
{
m_Entries[m_EntriesIndex] = { routineAddress, callingAddress };
m_EntriesIndex++;
}
}
void CDebugStackTrace::PopEntry()
{
if (m_EntriesIndex > 0)
{
m_EntriesIndex--;
}
}
void CDebugStackTrace::ClearEntries()
{
m_EntriesIndex = 0;
}
LRESULT CDebugStackTrace::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
DlgResize_Init();
m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, 0);
m_List.Attach(GetDlgItem(IDC_STACKTRACE_LIST));
m_List.AddColumn("Routine", 0);
m_List.AddColumn("Name", 1);
m_List.AddColumn("Caller", 0);
m_List.AddColumn("Routine", 1);
m_List.AddColumn("Name", 2);
m_List.SetColumnWidth(0, 60);
m_List.SetColumnWidth(1, 100);
m_List.SetColumnWidth(0, 70);
m_List.SetColumnWidth(1, 70);
m_List.SetColumnWidth(2, 160);
m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
WindowCreated();
return TRUE;
@ -41,7 +68,7 @@ LRESULT CDebugStackTrace::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM
LRESULT CDebugStackTrace::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RefreshList();
Refresh();
return FALSE;
}
@ -73,32 +100,46 @@ LRESULT CDebugStackTrace::OnListDblClicked(NMHDR* pNMHDR)
return 0;
}
void CDebugStackTrace::RefreshList()
void CDebugStackTrace::Refresh()
{
vector<uint32_t>* stackTrace = m_Debugger->StackTrace();
if (!m_Debugger->Breakpoints()->isDebugging())
{
return;
}
SetWindowText(stdstr_f("Stack Trace (%d)", m_EntriesIndex).c_str());
m_List.SetRedraw(FALSE);
m_List.DeleteAllItems();
int count = stackTrace->size();
CSymbols::EnterCriticalSection();
if (count > 4000)
for (int i = 0; i < m_EntriesIndex; i++)
{
count = 4000;
}
for (int i = 0; i < count; i++)
{
uint32_t address = stackTrace->at(i);
char szAddress[9];
sprintf(szAddress, "%08X", address);
uint32_t routineAddress = m_Entries[i].routineAddress;
uint32_t callingAddress = m_Entries[i].callingAddress;
char szAddress[9];
sprintf(szAddress, "%08X", callingAddress);
m_List.AddItem(i, 0, szAddress);
m_List.AddItem(i, 1, "symbol");
m_List.SetItemData(i, address);
sprintf(szAddress, "%08X", routineAddress);
m_List.AddItem(i, 1, szAddress);
CSymbolEntry* symbol = CSymbols::GetEntryByAddress(routineAddress);
if(symbol != NULL)
{
m_List.AddItem(i, 2, symbol->m_Name);
}
else
{
m_List.AddItem(i, 2, "");
}
m_List.SetItemData(i, routineAddress);
}
CSymbols::LeaveCriticalSection();
m_List.SetRedraw(TRUE);
}

View File

@ -12,6 +12,13 @@
#pragma once
#include "DebuggerUI.h"
#define STACKTRACE_MAX_ENTRIES 100
typedef struct {
uint32_t routineAddress;
uint32_t callingAddress;
} STACKTRACE_ENTRY;
class CDebugStackTrace :
public CDebugDialog<CDebugStackTrace>,
public CDialogResize<CDebugStackTrace>
@ -22,10 +29,17 @@ public:
CDebugStackTrace(CDebuggerUI * debugger);
virtual ~CDebugStackTrace(void);
void RefreshList();
void Refresh();
void PushEntry(uint32_t routineAddress, uint32_t callingAddress);
void PopEntry();
void ClearEntries();
private:
STACKTRACE_ENTRY m_Entries[STACKTRACE_MAX_ENTRIES];
int m_EntriesIndex;
HANDLE m_AutoRefreshThread;
static DWORD WINAPI AutoRefreshProc(void* _this);

View File

@ -11,6 +11,7 @@
#include "stdafx.h"
#include "DebuggerUI.h"
#include "Symbols.h"
CDebugStackView::CDebugStackView(CDebuggerUI * debugger) :
CDebugDialog<CDebugStackView>(debugger)
@ -81,6 +82,8 @@ void CDebugStackView::Refresh()
m_SPStatic.SetWindowTextA(stdstr_f("SP: %08X", spBase).c_str());
}
CSymbols::EnterCriticalSection();
for (int i = 0; i < 0x10; i++)
{
char t[4];
@ -104,5 +107,7 @@ void CDebugStackView::Refresh()
}
}
CSymbols::LeaveCriticalSection();
m_StackList.SetRedraw(TRUE);
}

View File

@ -14,6 +14,9 @@
#include "Symbols.h"
#include "DMALog.h"
CDebugMemoryView* CDebugMemoryView::_this = NULL;
HHOOK CDebugMemoryView::hWinMessageHook = NULL;
CDebugMemoryView::CDebugMemoryView(CDebuggerUI * debugger) :
CDebugDialog<CDebugMemoryView>(debugger),
m_MemoryList(NULL)
@ -115,10 +118,15 @@ LRESULT CDebugMemoryView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM
m_SymInfo.Attach(GetDlgItem(IDC_SYM_INFO));
m_DMAInfo.Attach(GetDlgItem(IDC_DMA_INFO));
_this = this;
DWORD dwThreadID = ::GetCurrentThreadId();
hWinMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProc, NULL, dwThreadID);
WindowCreated();
m_AutoRefreshThread = CreateThread(NULL, 0, AutoRefreshProc, (void*)this, 0, NULL);
return TRUE;
}
@ -132,6 +140,33 @@ DWORD WINAPI CDebugMemoryView::AutoRefreshProc(void* _this)
}
}
void CDebugMemoryView::InterceptMouseWheel(WPARAM wParam, LPARAM lParam)
{
uint32_t newAddress = m_DataStartLoc - ((short)HIWORD(wParam) / WHEEL_DELTA) * 16;
m_DataStartLoc = newAddress;
m_MemAddr.SetValue(m_DataStartLoc, false, true);
}
LRESULT CALLBACK CDebugMemoryView::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MSG *pMsg = (MSG*)lParam;
if (pMsg->message == WM_MOUSEWHEEL)
{
BOOL bHandled = TRUE;
_this->InterceptMouseWheel(pMsg->wParam, pMsg->lParam);
}
if (nCode < 0)
{
return CallNextHookEx(hWinMessageHook, nCode, wParam, lParam);
}
return 0;
}
LRESULT CDebugMemoryView::OnDestroy(void)
{
if (m_AutoRefreshThread != NULL)
@ -145,6 +180,7 @@ LRESULT CDebugMemoryView::OnDestroy(void)
delete m_MemoryList;
m_MemoryList = NULL;
}
UnhookWindowsHookEx(hWinMessageHook);
return 0;
}

View File

@ -60,6 +60,12 @@ private:
enum { MemoryToDisplay = 0x100 };
static CDebugMemoryView* _this;
static HHOOK hWinMessageHook;
static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
void InterceptMouseWheel(WPARAM wParam, LPARAM lParam);
CEditNumber m_MemAddr;
CListCtrl * m_MemoryList;
CAddSymbolDlg m_AddSymbolDlg;

View File

@ -27,16 +27,13 @@ CDebuggerUI::CDebuggerUI() :
m_Symbols(NULL),
m_Breakpoints(NULL),
m_ScriptSystem(NULL),
m_DMALogView(NULL),
m_StackTraceView(NULL),
m_StackTrace(NULL),
m_StackView(NULL),
m_DMALogView(NULL),
m_DMALog(NULL)
{
g_Debugger = this;
//m_DMALog = new vector<DMALogEntry>;
m_StackTrace = new vector<uint32_t>;
m_Breakpoints = new CBreakpoints();
m_ScriptSystem = new CScriptSystem(this);
@ -56,13 +53,12 @@ CDebuggerUI::~CDebuggerUI(void)
delete m_ScriptSystem;
delete m_Breakpoints;
delete m_Symbols;
delete m_DMALogView;
delete m_MemorySearch;
delete m_StackTrace;
delete m_DMALogView;
delete m_DMALog;
CSymbols::DeleteCriticalSection();
m_StackTrace->clear();
}
void CDebuggerUI::GameReset(CDebuggerUI * _this)
@ -82,15 +78,18 @@ void CDebuggerUI::GameReset(CDebuggerUI * _this)
_this->m_DMALog->ClearEntries();
}
if (_this->m_StackTrace)
{
_this->m_StackTrace->ClearEntries();
}
CSymbols::EnterCriticalSection();
CSymbols::Load();
CSymbols::LeaveCriticalSection();
if (_this->m_Symbols)
{
CSymbols::EnterCriticalSection();
_this->m_Symbols->Refresh();
CSymbols::LeaveCriticalSection();
}
}
@ -144,11 +143,11 @@ void CDebuggerUI::Debug_Reset(void)
delete m_DMALogView;
m_DMALogView = NULL;
}
if (m_StackTraceView)
if (m_StackTrace)
{
m_StackTraceView->HideWindow();
delete m_StackTraceView;
m_StackTraceView = NULL;
m_StackTrace->HideWindow();
delete m_StackTrace;
m_StackTrace = NULL;
}
if (m_StackView)
{
@ -314,11 +313,11 @@ void CDebuggerUI::Debug_ShowDMALogWindow(void)
void CDebuggerUI::Debug_ShowStackTrace(void)
{
if (m_StackTraceView == NULL)
if (m_StackTrace == NULL)
{
m_StackTraceView = new CDebugStackTrace(this);
m_StackTrace = new CDebugStackTrace(this);
}
m_StackTraceView->ShowWindow();
m_StackTrace->ShowWindow();
}
void CDebuggerUI::Debug_ShowStackWindow(void)
@ -338,6 +337,14 @@ void CDebuggerUI::Debug_RefreshStackWindow(void)
}
}
void CDebuggerUI::Debug_RefreshStackTraceWindow(void)
{
if (m_StackTrace != NULL)
{
m_StackTrace->Refresh();
}
}
CBreakpoints* CDebuggerUI::Breakpoints()
{
return m_Breakpoints;
@ -358,16 +365,13 @@ CDMALog* CDebuggerUI::DMALog()
return m_DMALog;
}
vector<uint32_t> * CDebuggerUI::StackTrace()
{
return m_StackTrace;
}
void CDebuggerUI::BreakpointHit()
{
m_Breakpoints->KeepDebugging();
Debug_ShowCommandsLocation(g_Reg->m_PROGRAM_COUNTER, false);
Debug_RefreshStackWindow();
Debug_RefreshStackTraceWindow();
m_Breakpoints->Pause();
}
@ -472,14 +476,23 @@ void CDebuggerUI::CPUStep()
OPCODE Opcode = R4300iOp::m_Opcode;
uint32_t op = Opcode.op;
uint32_t funct = Opcode.funct;
if (op == R4300i_JAL || funct == R4300i_SPECIAL_JALR) // JAL or JALR
if (m_StackTrace == NULL)
{
//m_StackTrace->push_back(R4300iOp::m_JumpToLocation);
m_StackTrace = new CDebugStackTrace(this);
}
if (op == R4300i_JAL || ((op == R4300i_SPECIAL) && (funct == R4300i_SPECIAL_JALR) && (Opcode.rd == 31))) // JAL or JALR RA, x
{
m_StackTrace->PushEntry(R4300iOp::m_JumpToLocation, g_Reg->m_PROGRAM_COUNTER);
}
else if (funct == R4300i_SPECIAL_JR && Opcode.rs == 31) // JR RA
{
//m_StackTrace->pop_back();
m_StackTrace->PopEntry();
}
else if (op == R4300i_CP0 && funct == R4300i_COP0_CO_ERET) // TODO may need more work
{
m_StackTrace->ClearEntries();
}
}

View File

@ -44,13 +44,12 @@ class CDebuggerUI :
CDebugScripts * m_Scripts;
CDebugSymbols * m_Symbols;
CDebugDMALogView * m_DMALogView;
CDebugStackTrace * m_StackTraceView;
CDebugStackTrace * m_StackTrace;
CDebugStackView * m_StackView;
CBreakpoints * m_Breakpoints;
CScriptSystem * m_ScriptSystem;
CDMALog * m_DMALog;
vector<uint32_t> * m_StackTrace;
void BreakpointHit(void);
@ -58,38 +57,38 @@ protected:
CDebuggerUI();
virtual ~CDebuggerUI();
void TLBChanged ( void );
bool CPUStepStarted ( void );
void CPUStep ( void );
void FrameDrawn ( void );
void TLBChanged ( void );
bool CPUStepStarted ( void );
void CPUStep ( void );
void FrameDrawn ( void );
public:
void Debug_Reset ( void );
void Debug_ShowMemoryDump ( void );
void Debug_ShowMemoryWindow ( void );
void Debug_ShowMemoryLocation ( uint32_t Address, bool VAddr );
void Debug_ShowMemorySearch ( void );
void Debug_ShowTLBWindow ( void );
void Debug_RefreshTLBWindow ( void );
void Debug_ShowCommandsWindow ( void );
void Debug_ShowCommandsLocation ( uint32_t address, bool top );
void Debug_ShowScriptsWindow ( void );
void Debug_LogScriptsWindow ( const char* text );
void Debug_ClearScriptsWindow ( void );
void Debug_RefreshScriptsWindow ( void );
void Debug_RefreshSymbolsWindow ( void );
void Debug_ShowSymbolsWindow ( void );
void Debug_ShowStackTrace ( void );
void Debug_ShowStackWindow ( void );
void Debug_RefreshStackWindow ( void );
void Debug_ShowDMALogWindow ( void );
void Debug_Reset ( void );
void Debug_ShowMemoryDump ( void );
void Debug_ShowMemoryWindow ( void );
void Debug_ShowMemoryLocation ( uint32_t Address, bool VAddr );
void Debug_ShowMemorySearch ( void );
void Debug_ShowTLBWindow ( void );
void Debug_RefreshTLBWindow ( void );
void Debug_ShowCommandsWindow ( void );
void Debug_ShowCommandsLocation ( uint32_t address, bool top );
void Debug_ShowScriptsWindow ( void );
void Debug_LogScriptsWindow ( const char* text );
void Debug_ClearScriptsWindow ( void );
void Debug_RefreshScriptsWindow ( void );
void Debug_RefreshSymbolsWindow ( void );
void Debug_ShowSymbolsWindow ( void );
void Debug_ShowStackTrace ( void );
void Debug_ShowStackWindow ( void );
void Debug_RefreshStackWindow ( void );
void Debug_RefreshStackTraceWindow ( void );
void Debug_ShowDMALogWindow ( void );
CBreakpoints* Breakpoints();
CDebugSymbols* Symbols();
CScriptSystem* ScriptSystem();
CDebugScripts* ScriptConsole();
CDMALog* DMALog();
vector<uint32_t> * StackTrace();
static void GameReset ( CDebuggerUI * _this );
};

View File

@ -1154,7 +1154,6 @@ void CMainMenu::FillOutMenu(HMENU hMenu)
/* Debug - Stack Trace
*******************/
Item.Reset(ID_DEBUGGER_STACKTRACE, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Stack Trace...");
Item.SetItemEnabled(false);
DebugMenu.push_back(Item);
DebugMenu.push_back(MENU_ITEM(SPLITER));

View File

@ -961,12 +961,12 @@ BEGIN
LTEXT "Block:",IDC_BLOCK_INFO,9,200,168,8
END
IDD_Debugger_StackTrace DIALOGEX 0, 0, 199, 167
IDD_Debugger_StackTrace DIALOGEX 0, 0, 223, 221
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Stack Trace"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_STACKTRACE_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,0,0,199,167
CONTROL "",IDC_STACKTRACE_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_TABSTOP,0,0,224,221
END
IDD_Debugger_RegCOP0 DIALOGEX 0, 0, 190, 210
@ -1589,8 +1589,6 @@ BEGIN
IDD_Debugger_StackTrace, DIALOG
BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 160
END
IDD_Debugger_RegCOP0, DIALOG