[Debugger] Symbols: improve performance, implement filter textbox (#2102)
This commit is contained in:
parent
29a40ba57b
commit
56911cef58
|
@ -7,7 +7,8 @@
|
||||||
#include "Symbols.h"
|
#include "Symbols.h"
|
||||||
|
|
||||||
const CSetValueDlg::ComboItem CDebugSymbols::ModalChangeTypeItems[] = {
|
const CSetValueDlg::ComboItem CDebugSymbols::ModalChangeTypeItems[] = {
|
||||||
{ "code", SYM_CODE},
|
{ "code", SYM_CODE },
|
||||||
|
{ "data", SYM_DATA },
|
||||||
{ "uint8", SYM_U8 },
|
{ "uint8", SYM_U8 },
|
||||||
{ "int8", SYM_S8 },
|
{ "int8", SYM_S8 },
|
||||||
{ "uint16", SYM_U16 },
|
{ "uint16", SYM_U16 },
|
||||||
|
@ -25,8 +26,12 @@ const CSetValueDlg::ComboItem CDebugSymbols::ModalChangeTypeItems[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
CDebugSymbols::CDebugSymbols(CDebuggerUI * debugger) :
|
CDebugSymbols::CDebugSymbols(CDebuggerUI * debugger) :
|
||||||
CDebugDialog<CDebugSymbols>(debugger)
|
CDebugDialog<CDebugSymbols>(debugger),
|
||||||
|
m_SymbolTable(debugger->SymbolTable()),
|
||||||
|
m_SymbolCacheStartIndex(0),
|
||||||
|
m_bFiltering(false)
|
||||||
{
|
{
|
||||||
|
memset(m_FilterText, 0, sizeof(m_FilterText));
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CDebugSymbols::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
LRESULT CDebugSymbols::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||||
|
@ -49,6 +54,8 @@ LRESULT CDebugSymbols::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*l
|
||||||
m_SymbolsListView.SetColumnWidth(3, 100);
|
m_SymbolsListView.SetColumnWidth(3, 100);
|
||||||
m_SymbolsListView.SetColumnWidth(4, 120);
|
m_SymbolsListView.SetColumnWidth(4, 120);
|
||||||
|
|
||||||
|
::SetWindowText(GetDlgItem(IDC_FILTER_EDIT), m_FilterText);
|
||||||
|
|
||||||
Refresh();
|
Refresh();
|
||||||
|
|
||||||
SetTimer(TIMER_ID_AUTO_REFRESH, 100, nullptr);
|
SetTimer(TIMER_ID_AUTO_REFRESH, 100, nullptr);
|
||||||
|
@ -74,7 +81,7 @@ void CDebugSymbols::OnTimer(UINT_PTR nIDEvent)
|
||||||
{
|
{
|
||||||
if (nIDEvent == TIMER_ID_AUTO_REFRESH)
|
if (nIDEvent == TIMER_ID_AUTO_REFRESH)
|
||||||
{
|
{
|
||||||
RefreshValues();
|
Refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,66 +96,53 @@ LRESULT CDebugSymbols::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*
|
||||||
m_AddSymbolDlg.DoModal(m_Debugger);
|
m_AddSymbolDlg.DoModal(m_Debugger);
|
||||||
break;
|
break;
|
||||||
case IDC_REMOVESYMBOL_BTN:
|
case IDC_REMOVESYMBOL_BTN:
|
||||||
{
|
|
||||||
int nItem = m_SymbolsListView.GetSelectedIndex();
|
|
||||||
if (nItem != -1)
|
|
||||||
{
|
{
|
||||||
int id = m_SymbolsListView.GetItemData(nItem);
|
int nItem = m_SymbolsListView.GetSelectedIndex();
|
||||||
m_Debugger->SymbolTable()->RemoveSymbolById(id);
|
int id = -1;
|
||||||
m_Debugger->SymbolTable()->Save();
|
if (m_bFiltering)
|
||||||
Refresh();
|
{
|
||||||
|
id = m_FilteredSymbols[nItem].m_Id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CSymbol symbol;
|
||||||
|
m_SymbolTable->GetSymbolByIndex(nItem, &symbol);
|
||||||
|
id = symbol.m_Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id != -1)
|
||||||
|
{
|
||||||
|
m_SymbolTable->RemoveSymbolById(id);
|
||||||
|
m_SymbolTable->Save();
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CDebugSymbols::OnListDblClicked(NMHDR* pNMHDR)
|
LRESULT CDebugSymbols::OnListDblClicked(NMHDR* pNMHDR)
|
||||||
{
|
{
|
||||||
if (g_MMU == nullptr)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG iItem = m_SymbolsListView.GetNextItem(-1, LVNI_SELECTED);
|
|
||||||
if (iItem == -1)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nSelectedCol = -1;
|
|
||||||
|
|
||||||
// Hit test for column
|
|
||||||
|
|
||||||
POINT mousePt;
|
|
||||||
RECT listRect;
|
|
||||||
GetCursorPos(&mousePt);
|
|
||||||
m_SymbolsListView.GetWindowRect(&listRect);
|
|
||||||
|
|
||||||
int mouseX = mousePt.x - listRect.left;
|
|
||||||
|
|
||||||
for (int nCol = 0, colX = 0; nCol < SymbolsListView_Num_Columns; nCol++)
|
|
||||||
{
|
|
||||||
int colWidth = m_SymbolsListView.GetColumnWidth(nCol);
|
|
||||||
if (mouseX >= colX && mouseX <= colX + colWidth)
|
|
||||||
{
|
|
||||||
nSelectedCol = nCol;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
colX += colWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
|
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
|
||||||
int nItem = pIA->iItem;
|
|
||||||
int id = m_SymbolsListView.GetItemData(nItem);
|
|
||||||
|
|
||||||
CSymbol symbol;
|
if (pIA->iItem == -1)
|
||||||
if (!m_Debugger->SymbolTable()->GetSymbolById(id, &symbol))
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int id = GetListItemSymbolId(pIA->iItem);
|
||||||
|
|
||||||
|
CSymbol symbol;
|
||||||
|
if (!m_SymbolTable->GetSymbolById(id, &symbol))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
POINT mousePt;
|
||||||
|
GetCursorPos(&mousePt);
|
||||||
|
int nSelectedCol = ColumnHitTest(mousePt);
|
||||||
|
|
||||||
switch (nSelectedCol)
|
switch (nSelectedCol)
|
||||||
{
|
{
|
||||||
case SymbolsListView_Col_Address:
|
case SymbolsListView_Col_Address:
|
||||||
|
@ -168,22 +162,22 @@ LRESULT CDebugSymbols::OnListDblClicked(NMHDR* pNMHDR)
|
||||||
ValueType t = (ValueType)m_SetValueDlg.GetEnteredData();
|
ValueType t = (ValueType)m_SetValueDlg.GetEnteredData();
|
||||||
|
|
||||||
// TODO: Is there a better way?
|
// TODO: Is there a better way?
|
||||||
m_Debugger->SymbolTable()->RemoveSymbolById(id);
|
m_SymbolTable->RemoveSymbolById(id);
|
||||||
m_Debugger->SymbolTable()->AddSymbol(t, symbol.m_Address, symbol.m_Name, symbol.m_Description);
|
m_SymbolTable->AddSymbol(t, symbol.m_Address, symbol.m_Name, symbol.m_Description);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SymbolsListView_Col_Name:
|
case SymbolsListView_Col_Name:
|
||||||
if (m_SetValueDlg.DoModal("Set name", "New name:", symbol.m_Name))
|
if (m_SetValueDlg.DoModal("Set name", "New name:", symbol.m_Name))
|
||||||
{
|
{
|
||||||
m_Debugger->SymbolTable()->RemoveSymbolById(id);
|
m_SymbolTable->RemoveSymbolById(id);
|
||||||
m_Debugger->SymbolTable()->AddSymbol(symbol.m_Type, symbol.m_Address, m_SetValueDlg.GetEnteredString().c_str(), symbol.m_Description);
|
m_SymbolTable->AddSymbol(symbol.m_Type, symbol.m_Address, m_SetValueDlg.GetEnteredString().c_str(), symbol.m_Description);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SymbolsListView_Col_Value:
|
case SymbolsListView_Col_Value:
|
||||||
char szValue[256];
|
char szValue[256];
|
||||||
const char* x;
|
const char* x;
|
||||||
const char* y;
|
const char* y;
|
||||||
m_Debugger->SymbolTable()->GetValueString(szValue, &symbol);
|
m_SymbolTable->GetValueString(szValue, &symbol);
|
||||||
if (m_SetValueDlg.DoModal("Change value", "New value:", szValue))
|
if (m_SetValueDlg.DoModal("Change value", "New value:", szValue))
|
||||||
{
|
{
|
||||||
const std::string & EnteredString = m_SetValueDlg.GetEnteredString();
|
const std::string & EnteredString = m_SetValueDlg.GetEnteredString();
|
||||||
|
@ -271,73 +265,194 @@ LRESULT CDebugSymbols::OnListDblClicked(NMHDR* pNMHDR)
|
||||||
case SymbolsListView_Col_Description:
|
case SymbolsListView_Col_Description:
|
||||||
if (m_SetValueDlg.DoModal("Set description", "New description:", symbol.m_Description))
|
if (m_SetValueDlg.DoModal("Set description", "New description:", symbol.m_Description))
|
||||||
{
|
{
|
||||||
m_Debugger->SymbolTable()->RemoveSymbolById(id);
|
m_SymbolTable->RemoveSymbolById(id);
|
||||||
m_Debugger->SymbolTable()->AddSymbol(symbol.m_Type, symbol.m_Address, symbol.m_Name, m_SetValueDlg.GetEnteredString().c_str());
|
m_SymbolTable->AddSymbol(symbol.m_Type, symbol.m_Address, symbol.m_Name, m_SetValueDlg.GetEnteredString().c_str());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Debugger->SymbolTable()->Save();
|
m_SymbolTable->Save();
|
||||||
Refresh();
|
Refresh();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDebugSymbols::Refresh()
|
LRESULT CDebugSymbols::OnListGetDispInfo(NMHDR* pNMHDR)
|
||||||
{
|
{
|
||||||
if (m_SymbolsListView.m_hWnd == nullptr)
|
NMLVDISPINFO* plvdi = (NMLVDISPINFO*)pNMHDR;
|
||||||
|
|
||||||
|
int index = plvdi->item.iItem;
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
{
|
{
|
||||||
return;
|
return TRUE;
|
||||||
}
|
|
||||||
m_SymbolsListView.SetRedraw(FALSE);
|
|
||||||
m_SymbolsListView.DeleteAllItems();
|
|
||||||
|
|
||||||
CSymbol symbol;
|
|
||||||
int nItem = 0;
|
|
||||||
|
|
||||||
while (m_Debugger->SymbolTable()->GetSymbolByIndex(nItem, &symbol))
|
|
||||||
{
|
|
||||||
char szValue[256];
|
|
||||||
m_Debugger->SymbolTable()->GetValueString(szValue, &symbol);
|
|
||||||
|
|
||||||
stdstr strAddr = stdstr_f("%08X", symbol.m_Address);
|
|
||||||
|
|
||||||
m_SymbolsListView.AddItem(nItem, 0, strAddr.ToUTF16().c_str());
|
|
||||||
m_SymbolsListView.AddItem(nItem, 1, stdstr(symbol.TypeName()).ToUTF16().c_str());
|
|
||||||
m_SymbolsListView.AddItem(nItem, 2, stdstr(symbol.m_Name).ToUTF16().c_str());
|
|
||||||
m_SymbolsListView.AddItem(nItem, 4, stdstr(symbol.m_Description).ToUTF16().c_str());
|
|
||||||
m_SymbolsListView.AddItem(nItem, 5, stdstr(szValue).ToUTF16().c_str());
|
|
||||||
|
|
||||||
m_SymbolsListView.SetItemData(nItem, symbol.m_Id);
|
|
||||||
nItem++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_SymbolsListView.SetRedraw(TRUE);
|
std::vector<SymbolCacheItem>& cache = m_bFiltering ? m_FilteredSymbols : m_SymbolCache;
|
||||||
|
|
||||||
|
if (!m_bFiltering)
|
||||||
|
{
|
||||||
|
index -= m_SymbolCacheStartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (plvdi->item.iSubItem)
|
||||||
|
{
|
||||||
|
case SymbolsListView_Col_Address:
|
||||||
|
plvdi->item.pszText = cache[index].m_Address;
|
||||||
|
break;
|
||||||
|
case SymbolsListView_Col_Type:
|
||||||
|
plvdi->item.pszText = cache[index].m_Type;
|
||||||
|
break;
|
||||||
|
case SymbolsListView_Col_Name:
|
||||||
|
plvdi->item.pszText = cache[index].m_Name;
|
||||||
|
break;
|
||||||
|
case SymbolsListView_Col_Value:
|
||||||
|
plvdi->item.pszText = cache[index].m_Value;
|
||||||
|
break;
|
||||||
|
case SymbolsListView_Col_Description:
|
||||||
|
plvdi->item.pszText = cache[index].m_Description;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDebugSymbols::RefreshValues()
|
LRESULT CDebugSymbols::OnListCacheHint(NMHDR * pNMHDR)
|
||||||
{
|
{
|
||||||
if (g_MMU == nullptr)
|
NMLVCACHEHINT* plvch = (NMLVCACHEHINT*)pNMHDR;
|
||||||
|
|
||||||
|
if (m_bFiltering)
|
||||||
{
|
{
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = m_SymbolsListView.GetItemCount();
|
m_SymbolCacheStartIndex = plvch->iFrom;
|
||||||
|
m_SymbolCache.clear();
|
||||||
CSymbol symbol;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int index = plvch->iFrom; index <= plvch->iTo; index++)
|
||||||
{
|
{
|
||||||
int symbolId = m_SymbolsListView.GetItemData(i);
|
CSymbol symbol;
|
||||||
|
if (!m_SymbolTable->GetSymbolByIndex(index, &symbol))
|
||||||
if (!m_Debugger->SymbolTable()->GetSymbolById(symbolId, &symbol))
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char szValue[256];
|
SymbolCacheItem item(symbol, m_SymbolTable);
|
||||||
m_Debugger->SymbolTable()->GetValueString(szValue, &symbol);
|
m_SymbolCache.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
m_SymbolsListView.SetItemText(i, 3, stdstr(szValue).ToUTF16().c_str());
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CDebugSymbols::OnFilterChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||||
|
{
|
||||||
|
if (::GetWindowTextLength(GetDlgItem(IDC_FILTER_EDIT)) == 0)
|
||||||
|
{
|
||||||
|
m_bFiltering = false;
|
||||||
|
Refresh();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bFiltering = true;
|
||||||
|
::GetWindowText(GetDlgItem(IDC_FILTER_EDIT), m_FilterText, sizeof(m_FilterText) / sizeof(wchar_t));
|
||||||
|
|
||||||
|
UpdateFilteredSymbols();
|
||||||
|
|
||||||
|
m_SymbolsListView.SetItemCount(m_FilteredSymbols.size());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CDebugSymbols::ColumnHitTest(POINT& pt)
|
||||||
|
{
|
||||||
|
int nHitCol = -1;
|
||||||
|
RECT listRect;
|
||||||
|
m_SymbolsListView.GetWindowRect(&listRect);
|
||||||
|
|
||||||
|
int mouseX = pt.x - listRect.left;
|
||||||
|
|
||||||
|
for (int nCol = 0, colX = 0; nCol < SymbolsListView_Num_Columns; nCol++)
|
||||||
|
{
|
||||||
|
int colWidth = m_SymbolsListView.GetColumnWidth(nCol);
|
||||||
|
if (mouseX >= colX && mouseX <= colX + colWidth)
|
||||||
|
{
|
||||||
|
nHitCol = nCol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
colX += colWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nHitCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDebugSymbols::UpdateFilteredSymbols()
|
||||||
|
{
|
||||||
|
m_FilteredSymbols.clear();
|
||||||
|
|
||||||
|
CSymbol symbol;
|
||||||
|
size_t index = 0;
|
||||||
|
while (m_SymbolTable->GetSymbolByIndex(index++, &symbol))
|
||||||
|
{
|
||||||
|
std::wstring strName = stdstr(symbol.m_Name).ToUTF16();
|
||||||
|
std::wstring strDesc = stdstr(symbol.m_Description).ToUTF16();
|
||||||
|
|
||||||
|
if (strName.find(m_FilterText) != std::wstring::npos ||
|
||||||
|
strDesc.find(m_FilterText) != std::wstring::npos)
|
||||||
|
{
|
||||||
|
SymbolCacheItem item(symbol, m_SymbolTable);
|
||||||
|
m_FilteredSymbols.push_back(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDebugSymbols::Refresh()
|
||||||
|
{
|
||||||
|
if (g_Settings->LoadStringVal(Game_GameName) != "")
|
||||||
|
{
|
||||||
|
stdstr windowTitle = stdstr_f("Symbols - %s", g_Settings->LoadStringVal(Game_GameName).c_str());
|
||||||
|
SetWindowText(windowTitle.ToUTF16().c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetWindowText(L"Symbols");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_SymbolsListView.m_hWnd == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numSymbols = 0;
|
||||||
|
|
||||||
|
if (m_bFiltering)
|
||||||
|
{
|
||||||
|
UpdateFilteredSymbols();
|
||||||
|
numSymbols = m_FilteredSymbols.size();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numSymbols = m_SymbolTable->GetCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_SymbolsListView.SetItemCountEx(numSymbols, LVSICF_NOSCROLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CDebugSymbols::GetListItemSymbolId(int nItem)
|
||||||
|
{
|
||||||
|
if (m_bFiltering)
|
||||||
|
{
|
||||||
|
if (nItem >= m_FilteredSymbols.size())
|
||||||
|
{
|
||||||
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_FilteredSymbols[nItem].m_Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSymbol symbol;
|
||||||
|
if (!m_SymbolTable->GetSymbolByIndex(nItem, &symbol))
|
||||||
|
{
|
||||||
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbol.m_Id;
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "DebuggerUI.h"
|
#include "DebuggerUI.h"
|
||||||
|
#include "Symbols.h"
|
||||||
// TODO: Maybe add char* ownerName and use a TreeView
|
|
||||||
|
|
||||||
class CDebugSymbols :
|
class CDebugSymbols :
|
||||||
public CDebugDialog<CDebugSymbols>,
|
public CDebugDialog<CDebugSymbols>,
|
||||||
|
@ -18,38 +17,81 @@ private:
|
||||||
SymbolsListView_Num_Columns
|
SymbolsListView_Num_Columns
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SymbolCacheItem {
|
||||||
|
int m_Id;
|
||||||
|
wchar_t m_Address[16];
|
||||||
|
wchar_t m_Type[16];
|
||||||
|
wchar_t m_Name[48];
|
||||||
|
wchar_t m_Value[64];
|
||||||
|
wchar_t m_Description[256];
|
||||||
|
|
||||||
|
SymbolCacheItem(CSymbol& symbol, CSymbolTable* symbolTable)
|
||||||
|
{
|
||||||
|
char szValue[64];
|
||||||
|
symbolTable->GetValueString(szValue, &symbol);
|
||||||
|
|
||||||
|
std::wstring strType = stdstr(symbol.TypeName()).ToUTF16();
|
||||||
|
std::wstring strName = stdstr(symbol.m_Name).ToUTF16();
|
||||||
|
std::wstring strValue = stdstr(szValue).ToUTF16();
|
||||||
|
std::wstring strDesc = stdstr(symbol.m_Description).ToUTF16();
|
||||||
|
|
||||||
|
m_Id = symbol.m_Id;
|
||||||
|
wnsprintf(m_Address, sizeof(m_Address) / sizeof(wchar_t), L"%08X", symbol.m_Address);
|
||||||
|
wcsncpy(m_Type, strType.c_str(), sizeof(m_Type) / sizeof(wchar_t));
|
||||||
|
wcsncpy(m_Name, strName.c_str(), sizeof(m_Name) / sizeof(wchar_t));
|
||||||
|
wcsncpy(m_Value, strValue.c_str(), sizeof(m_Value) / sizeof(wchar_t));
|
||||||
|
wcsncpy(m_Description, strDesc.c_str(), sizeof(m_Description) / sizeof(wchar_t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static const CSetValueDlg::ComboItem ModalChangeTypeItems[];
|
static const CSetValueDlg::ComboItem ModalChangeTypeItems[];
|
||||||
|
|
||||||
|
CSymbolTable* m_SymbolTable;
|
||||||
CListViewCtrl m_SymbolsListView;
|
CListViewCtrl m_SymbolsListView;
|
||||||
CSetValueDlg m_SetValueDlg;
|
CSetValueDlg m_SetValueDlg;
|
||||||
CAddSymbolDlg m_AddSymbolDlg;
|
CAddSymbolDlg m_AddSymbolDlg;
|
||||||
|
|
||||||
|
size_t m_SymbolCacheStartIndex;
|
||||||
|
std::vector<SymbolCacheItem> m_SymbolCache;
|
||||||
|
|
||||||
|
bool m_bFiltering;
|
||||||
|
wchar_t m_FilterText[64];
|
||||||
|
std::vector<SymbolCacheItem> m_FilteredSymbols;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum { IDD = IDD_Debugger_Symbols };
|
enum { IDD = IDD_Debugger_Symbols };
|
||||||
enum { TIMER_ID_AUTO_REFRESH };
|
enum { TIMER_ID_AUTO_REFRESH };
|
||||||
|
|
||||||
CDebugSymbols(CDebuggerUI * debugger);
|
CDebugSymbols(CDebuggerUI * debugger);
|
||||||
//virtual ~CDebugScripts(void);
|
//virtual ~CDebugSymbols(void);
|
||||||
|
|
||||||
void Refresh();
|
void Refresh();
|
||||||
void RefreshValues();
|
void UpdateFilteredSymbols();
|
||||||
|
int GetListItemSymbolId(int nItem);
|
||||||
|
int ColumnHitTest(POINT& pt);
|
||||||
|
|
||||||
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||||
LRESULT OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
LRESULT OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||||
LRESULT OnListDblClicked(NMHDR* pNMHDR);
|
LRESULT OnFilterChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||||
|
LRESULT OnListDblClicked(NMHDR* pNMHDR);
|
||||||
|
LRESULT OnListGetDispInfo(NMHDR* pNMHDR);
|
||||||
|
LRESULT OnListCacheHint(NMHDR* pNMHDR);
|
||||||
LRESULT OnDestroy(void);
|
LRESULT OnDestroy(void);
|
||||||
void OnExitSizeMove(void);
|
void OnExitSizeMove(void);
|
||||||
void OnTimer(UINT_PTR nIDEvent);
|
void OnTimer(UINT_PTR nIDEvent);
|
||||||
|
|
||||||
BEGIN_MSG_MAP_EX(CDebugSymbols)
|
BEGIN_MSG_MAP_EX(CDebugSymbols)
|
||||||
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
|
|
||||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||||
MSG_WM_DESTROY(OnDestroy)
|
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
|
||||||
|
COMMAND_HANDLER(IDC_FILTER_EDIT, EN_CHANGE, OnFilterChanged)
|
||||||
NOTIFY_HANDLER_EX(IDC_SYMBOLS_LIST, NM_DBLCLK, OnListDblClicked)
|
NOTIFY_HANDLER_EX(IDC_SYMBOLS_LIST, NM_DBLCLK, OnListDblClicked)
|
||||||
|
NOTIFY_HANDLER_EX(IDC_SYMBOLS_LIST, LVN_GETDISPINFO, OnListGetDispInfo)
|
||||||
|
NOTIFY_HANDLER_EX(IDC_SYMBOLS_LIST, LVN_ODCACHEHINT, OnListCacheHint)
|
||||||
MSG_WM_TIMER(OnTimer)
|
MSG_WM_TIMER(OnTimer)
|
||||||
|
MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
|
||||||
|
MSG_WM_DESTROY(OnDestroy)
|
||||||
CHAIN_MSG_MAP(CDialogResize<CDebugSymbols>)
|
CHAIN_MSG_MAP(CDialogResize<CDebugSymbols>)
|
||||||
MSG_WM_EXITSIZEMOVE(OnExitSizeMove);
|
END_MSG_MAP()
|
||||||
END_MSG_MAP()
|
|
||||||
|
|
||||||
BEGIN_DLGRESIZE_MAP(CDebugSymbols)
|
BEGIN_DLGRESIZE_MAP(CDebugSymbols)
|
||||||
DLGRESIZE_CONTROL(IDC_FILTER_EDIT, DLSZ_MOVE_Y)
|
DLGRESIZE_CONTROL(IDC_FILTER_EDIT, DLSZ_MOVE_Y)
|
||||||
|
|
|
@ -923,7 +923,7 @@ LRESULT CDebugMemoryView::OnHxHotAddrChanged(LPNMHDR /*lpNMHDR*/)
|
||||||
stdstr strAddrInfo = "";
|
stdstr strAddrInfo = "";
|
||||||
|
|
||||||
CSymbol symbol;
|
CSymbol symbol;
|
||||||
if (m_Debugger->SymbolTable()->GetSymbolByOverlappedAddress(m_HotAddress, &symbol))
|
if (m_Debugger->SymbolTable()->GetSymbolByAddress(m_HotAddress, &symbol))
|
||||||
{
|
{
|
||||||
strAddrInfo += stdstr_f("%08X %s %s", symbol.m_Address, symbol.TypeName(), symbol.m_Name);
|
strAddrInfo += stdstr_f("%08X %s %s", symbol.m_Address, symbol.TypeName(), symbol.m_Name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,8 @@ void CSymbolTable::Load()
|
||||||
{
|
{
|
||||||
CGuard guard(m_CS);
|
CGuard guard(m_CS);
|
||||||
|
|
||||||
|
m_AddressMap.clear();
|
||||||
|
|
||||||
m_NextSymbolId = 0;
|
m_NextSymbolId = 0;
|
||||||
m_Symbols.clear();
|
m_Symbols.clear();
|
||||||
|
|
||||||
|
@ -224,7 +226,7 @@ void CSymbolTable::Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add symbol object to the vector
|
// Add symbol object to the vector
|
||||||
AddSymbol(type, address, name, description);
|
AddSymbol(type, address, name, description, false);
|
||||||
|
|
||||||
if (m_ParserDelimeter == '\0')
|
if (m_ParserDelimeter == '\0')
|
||||||
{
|
{
|
||||||
|
@ -234,6 +236,9 @@ void CSymbolTable::Load()
|
||||||
|
|
||||||
lineNumber++;
|
lineNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort(m_Symbols.begin(), m_Symbols.end(), CmpSymbolAddresses);
|
||||||
|
UpdateAddressMap();
|
||||||
|
|
||||||
delete[] m_SymFileParseBuffer;
|
delete[] m_SymFileParseBuffer;
|
||||||
m_SymFileParseBuffer = nullptr;
|
m_SymFileParseBuffer = nullptr;
|
||||||
|
@ -380,7 +385,7 @@ void CSymbolTable::GetValueString(char* dst, CSymbol* symbol)
|
||||||
void CSymbolTable::ParseErrorAlert(char* message, int lineNumber)
|
void CSymbolTable::ParseErrorAlert(char* message, int lineNumber)
|
||||||
{
|
{
|
||||||
stdstr messageFormatted = stdstr_f("%s\nLine %d", message, lineNumber);
|
stdstr messageFormatted = stdstr_f("%s\nLine %d", message, lineNumber);
|
||||||
MessageBox(nullptr, messageFormatted.ToUTF16().c_str(), L"Parse error", MB_OK | MB_ICONWARNING);
|
MessageBox(nullptr, messageFormatted.ToUTF16().c_str(), L"Symbol parse error", MB_OK | MB_ICONWARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSymbolTable::Reset()
|
void CSymbolTable::Reset()
|
||||||
|
@ -394,7 +399,7 @@ bool CSymbolTable::CmpSymbolAddresses(CSymbol& a, CSymbol& b)
|
||||||
return (a.m_Address < b.m_Address);
|
return (a.m_Address < b.m_Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSymbolTable::AddSymbol(int type, uint32_t address, const char* name, const char* description)
|
void CSymbolTable::AddSymbol(int type, uint32_t address, const char* name, const char* description, bool bSortAfter)
|
||||||
{
|
{
|
||||||
CGuard guard(m_CS);
|
CGuard guard(m_CS);
|
||||||
|
|
||||||
|
@ -411,9 +416,23 @@ void CSymbolTable::AddSymbol(int type, uint32_t address, const char* name, const
|
||||||
int id = m_NextSymbolId++;
|
int id = m_NextSymbolId++;
|
||||||
|
|
||||||
CSymbol symbol = CSymbol(id, type, address, name, description);
|
CSymbol symbol = CSymbol(id, type, address, name, description);
|
||||||
|
m_AddressMap[address] = m_Symbols.size();
|
||||||
m_Symbols.push_back(symbol);
|
m_Symbols.push_back(symbol);
|
||||||
|
|
||||||
sort(m_Symbols.begin(), m_Symbols.end(), CmpSymbolAddresses);
|
if (bSortAfter)
|
||||||
|
{
|
||||||
|
sort(m_Symbols.begin(), m_Symbols.end(), CmpSymbolAddresses);
|
||||||
|
UpdateAddressMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSymbolTable::UpdateAddressMap()
|
||||||
|
{
|
||||||
|
m_AddressMap.clear();
|
||||||
|
for (size_t i = 0; i < m_Symbols.size(); i++)
|
||||||
|
{
|
||||||
|
m_AddressMap[m_Symbols[i].m_Address] = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSymbolTable::GetCount()
|
int CSymbolTable::GetCount()
|
||||||
|
@ -436,30 +455,15 @@ bool CSymbolTable::GetSymbolByIndex(size_t index, CSymbol* symbol)
|
||||||
bool CSymbolTable::GetSymbolByAddress(uint32_t address, CSymbol* symbol)
|
bool CSymbolTable::GetSymbolByAddress(uint32_t address, CSymbol* symbol)
|
||||||
{
|
{
|
||||||
CGuard guard(m_CS);
|
CGuard guard(m_CS);
|
||||||
for (size_t i = 0; i < m_Symbols.size(); i++)
|
|
||||||
{
|
|
||||||
if (m_Symbols[i].m_Address == address)
|
|
||||||
{
|
|
||||||
*symbol = m_Symbols[i];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSymbolTable::GetSymbolByOverlappedAddress(uint32_t address, CSymbol* symbol)
|
if (m_AddressMap.count(address) == 0)
|
||||||
{
|
|
||||||
CGuard guard(m_CS);
|
|
||||||
for (size_t i = 0; i < m_Symbols.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (address >= m_Symbols[i].m_Address &&
|
return false;
|
||||||
address < m_Symbols[i].m_Address + m_Symbols[i].TypeSize())
|
|
||||||
{
|
|
||||||
*symbol = m_Symbols[i];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
size_t index = m_AddressMap[address];
|
||||||
|
*symbol = m_Symbols[index];
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSymbolTable::GetSymbolById(int id, CSymbol* symbol)
|
bool CSymbolTable::GetSymbolById(int id, CSymbol* symbol)
|
||||||
|
@ -484,8 +488,10 @@ bool CSymbolTable::RemoveSymbolById(int id)
|
||||||
if (m_Symbols[i].m_Id == id)
|
if (m_Symbols[i].m_Id == id)
|
||||||
{
|
{
|
||||||
m_Symbols.erase(m_Symbols.begin() + i);
|
m_Symbols.erase(m_Symbols.begin() + i);
|
||||||
|
UpdateAddressMap();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,8 @@ private:
|
||||||
CDebuggerUI* m_Debugger;
|
CDebuggerUI* m_Debugger;
|
||||||
CriticalSection m_CS;
|
CriticalSection m_CS;
|
||||||
std::vector<CSymbol> m_Symbols;
|
std::vector<CSymbol> m_Symbols;
|
||||||
|
std::map<uint32_t, size_t> m_AddressMap; // address -> symbol index
|
||||||
|
|
||||||
int m_NextSymbolId;
|
int m_NextSymbolId;
|
||||||
|
|
||||||
CFile m_SymFileHandle;
|
CFile m_SymFileHandle;
|
||||||
|
@ -64,6 +65,8 @@ private:
|
||||||
|
|
||||||
void ParserFetchToken(const char* delim);
|
void ParserFetchToken(const char* delim);
|
||||||
|
|
||||||
|
void UpdateAddressMap();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static symbol_type_info_t m_SymbolTypes[];
|
static symbol_type_info_t m_SymbolTypes[];
|
||||||
static const char* GetTypeName(int typeId);
|
static const char* GetTypeName(int typeId);
|
||||||
|
@ -78,13 +81,12 @@ public:
|
||||||
void Save();
|
void Save();
|
||||||
void ParseErrorAlert(char* message, int lineNumber);
|
void ParseErrorAlert(char* message, int lineNumber);
|
||||||
|
|
||||||
void AddSymbol(int type, uint32_t address, const char* name, const char* description = nullptr);
|
void AddSymbol(int type, uint32_t address, const char* name, const char* description = nullptr, bool bSortAfter = true);
|
||||||
void Reset();
|
void Reset();
|
||||||
int GetCount();
|
int GetCount();
|
||||||
bool GetSymbolById(int id, CSymbol* symbol);
|
bool GetSymbolById(int id, CSymbol* symbol);
|
||||||
bool GetSymbolByIndex(size_t index, CSymbol* symbol);
|
bool GetSymbolByIndex(size_t index, CSymbol* symbol);
|
||||||
bool GetSymbolByAddress(uint32_t address, CSymbol* symbol);
|
bool GetSymbolByAddress(uint32_t address, CSymbol* symbol);
|
||||||
bool GetSymbolByOverlappedAddress(uint32_t address, CSymbol* symbol);
|
|
||||||
bool RemoveSymbolById(int id);
|
bool RemoveSymbolById(int id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -888,10 +888,10 @@ STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | W
|
||||||
CAPTION "Symbols"
|
CAPTION "Symbols"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
CONTROL "",IDC_SYMBOLS_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_TABSTOP,0,0,313,123
|
CONTROL "",IDC_SYMBOLS_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_TABSTOP,0,0,313,123
|
||||||
PUSHBUTTON "+",IDC_ADDSYMBOL_BTN,284,125,24,12
|
PUSHBUTTON "+",IDC_ADDSYMBOL_BTN,284,125,24,12
|
||||||
PUSHBUTTON "-",IDC_REMOVESYMBOL_BTN,259,125,24,12
|
PUSHBUTTON "-",IDC_REMOVESYMBOL_BTN,259,125,24,12
|
||||||
EDITTEXT IDC_FILTER_EDIT,29,125,150,12,ES_AUTOHSCROLL | WS_DISABLED
|
EDITTEXT IDC_FILTER_EDIT,29,125,150,12,ES_AUTOHSCROLL
|
||||||
LTEXT "Filter:",IDC_FILTER_STATIC,9,127,18,9
|
LTEXT "Filter:",IDC_FILTER_STATIC,9,127,18,9
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue