[Debugger] Symbols: improve performance, implement filter textbox (#2102)

This commit is contained in:
shyguyhex 2021-08-25 21:58:34 -05:00 committed by GitHub
parent 29a40ba57b
commit 56911cef58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 301 additions and 136 deletions

View File

@ -8,6 +8,7 @@
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();
} }
} }
@ -91,64 +98,51 @@ LRESULT CDebugSymbols::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*
case IDC_REMOVESYMBOL_BTN: case IDC_REMOVESYMBOL_BTN:
{ {
int nItem = m_SymbolsListView.GetSelectedIndex(); int nItem = m_SymbolsListView.GetSelectedIndex();
if (nItem != -1) int id = -1;
if (m_bFiltering)
{ {
int id = m_SymbolsListView.GetItemData(nItem); id = m_FilteredSymbols[nItem].m_Id;
m_Debugger->SymbolTable()->RemoveSymbolById(id); }
m_Debugger->SymbolTable()->Save(); else
{
CSymbol symbol;
m_SymbolTable->GetSymbolByIndex(nItem, &symbol);
id = symbol.m_Id;
}
if (id != -1)
{
m_SymbolTable->RemoveSymbolById(id);
m_SymbolTable->Save();
Refresh(); 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;
{
return;
}
m_SymbolsListView.SetRedraw(FALSE);
m_SymbolsListView.DeleteAllItems();
int index = plvdi->item.iItem;
if (index == -1)
{
return 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;
}
LRESULT CDebugSymbols::OnListCacheHint(NMHDR * pNMHDR)
{
NMLVCACHEHINT* plvch = (NMLVCACHEHINT*)pNMHDR;
if (m_bFiltering)
{
return 0;
}
m_SymbolCacheStartIndex = plvch->iFrom;
m_SymbolCache.clear();
for (int index = plvch->iFrom; index <= plvch->iTo; index++)
{
CSymbol symbol; CSymbol symbol;
int nItem = 0; if (!m_SymbolTable->GetSymbolByIndex(index, &symbol))
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);
}
void CDebugSymbols::RefreshValues()
{
if (g_MMU == nullptr)
{
return;
}
int count = m_SymbolsListView.GetItemCount();
CSymbol symbol;
for (int i = 0; i < count; i++)
{
int symbolId = m_SymbolsListView.GetItemData(i);
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;
}

View File

@ -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,37 +17,80 @@ 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 OnFilterChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnListDblClicked(NMHDR* pNMHDR); 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)

View File

@ -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);
} }

View File

@ -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')
{ {
@ -235,6 +237,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);
if (bSortAfter)
{
sort(m_Symbols.begin(), m_Symbols.end(), CmpSymbolAddresses); 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,31 +455,16 @@ 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_AddressMap.count(address) == 0)
{ {
if (m_Symbols[i].m_Address == address)
{
*symbol = m_Symbols[i];
return true;
}
}
return false; return false;
} }
bool CSymbolTable::GetSymbolByOverlappedAddress(uint32_t address, CSymbol* symbol) size_t index = m_AddressMap[address];
{ *symbol = m_Symbols[index];
CGuard guard(m_CS);
for (size_t i = 0; i < m_Symbols.size(); i++)
{
if (address >= m_Symbols[i].m_Address &&
address < m_Symbols[i].m_Address + m_Symbols[i].TypeSize())
{
*symbol = m_Symbols[i];
return true; return true;
} }
}
return false;
}
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;
} }

View File

@ -49,6 +49,7 @@ 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;
@ -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);
}; };

View File

@ -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