1935 lines
62 KiB
C#
1935 lines
62 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using System.Configuration;
|
|
using System.Collections.Specialized;
|
|
using static System.Int32;
|
|
using static System.Windows.Forms.AxHost;
|
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;
|
|
|
|
namespace CruncherSharp
|
|
{
|
|
public partial class CruncherSharpForm : Form
|
|
{
|
|
public enum SearchType
|
|
{
|
|
None,
|
|
UnusedVTables,
|
|
MSVCExtraPadding,
|
|
MSVCEmptyBaseClass,
|
|
UnusedInterfaces,
|
|
UnusedVirtual,
|
|
MaskingFunction,
|
|
RemovedInline,
|
|
}
|
|
|
|
private readonly List<string> _FunctionsToIgnore;
|
|
private readonly Stack<SymbolInfo> _NavigationStack;
|
|
private readonly Stack<SymbolInfo> _RedoNavigationStack;
|
|
private SymbolAnalyzer _SymbolAnalyzerDia;
|
|
#if RAWPDB
|
|
private SymbolAnalyzer _SymbolAnalyzerRawPDB;
|
|
#endif
|
|
private readonly DataTable _Table;
|
|
public bool _CloseRequested = false;
|
|
public bool _HasInstancesCount = false;
|
|
public bool _HasSecondPDB = false;
|
|
public bool _HasMemPools = false;
|
|
public bool _IgnoreSelectionChange = false;
|
|
public bool _RestrictToSymbolsImportedFromCSV = false;
|
|
private ulong _PrefetchStartOffset = 0;
|
|
private SearchType _SearchCategory = SearchType.None;
|
|
|
|
private SymbolInfo _SelectedSymbol;
|
|
|
|
private Timer _TypingTimer;
|
|
|
|
private SymbolAnalyzer CurrentSymbolAnalyzer
|
|
{
|
|
get
|
|
{
|
|
#if RAWPDB
|
|
return useRawPDBToolStripMenuItem.Checked ? _SymbolAnalyzerRawPDB : _SymbolAnalyzerDia;
|
|
#else
|
|
return _SymbolAnalyzerDia;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public CruncherSharpForm()
|
|
{
|
|
InitializeComponent();
|
|
|
|
_SymbolAnalyzerDia = new SymbolAnalyzerDIA();
|
|
#if RAWPDB
|
|
_SymbolAnalyzerRawPDB = new SymbolAnalyzerRawPDB();
|
|
#endif
|
|
_Table = CreateDataTable();
|
|
_Table.CaseSensitive = checkBoxMatchCase.Checked;
|
|
_NavigationStack = new Stack<SymbolInfo>();
|
|
_RedoNavigationStack = new Stack<SymbolInfo>();
|
|
_FunctionsToIgnore = new List<string>();
|
|
_SelectedSymbol = null;
|
|
bindingSourceSymbols.DataSource = _Table;
|
|
dataGridSymbols.DataSource = bindingSourceSymbols;
|
|
|
|
dataGridSymbols.Columns[0].Width = 275;
|
|
for (int i = 1; i < dataGridSymbols.Columns.Count; i++)
|
|
{
|
|
dataGridSymbols.Columns[i].Width = 75;
|
|
}
|
|
UpdateColumnVisibility();
|
|
|
|
WindowState = FormWindowState.Maximized;
|
|
|
|
string SymbolAnalyzer = ConfigurationManager.AppSettings.Get("SymbolAnalyzer");
|
|
useRawPDBToolStripMenuItem.Checked = SymbolAnalyzer == "RawPDB";
|
|
if (ShowMemPool("MB2"))
|
|
{
|
|
mB2ToolStripMenuItem.Checked = true;
|
|
}
|
|
|
|
NameValueCollection alignmentSection = (NameValueCollection)ConfigurationManager.GetSection("Alignment");
|
|
if (alignmentSection != null)
|
|
{
|
|
foreach (string Key in alignmentSection.AllKeys)
|
|
{
|
|
uint align = uint.Parse(alignmentSection.Get(Key));
|
|
CurrentSymbolAnalyzer.ConfigAlignment.Add(Key, align);
|
|
}
|
|
}
|
|
NameValueCollection enumSection = (NameValueCollection)ConfigurationManager.GetSection("Enums");
|
|
if (enumSection != null)
|
|
{
|
|
foreach (string Key in enumSection.AllKeys)
|
|
{
|
|
uint align = uint.Parse(enumSection.Get(Key));
|
|
CurrentSymbolAnalyzer.ConfigEnum.Add(Key, align);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnCreateControl() => OpenPDB();
|
|
|
|
public SearchType SearchCategory
|
|
{
|
|
get => _SearchCategory;
|
|
private set
|
|
{
|
|
_SearchCategory = value;
|
|
UpdateCheckedOption();
|
|
}
|
|
}
|
|
|
|
private void Reset()
|
|
{
|
|
checkedListBoxNamespaces.Items.Clear();
|
|
_Table.Clear();
|
|
dataGridViewSymbolInfo.Rows.Clear();
|
|
dataGridViewFunctionsInfo.Rows.Clear();
|
|
_SelectedSymbol = null;
|
|
_RestrictToSymbolsImportedFromCSV = false;
|
|
labelCurrentSymbol.Text = "";
|
|
_SymbolAnalyzerDia.Reset();
|
|
#if RAWPDB
|
|
_SymbolAnalyzerRawPDB.Reset();
|
|
#endif
|
|
UpdateBtnLoadText();
|
|
}
|
|
|
|
private void UpdateBtnLoadText()
|
|
{
|
|
if (textBoxFilter.Text.Length > 0)
|
|
btnLoad.Text = "Load filtered symbols";
|
|
else
|
|
btnLoad.Text = "Load all symbols";
|
|
}
|
|
|
|
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
private void loadPDBToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (loadPDBBackgroundWorker.IsBusy || loadCSVBackgroundWorker.IsBusy)
|
|
return;
|
|
|
|
OpenPDB();
|
|
}
|
|
|
|
private void OpenPDB()
|
|
{
|
|
if (openPdbDialog.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
|
|
Reset();
|
|
|
|
_SymbolAnalyzerDia.FileName = openPdbDialog.FileName;
|
|
#if RAWPDB
|
|
_SymbolAnalyzerRawPDB.FileName = openPdbDialog.FileName;
|
|
_SymbolAnalyzerRawPDB.OpenAsync(openPdbDialog.FileName);
|
|
#endif
|
|
Text = "Cruncher# - " + openPdbDialog.FileName;
|
|
|
|
btnLoad.Enabled = true;
|
|
btnReset.Enabled = true;
|
|
loadInstanceCountToolStripMenuItem.Enabled = true;
|
|
textBoxFilter.Focus();
|
|
}
|
|
|
|
public void LoadPdb(string fileName, bool secondPDB)
|
|
{
|
|
_SelectedSymbol = null;
|
|
toolStripProgressBar.Value = 0;
|
|
toolStripStatusLabel.Text = "Loading PDB...";
|
|
if (!secondPDB)
|
|
{
|
|
Text = "Cruncher# - " + fileName;
|
|
if (textBoxFilter.Text.Length > 0)
|
|
Text += " Filter: " + textBoxFilter.Text;
|
|
}
|
|
|
|
var task = new LoadPDBTask
|
|
{
|
|
FileName = fileName,
|
|
SecondPDB = secondPDB,
|
|
Filter = textBoxFilter.Text,
|
|
MatchCase = checkBoxMatchCase.Checked,
|
|
WholeExpression = checkBoxMatchWholeExpression.Checked,
|
|
UseRegularExpression = checkBoxRegularExpressions.Checked,
|
|
UseProgressBar = String.IsNullOrEmpty(textBoxFilter.Text) || !checkBoxMatchWholeExpression.Checked
|
|
};
|
|
loadPDBBackgroundWorker.RunWorkerAsync(task);
|
|
}
|
|
|
|
private static string SymbolRowName = "Symbol";
|
|
private static string SizeRowName = "Size";
|
|
private static string MinAlignmentRowName = "Min alignment";
|
|
private static string PaddingRowName = "Padding";
|
|
private static string PaddingZonesRowName = "Padding zones";
|
|
private static string TotalPaddingRowName = "Total padding";
|
|
private static string PotentialSavingRowName = "Potential saving";
|
|
private static string TotalDeltaRowName = "Total delta";
|
|
private static string InstancesRowName = "Instances";
|
|
private static string TotalCountRowName = "Total count";
|
|
private static string TotalSizeRowName = "Total size";
|
|
private static string TotalWasteRowName = "Total waste";
|
|
private static string MempoolUsageRowName = "Mempool usage";
|
|
private static string MempoolTotalUsageRowName = "Mempool total usage";
|
|
private static string MempoolRowName = "Current mempool";
|
|
private static string MempoolDeltaRowName = "Delta to lower mempool";
|
|
private static string PotentialWinRowName = "Potential total saving";
|
|
private static string NewSizeRowName = "New size";
|
|
private static string DeltaRowName = "Delta";
|
|
|
|
private DataTable CreateDataTable()
|
|
{
|
|
var table = new DataTable("Symbols");
|
|
table.Columns.Add(new DataColumn {ColumnName = SymbolRowName, ReadOnly = true});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = SizeRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = MinAlignmentRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = PaddingRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = PaddingZonesRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = TotalPaddingRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = PotentialSavingRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = MempoolRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = MempoolDeltaRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = InstancesRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt64")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = TotalCountRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt64")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = TotalSizeRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt64")
|
|
});
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = TotalWasteRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt64")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = MempoolUsageRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = MempoolTotalUsageRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = PotentialWinRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt64")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = NewSizeRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.UInt32")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = DeltaRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.Int32")
|
|
});
|
|
|
|
table.Columns.Add(new DataColumn
|
|
{
|
|
ColumnName = TotalDeltaRowName,
|
|
ReadOnly = true,
|
|
DataType = Type.GetType("System.Int64")
|
|
});
|
|
|
|
|
|
return table;
|
|
}
|
|
|
|
void UpdateColumnVisibility()
|
|
{
|
|
dataGridSymbols.Columns[NewSizeRowName].Visible = _HasSecondPDB;
|
|
dataGridSymbols.Columns[DeltaRowName].Visible = _HasSecondPDB;
|
|
dataGridSymbols.Columns[TotalDeltaRowName].Visible = _HasSecondPDB;
|
|
|
|
dataGridSymbols.Columns[InstancesRowName].Visible = _HasInstancesCount;
|
|
dataGridSymbols.Columns[TotalCountRowName].Visible = _HasInstancesCount;
|
|
dataGridSymbols.Columns[TotalSizeRowName].Visible = _HasInstancesCount && !_HasMemPools;
|
|
dataGridSymbols.Columns[TotalWasteRowName].Visible = _HasInstancesCount && !_HasMemPools;
|
|
dataGridSymbols.Columns[MempoolUsageRowName].Visible = _HasInstancesCount && _HasMemPools;
|
|
dataGridSymbols.Columns[MempoolTotalUsageRowName].Visible = _HasInstancesCount && _HasMemPools;
|
|
|
|
dataGridSymbols.Columns[PotentialWinRowName].Visible = _HasInstancesCount && _HasMemPools;
|
|
}
|
|
|
|
private void AddInstancesCount()
|
|
{
|
|
_HasInstancesCount = true;
|
|
UpdateColumnVisibility();
|
|
|
|
}
|
|
|
|
private void AddSecondPDB()
|
|
{
|
|
|
|
_HasSecondPDB = true;
|
|
UpdateColumnVisibility();
|
|
}
|
|
|
|
private void AddSymbolToTable(SymbolInfo symbolInfo)
|
|
{
|
|
var row = _Table.NewRow();
|
|
|
|
row[SymbolRowName] = symbolInfo.Name;
|
|
row[SizeRowName] = symbolInfo.Size;
|
|
row[PaddingRowName] = symbolInfo.Padding;
|
|
row[MinAlignmentRowName] = symbolInfo.MinAlignment.Value;
|
|
row[PaddingZonesRowName] = symbolInfo.PaddingZonesCount;
|
|
row[TotalPaddingRowName] = symbolInfo.TotalPadding.Value;
|
|
row[PotentialSavingRowName] = symbolInfo.PotentialSaving.Value;
|
|
row[InstancesRowName] = symbolInfo.NumInstances;
|
|
row[TotalCountRowName] = symbolInfo.TotalCount;
|
|
row[TotalSizeRowName] = symbolInfo.TotalCount * symbolInfo.Size;
|
|
row[TotalWasteRowName] = symbolInfo.TotalCount * symbolInfo.PotentialSaving;
|
|
if (_HasSecondPDB && symbolInfo.NewSize != null)
|
|
{
|
|
row[NewSizeRowName] = symbolInfo.NewSize;
|
|
row[DeltaRowName] = (long)symbolInfo.NewSize - (long)symbolInfo.Size;
|
|
}
|
|
|
|
if (_HasInstancesCount && symbolInfo.NumInstances > 0)
|
|
{
|
|
if (_HasMemPools)
|
|
{
|
|
row[TotalDeltaRowName] = symbolInfo.ComputeTotalMempoolDelta();
|
|
}
|
|
else
|
|
{
|
|
row[TotalDeltaRowName] = symbolInfo.ComputeTotalDelta();
|
|
}
|
|
}
|
|
else if (_HasInstancesCount)
|
|
{
|
|
row[TotalDeltaRowName] = 0;
|
|
}
|
|
|
|
if (_HasMemPools && symbolInfo.CurrentMemPool > 0)
|
|
{
|
|
row[MempoolRowName] = symbolInfo.CurrentMemPool;
|
|
row[MempoolDeltaRowName] = symbolInfo.Size - symbolInfo.LowerMemPool;
|
|
|
|
row[MempoolUsageRowName] = (long)(symbolInfo.CurrentMemPool) * (long)symbolInfo.NumInstances;
|
|
row[MempoolTotalUsageRowName] = (long)(symbolInfo.ComputeTotalMempoolUsage());
|
|
row[PotentialWinRowName] = (long)(symbolInfo.ComputePotentialTotalSaving());
|
|
}
|
|
|
|
_Table.Rows.Add(row);
|
|
}
|
|
|
|
|
|
private ulong GetCacheLineSize()
|
|
{
|
|
return Convert.ToUInt32(textBoxCache.Text);
|
|
}
|
|
|
|
private SymbolInfo FindSelectedSymbolInfo()
|
|
{
|
|
if (dataGridSymbols.SelectedRows.Count == 0) return null;
|
|
|
|
var selectedRow = dataGridSymbols.SelectedRows[0];
|
|
var symbolName = selectedRow.Cells[0].Value.ToString();
|
|
return CurrentSymbolAnalyzer.FindSymbolInfo(symbolName);
|
|
}
|
|
|
|
private string GetFilterString()
|
|
{
|
|
if (checkBoxSubclasses.Checked || checkBoxMember.Checked)
|
|
return null;
|
|
|
|
var filters = new List<string>();
|
|
if (textBoxFilter.Text.Length > 0)
|
|
if (checkBoxMatchWholeExpression.Checked)
|
|
filters.Add($"Symbol = '{textBoxFilter.Text.Replace("'", string.Empty)}'");
|
|
else if (checkBoxRegularExpressions.Checked)
|
|
filters.Add($"Symbol LIKE '{textBoxFilter.Text.Replace("'", string.Empty)}'");
|
|
else
|
|
filters.Add($"Symbol LIKE '*{textBoxFilter.Text.Replace("'", string.Empty)}*'");
|
|
if (!chkShowTemplates.Checked)
|
|
filters.Add("Symbol NOT LIKE '*<*'");
|
|
if (checkedListBoxNamespaces.CheckedItems.Count > 0)
|
|
{
|
|
var namespaceFilters = checkedListBoxNamespaces.CheckedItems.Cast<string>()
|
|
.Select(item => $"Symbol LIKE '*{item.Replace("'", string.Empty)}::*'");
|
|
filters.Add($"({string.Join(" OR ", namespaceFilters)})");
|
|
}
|
|
|
|
return string.Join(" AND ", filters);
|
|
}
|
|
|
|
|
|
private void UpdateFilter()
|
|
{
|
|
_Table.CaseSensitive = checkBoxMatchCase.Checked;
|
|
try
|
|
{
|
|
bindingSourceSymbols.Filter = GetFilterString();
|
|
textBoxFilter.BackColor = Color.Empty;
|
|
textBoxFilter.ForeColor = Color.Empty;
|
|
}
|
|
catch (EvaluateException)
|
|
{
|
|
textBoxFilter.BackColor = Color.Red;
|
|
textBoxFilter.ForeColor = Color.White;
|
|
}
|
|
}
|
|
|
|
private void dataGridSymbols_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
if (_IgnoreSelectionChange)
|
|
return;
|
|
|
|
_PrefetchStartOffset = 0;
|
|
if (dataGridSymbols.SelectedRows.Count > 1)
|
|
ShowSelectionSummary();
|
|
else
|
|
ShowSelectedSymbolInfo();
|
|
}
|
|
|
|
private void dataGridSymbols_DerivedClassSelected(object sender, EventArgs e)
|
|
{
|
|
dataGridSymbols.ClearSelection();
|
|
if (TrySelectSymbol(sender.ToString()) == false)
|
|
{
|
|
var symbolInfo = CurrentSymbolAnalyzer.FindSymbolInfo(sender.ToString());
|
|
if (symbolInfo != null)
|
|
{
|
|
ShowSymbolInfo(symbolInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dataGridSymbols_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
_PrefetchStartOffset = 0;
|
|
ShowSelectedSymbolInfo();
|
|
}
|
|
|
|
private void ShowSelectionSummary()
|
|
{
|
|
dataGridViewSymbolInfo.Rows.Clear();
|
|
|
|
ulong totalMemory = 0;
|
|
ulong totalWaste = 0;
|
|
long totalDiff = 0;
|
|
foreach (DataGridViewRow selectedRow in dataGridSymbols.SelectedRows)
|
|
{
|
|
var symbolName = selectedRow.Cells[0].Value.ToString();
|
|
var symbolInfo = CurrentSymbolAnalyzer.FindSymbolInfo(symbolName);
|
|
|
|
if (_HasInstancesCount)
|
|
{
|
|
totalMemory += symbolInfo.NumInstances * symbolInfo.Size;
|
|
totalWaste += symbolInfo.NumInstances * symbolInfo.PotentialSaving.Value;
|
|
if (_HasSecondPDB)
|
|
totalDiff += ((long) symbolInfo.NewSize - (long) symbolInfo.Size) *
|
|
(long) symbolInfo.NumInstances;
|
|
}
|
|
else
|
|
{
|
|
totalMemory += symbolInfo.Size;
|
|
totalWaste += symbolInfo.PotentialSaving.Value;
|
|
}
|
|
}
|
|
|
|
labelCurrentSymbol.Text = "Total memory: " + totalMemory + " total waste: " + totalWaste;
|
|
if (_HasInstancesCount && _HasSecondPDB)
|
|
labelCurrentSymbol.Text += " total diff: " + totalDiff;
|
|
}
|
|
|
|
private void ShowSelectedSymbolInfo()
|
|
{
|
|
dataGridViewSymbolInfo.Rows.Clear();
|
|
var info = FindSelectedSymbolInfo();
|
|
if (info != null)
|
|
{
|
|
ShowSymbolInfo(info);
|
|
}
|
|
}
|
|
|
|
private bool TrySelectSymbol(string name, bool ShowSelection = true)
|
|
{
|
|
foreach (DataGridViewRow dr in dataGridSymbols.Rows)
|
|
{
|
|
var dc = dr.Cells[0]; // name
|
|
if (!dc.Value.ToString().Equals(name))
|
|
continue;
|
|
_IgnoreSelectionChange = !ShowSelection;
|
|
dataGridSymbols.CurrentCell = dc;
|
|
_IgnoreSelectionChange = false;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void ShowSymbolInfo(SymbolInfo info)
|
|
{
|
|
if (_SelectedSymbol != info)
|
|
{
|
|
labelCurrentSymbol.Text = info.Name;
|
|
|
|
if (_SelectedSymbol != null)
|
|
{
|
|
_NavigationStack.Push(_SelectedSymbol);
|
|
}
|
|
_RedoNavigationStack.Clear();
|
|
|
|
_SelectedSymbol = info;
|
|
}
|
|
|
|
UpdateSymbolGrid();
|
|
}
|
|
|
|
private void ShowPreviousSymbolInfo()
|
|
{
|
|
if (_NavigationStack.Count == 0)
|
|
return;
|
|
if (_SelectedSymbol != null)
|
|
{
|
|
_RedoNavigationStack.Push(_SelectedSymbol);
|
|
}
|
|
_SelectedSymbol = _NavigationStack.Pop();
|
|
labelCurrentSymbol.Text = _SelectedSymbol.Name;
|
|
UpdateSymbolGrid();
|
|
|
|
TrySelectSymbol(labelCurrentSymbol.Text, false);
|
|
}
|
|
|
|
private void ShowNextSymbolInfo()
|
|
{
|
|
if (_RedoNavigationStack.Count == 0)
|
|
return;
|
|
if (_SelectedSymbol != null)
|
|
{
|
|
_NavigationStack.Push(_SelectedSymbol);
|
|
}
|
|
_SelectedSymbol = _RedoNavigationStack.Pop();
|
|
labelCurrentSymbol.Text = _SelectedSymbol.Name;
|
|
UpdateSymbolGrid();
|
|
|
|
TrySelectSymbol(labelCurrentSymbol.Text, false);
|
|
}
|
|
|
|
private void UpdateSymbolGrid()
|
|
{
|
|
dataGridViewSymbolInfo.Rows.Clear();
|
|
dataGridViewFunctionsInfo.Rows.Clear();
|
|
|
|
var prevCacheBoundaryOffset = _PrefetchStartOffset;
|
|
|
|
if (_SelectedSymbol != null)
|
|
{
|
|
if (prevCacheBoundaryOffset > _SelectedSymbol.Size)
|
|
prevCacheBoundaryOffset = _SelectedSymbol.Size;
|
|
|
|
ulong numCacheLines = 0;
|
|
var increment = 0;
|
|
|
|
AddSymbolToGrid(_SelectedSymbol, ref prevCacheBoundaryOffset, ref numCacheLines, 0, increment);
|
|
}
|
|
}
|
|
|
|
private void RefreshSymbolGrid(int rowIndex)
|
|
{
|
|
var firstRow = dataGridViewSymbolInfo.FirstDisplayedScrollingRowIndex;
|
|
UpdateSymbolGrid();
|
|
if (rowIndex < dataGridViewSymbolInfo.Rows.Count)
|
|
{
|
|
dataGridViewSymbolInfo.Rows[rowIndex].Selected = true;
|
|
dataGridViewSymbolInfo.FirstDisplayedScrollingRowIndex = firstRow;
|
|
}
|
|
}
|
|
|
|
private void AddSymbolToGrid(SymbolInfo symbol, ref ulong prevCacheBoundaryOffset, ref ulong numCacheLines,
|
|
ulong previousOffset, int increment)
|
|
{
|
|
var cacheLineSize = GetCacheLineSize();
|
|
|
|
var incrementText = "";
|
|
var incrementTextEmpty = "";
|
|
|
|
var whitespaceIncrementText = "";
|
|
for (var i = 0; i < increment; i++)
|
|
{
|
|
whitespaceIncrementText += " ";
|
|
if (i == increment - 1)
|
|
incrementText += " |__ ";
|
|
else
|
|
incrementText += " | ";
|
|
incrementTextEmpty += " | ";
|
|
}
|
|
|
|
foreach (var member in symbol.Members)
|
|
{
|
|
var currentOffset = previousOffset + member.Offset;
|
|
if (member.PaddingBefore > 0 && checkBoxPadding.Checked)
|
|
{
|
|
var paddingOffset = member.Offset - member.PaddingBefore;
|
|
string[] paddingRow =
|
|
{
|
|
string.Empty,
|
|
incrementTextEmpty,
|
|
PaddingRowName,
|
|
paddingOffset.ToString(),
|
|
string.Empty,
|
|
member.PaddingBefore.ToString(),
|
|
string.Empty,
|
|
string.Empty,
|
|
member.PaddingBefore.ToString()
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(paddingRow);
|
|
}
|
|
|
|
if (checkBoxCacheLines.Checked)
|
|
{
|
|
var cacheLines = new List<ulong>();
|
|
while (currentOffset >= cacheLineSize + prevCacheBoundaryOffset)
|
|
{
|
|
numCacheLines++;
|
|
var cacheLineOffset = numCacheLines * cacheLineSize + _PrefetchStartOffset;
|
|
cacheLines.Add(cacheLineOffset);
|
|
prevCacheBoundaryOffset = cacheLineOffset;
|
|
}
|
|
|
|
if (cacheLines.Count > 3 && checkBoxSmartCacheLines.Checked)
|
|
{
|
|
string[] firstBoundaryRow =
|
|
{
|
|
string.Empty, incrementTextEmpty, "Cacheline boundary", cacheLines[0].ToString(),
|
|
string.Empty, string.Empty, string.Empty
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(firstBoundaryRow);
|
|
string[] middleBoundariesRow =
|
|
{
|
|
string.Empty, incrementTextEmpty, "Cacheline boundaries (...)", string.Empty,
|
|
string.Empty, string.Empty, string.Empty
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(middleBoundariesRow);
|
|
string[] lastBoundaryRow =
|
|
{
|
|
string.Empty, incrementTextEmpty, "Cacheline boundary",
|
|
cacheLines[cacheLines.Count - 1].ToString(), string.Empty, string.Empty, string.Empty
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(lastBoundaryRow);
|
|
}
|
|
else
|
|
{
|
|
cacheLines.ForEach(offset =>
|
|
{
|
|
string[] boundaryRow =
|
|
{
|
|
string.Empty,
|
|
incrementTextEmpty,
|
|
"Cacheline boundary",
|
|
offset.ToString()
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(boundaryRow);
|
|
});
|
|
}
|
|
}
|
|
|
|
var expand = "";
|
|
if (member.Expanded)
|
|
expand = whitespaceIncrementText + "- ";
|
|
else if (member.IsExapandable)
|
|
expand = whitespaceIncrementText + "+ ";
|
|
|
|
string PotentialSaving = string.Empty;
|
|
if (member.PotentialSaving.HasValue)
|
|
{
|
|
PotentialSaving = member.PotentialSaving.ToString();
|
|
}
|
|
else if (member.Category == SymbolMemberInfo.MemberCategory.VTable && symbol.HasUnusedVTable())
|
|
{
|
|
PotentialSaving = "8";
|
|
}
|
|
else if (member.TypeInfo != null && member.TypeInfo.PotentialSaving != null && member.TypeInfo.PotentialSaving.Value > 0)
|
|
{
|
|
PotentialSaving = member.TypeInfo.PotentialSaving.Value.ToString();
|
|
}
|
|
|
|
object[] row =
|
|
{
|
|
expand,
|
|
incrementText + member.DisplayName,
|
|
member.TypeName,
|
|
currentOffset.ToString(),
|
|
(member.BitField ? member.BitPosition.ToString() : string.Empty),
|
|
member.BitField ? (member.BitSize.ToString() + (member.BitSize == 1 ? " bit" : " bits")) : (member.Size.ToString() + (member.Size == 1 ? " byte" : " bytes")),
|
|
member.MinAlignment.ToString(),
|
|
member.TypeInfo?.Padding.ToString() ?? "0",
|
|
PotentialSaving
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(row);
|
|
dataGridViewSymbolInfo.Rows[dataGridViewSymbolInfo.Rows.Count - 1].Tag = member;
|
|
|
|
if (member.Expanded && member.TypeInfo != null)
|
|
AddSymbolToGrid(member.TypeInfo, ref prevCacheBoundaryOffset, ref numCacheLines, currentOffset,
|
|
increment + 1);
|
|
|
|
if (member.BitField && member.BitPaddingAfter > 0 && checkBoxBitPadding.Checked)
|
|
{
|
|
var paddingOffset = member.BitPaddingAfter.ToString() + " bits";
|
|
string[] paddingRow =
|
|
{
|
|
string.Empty,
|
|
incrementTextEmpty,
|
|
"Bitfield padding",
|
|
currentOffset.ToString(),
|
|
(member.BitPosition + member.BitSize).ToString(),
|
|
paddingOffset
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(paddingRow);
|
|
}
|
|
}
|
|
|
|
// Final structure padding.
|
|
if (symbol.EndPadding > 0 && checkBoxPadding.Checked)
|
|
{
|
|
var endPaddingOffset = symbol.Size - symbol.EndPadding;
|
|
string[] paddingRow =
|
|
{
|
|
string.Empty,
|
|
string.Empty,
|
|
PaddingRowName,
|
|
endPaddingOffset.ToString(),
|
|
string.Empty,
|
|
symbol.EndPadding.ToString(),
|
|
string.Empty,
|
|
string.Empty,
|
|
symbol.EndPadding.ToString()
|
|
};
|
|
dataGridViewSymbolInfo.Rows.Add(paddingRow);
|
|
}
|
|
|
|
if (symbol.Functions != null)
|
|
{
|
|
foreach (var function in symbol.Functions)
|
|
{
|
|
object[] row =
|
|
{
|
|
function.DisplayName, function.Virtual, function.IsPure, function.IsOverride, function.IsOverloaded,
|
|
function.IsMasking
|
|
};
|
|
dataGridViewFunctionsInfo.Rows.Add(row);
|
|
dataGridViewFunctionsInfo.Rows[dataGridViewFunctionsInfo.Rows.Count - 1].Tag = function;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dataGridSymbols_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
|
|
{
|
|
if (e.Column.Index > 0)
|
|
{
|
|
e.Handled = true;
|
|
TryParse(e.CellValue1.ToString(), out var val1);
|
|
TryParse(e.CellValue2.ToString(), out var val2);
|
|
e.SortResult = val1 - val2;
|
|
}
|
|
}
|
|
|
|
private void dataGridViewSymbolInfo_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
var row = dataGridViewSymbolInfo.Rows[e.RowIndex];
|
|
var nameCell = row.Cells[2];
|
|
|
|
if (row.Tag is SymbolMemberInfo info)
|
|
{
|
|
if (info.Category == SymbolMemberInfo.MemberCategory.VTable)
|
|
e.CellStyle.BackColor = Color.LemonChiffon;
|
|
else if (info.IsBase)
|
|
e.CellStyle.BackColor = Color.LightGreen;
|
|
else if (info.BitField)
|
|
{
|
|
if (e.ColumnIndex == 3 ) // Offset column
|
|
{
|
|
e.CellStyle.BackColor = Color.FromArgb((int)((info.Offset * 37) % 256), 192, 192); // random color not too dark
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Bitfield";
|
|
|
|
}
|
|
}
|
|
else if (info.AlignWithPrevious)
|
|
{
|
|
if (e.ColumnIndex == 3) // Offset column
|
|
{
|
|
e.CellStyle.BackColor = Color.Salmon;
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Aligned with previous";
|
|
}
|
|
}
|
|
else if (checkBoxCacheLines.Checked && checkBoxShowOverlap.Checked)
|
|
{
|
|
var cacheLineSize = GetCacheLineSize();
|
|
var cacheOffset = (info.Offset - _PrefetchStartOffset) % cacheLineSize;
|
|
if (cacheOffset + info.Size > cacheLineSize)
|
|
{
|
|
e.CellStyle.BackColor = Color.LightYellow;
|
|
}
|
|
}
|
|
|
|
if (info.Volatile)
|
|
{
|
|
if (e.ColumnIndex == 0) // Name (Field) column
|
|
{
|
|
e.CellStyle.BackColor = Color.LightBlue;
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Volatile";
|
|
}
|
|
}
|
|
}
|
|
else if (nameCell.Value.ToString() == PaddingRowName)
|
|
{
|
|
e.CellStyle.BackColor = Color.LightPink;
|
|
if (e.ColumnIndex == 2)
|
|
e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
|
|
}
|
|
else if (nameCell.Value.ToString() == "Bitfield padding")
|
|
{
|
|
e.CellStyle.BackColor = Color.PaleVioletRed;
|
|
if (e.ColumnIndex == 2)
|
|
e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
|
|
}
|
|
else if (nameCell.Value.ToString().StartsWith("Cacheline"))
|
|
{
|
|
e.CellStyle.BackColor = Color.LightGray;
|
|
if (e.ColumnIndex == 2)
|
|
e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
|
|
}
|
|
}
|
|
|
|
private void textBoxFilter_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if (_TypingTimer == null)
|
|
{
|
|
_TypingTimer = new Timer();
|
|
_TypingTimer.Interval = 500;
|
|
_TypingTimer.Tick += new EventHandler(this.HandleTypingTimerTimeout);
|
|
}
|
|
_TypingTimer.Stop();
|
|
_TypingTimer.Start();
|
|
}
|
|
|
|
|
|
private void HandleTypingTimerTimeout(object sender, EventArgs e)
|
|
{
|
|
var timer = sender as Timer;
|
|
if (timer == null)
|
|
{
|
|
return;
|
|
}
|
|
timer.Stop();
|
|
|
|
if (checkBoxMember.Checked || checkBoxSubclasses.Checked)
|
|
PopulateDataTable();
|
|
else
|
|
UpdateFilter();
|
|
|
|
UpdateBtnLoadText();
|
|
}
|
|
|
|
private void textBoxFilter_KeyUp(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Return && !loadPDBBackgroundWorker.IsBusy && !loadCSVBackgroundWorker.IsBusy)
|
|
{
|
|
LoadPdb(CurrentSymbolAnalyzer.FileName, false);
|
|
btnLoad.Text = "Cancel";
|
|
}
|
|
}
|
|
|
|
private void copyTypeLayoutToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
var info = FindSelectedSymbolInfo();
|
|
if (info != null) Clipboard.SetText(info.ToString());
|
|
}
|
|
|
|
private void textBoxCache_KeyPress(object sender, KeyPressEventArgs e)
|
|
{
|
|
if (e.KeyChar == (char) Keys.Enter || e.KeyChar == (char) Keys.Escape)
|
|
ShowSelectedSymbolInfo();
|
|
OnKeyPress(e);
|
|
}
|
|
|
|
private void textBoxCache_Leave(object sender, EventArgs e)
|
|
{
|
|
ShowSelectedSymbolInfo();
|
|
}
|
|
|
|
private void setPrefetchStartOffsetToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (dataGridViewSymbolInfo.SelectedRows.Count != 0)
|
|
{
|
|
var selectedRow = dataGridViewSymbolInfo.SelectedRows[0];
|
|
ulong symbolOffset = Convert.ToUInt32(selectedRow.Cells[3].Value);
|
|
_PrefetchStartOffset = symbolOffset % GetCacheLineSize();
|
|
RefreshSymbolGrid(selectedRow.Index);
|
|
}
|
|
}
|
|
|
|
|
|
private void checkBoxCacheLines_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
checkBoxSmartCacheLines.Enabled = checkBoxCacheLines.Checked;
|
|
checkBoxShowOverlap.Enabled = checkBoxCacheLines.Checked;
|
|
textBoxCache.Enabled = checkBoxCacheLines.Checked;
|
|
labelCacheLine.Enabled = checkBoxCacheLines.Checked;
|
|
|
|
if (dataGridViewSymbolInfo.SelectedRows.Count != 0)
|
|
{
|
|
var selectedRow = dataGridViewSymbolInfo.SelectedRows[0];
|
|
RefreshSymbolGrid(selectedRow.Index);
|
|
}
|
|
else
|
|
{
|
|
RefreshSymbolGrid(0);
|
|
}
|
|
}
|
|
|
|
private void dataGridViewSymbolInfo_MouseClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Right)
|
|
{
|
|
var currentMouseOverRow = dataGridViewSymbolInfo.HitTest(e.X, e.Y).RowIndex;
|
|
if (currentMouseOverRow >= 0)
|
|
{
|
|
dataGridViewSymbolInfo.Rows[currentMouseOverRow].Selected = true;
|
|
contextMenuStripMembers.Show(dataGridViewSymbolInfo, new Point(e.X, e.Y));
|
|
}
|
|
}
|
|
else if (e.Button == MouseButtons.XButton1)
|
|
{
|
|
ShowPreviousSymbolInfo();
|
|
}
|
|
else if (e.Button == MouseButtons.XButton2)
|
|
{
|
|
ShowNextSymbolInfo();
|
|
}
|
|
}
|
|
|
|
private void dataGridViewSymbolInfo_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
var selectedRow = dataGridViewSymbolInfo.Rows[e.RowIndex];
|
|
var currentSymbolInfo = selectedRow.Tag as SymbolMemberInfo;
|
|
if (currentSymbolInfo != null && currentSymbolInfo.Category != SymbolMemberInfo.MemberCategory.Member)
|
|
{
|
|
var typeName = currentSymbolInfo.TypeName;
|
|
if (typeName.Contains("[")) typeName = typeName.Substring(0, typeName.IndexOf("["));
|
|
|
|
if (currentSymbolInfo.Category == SymbolMemberInfo.MemberCategory.Pointer)
|
|
{
|
|
if (typeName.Contains("*")) typeName = typeName.Substring(0, typeName.IndexOf("*"));
|
|
if (typeName.Contains("&")) typeName = typeName.Substring(0, typeName.IndexOf("&"));
|
|
}
|
|
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
var jumpToSymbolInfo = CurrentSymbolAnalyzer.FindSymbolInfo(typeName, true);
|
|
if (jumpToSymbolInfo != null)
|
|
{
|
|
if (e.ColumnIndex == 0)
|
|
{
|
|
if (currentSymbolInfo.IsExapandable)
|
|
{
|
|
currentSymbolInfo.Expanded = !currentSymbolInfo.Expanded;
|
|
RefreshSymbolGrid(e.RowIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ShowSymbolInfo(jumpToSymbolInfo);
|
|
TrySelectSymbol(typeName, false);
|
|
}
|
|
}
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
}
|
|
|
|
private void chkShowTemplates_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
UpdateFilter();
|
|
}
|
|
|
|
private void checkBoxSmartCacheLines_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
ShowSelectedSymbolInfo();
|
|
}
|
|
|
|
private void checkedListBoxNamespaces_ItemCheck(object sender, ItemCheckEventArgs e)
|
|
{
|
|
this.BeginInvoke(new Action(() =>
|
|
{
|
|
UpdateFilter();
|
|
}));
|
|
}
|
|
|
|
private void dataGridViewSymbolInfo_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Back)
|
|
{
|
|
ShowPreviousSymbolInfo();
|
|
}
|
|
if (e.KeyCode == Keys.Next)
|
|
{
|
|
ShowNextSymbolInfo();
|
|
}
|
|
|
|
OnKeyDown(e);
|
|
}
|
|
|
|
private void loadPDBBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
|
{
|
|
toolStripProgressBar.Value = e.ProgressPercentage;
|
|
toolStripStatusLabel.Text = e.UserState as String;
|
|
}
|
|
|
|
private void loadPDBBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
UpdateBtnLoadText();
|
|
|
|
if (e.Cancelled)
|
|
{
|
|
if (_CloseRequested)
|
|
{
|
|
Close();
|
|
}
|
|
else
|
|
{
|
|
toolStripStatusLabel.Text = "";
|
|
toolStripProgressBar.Value = 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
var loadPdbSuccess = (bool) e.Result;
|
|
|
|
if (!loadPdbSuccess)
|
|
{
|
|
MessageBox.Show(this, CurrentSymbolAnalyzer.LastError);
|
|
toolStripStatusLabel.Text = "Failed to load PDB.";
|
|
return;
|
|
}
|
|
|
|
OnPDBLoaded();
|
|
}
|
|
|
|
private void loadPDBBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
e.Result = CurrentSymbolAnalyzer.LoadPdb(sender, e);
|
|
}
|
|
|
|
|
|
private void loadCSVBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
|
{
|
|
toolStripProgressBar.Value = e.ProgressPercentage;
|
|
toolStripStatusLabel.Text = e.UserState as String;
|
|
}
|
|
|
|
private void loadCSVBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
UpdateBtnLoadText();
|
|
|
|
if (e.Cancelled)
|
|
{
|
|
if (_CloseRequested)
|
|
{
|
|
Close();
|
|
}
|
|
else
|
|
{
|
|
toolStripStatusLabel.Text = "";
|
|
toolStripProgressBar.Value = 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
var loadCSVSuccess = (bool)e.Result;
|
|
|
|
if (!loadCSVSuccess)
|
|
{
|
|
MessageBox.Show(this, CurrentSymbolAnalyzer.LastError);
|
|
toolStripStatusLabel.Text = "Failed to load CSV.";
|
|
return;
|
|
}
|
|
|
|
foreach (var symbol in CurrentSymbolAnalyzer.Symbols.Values)
|
|
if (symbol.NumInstances > 0)
|
|
symbol.UpdateTotalCount(symbol.NumInstances);
|
|
|
|
AddInstancesCount();
|
|
OnPDBLoaded();
|
|
}
|
|
|
|
private void loadCSVBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
e.Result = CurrentSymbolAnalyzer.LoadCSV(sender, e);
|
|
}
|
|
|
|
|
|
private void OnPDBLoaded()
|
|
{
|
|
compareWithPDBToolStripMenuItem.Enabled = true;
|
|
exportCsvToolStripMenuItem.Enabled = true;
|
|
findUnusedVtablesToolStripMenuItem.Enabled = true;
|
|
findMSVCExtraPaddingToolStripMenuItem.Enabled = true;
|
|
findMSVCEmptyBaseClassToolStripMenuItem.Enabled = true;
|
|
findUnusedInterfacesToolStripMenuItem.Enabled = true;
|
|
findUnusedVirtualToolStripMenuItem.Enabled = true;
|
|
findMaskingFunctionsToolStripMenuItem.Enabled = true;
|
|
findRemovedInlineToolStripMenuItem.Enabled = true;
|
|
|
|
// Temporarily clear the filter so, if current filter is invalid, we don't generate a ton of exceptions while populating the table
|
|
var preExistingFilter = textBoxFilter.Text;
|
|
textBoxFilter.Text = string.Empty;
|
|
|
|
PopulateDataTable();
|
|
|
|
checkedListBoxNamespaces.Items.Clear();
|
|
if (checkedListBoxNamespaces.Enabled)
|
|
{
|
|
foreach (var name in CurrentSymbolAnalyzer.RootNamespaces) checkedListBoxNamespaces.Items.Add(name);
|
|
}
|
|
|
|
// Sort by name by default (ascending)
|
|
dataGridSymbols.Sort(dataGridSymbols.Columns[0], ListSortDirection.Ascending);
|
|
bindingSourceSymbols.Filter = null; // "Symbol LIKE '*rde*'";
|
|
|
|
// Restore the filter now that the table is populated
|
|
textBoxFilter.Text = preExistingFilter;
|
|
UpdateFilter();
|
|
|
|
ShowSelectedSymbolInfo();
|
|
|
|
_NavigationStack.Clear();
|
|
}
|
|
|
|
private void loadInstanceCountToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (loadPDBBackgroundWorker.IsBusy || loadCSVBackgroundWorker.IsBusy)
|
|
return;
|
|
if (openCsvDialog.ShowDialog() == DialogResult.OK)
|
|
LoadCsv(openPdbDialog.FileName);
|
|
}
|
|
|
|
private void LoadCsv(string fileName)
|
|
{
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
|
|
if (_HasInstancesCount)
|
|
foreach (var symbol in CurrentSymbolAnalyzer.Symbols.Values)
|
|
{
|
|
symbol.NumInstances = 0;
|
|
symbol.TotalCount = 0;
|
|
}
|
|
|
|
using (var sourceStream =
|
|
File.Open(openCsvDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
{
|
|
List<LoadCSVTask> tasks = new List<LoadCSVTask>();
|
|
using (var reader = new StreamReader(sourceStream))
|
|
{
|
|
; while (!reader.EndOfStream)
|
|
{
|
|
var line = reader.ReadLine();
|
|
var values = line.Split(',');
|
|
var count = ulong.Parse(values[1]);
|
|
if (count > 0)
|
|
{
|
|
var task = new LoadCSVTask
|
|
{
|
|
ClassName = values[0],
|
|
Count = count
|
|
};
|
|
|
|
tasks.Add(task);
|
|
}
|
|
|
|
}
|
|
loadCSVBackgroundWorker.RunWorkerAsync(tasks);
|
|
btnLoad.Text = "Cancel";
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void compareWithPDBToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (loadPDBBackgroundWorker.IsBusy || loadCSVBackgroundWorker.IsBusy)
|
|
return;
|
|
if (openPdbDialog.ShowDialog() == DialogResult.OK)
|
|
{
|
|
AddSecondPDB();
|
|
LoadPdb(openPdbDialog.FileName, true);
|
|
if (_HasMemPools)
|
|
{
|
|
foreach (var symbolInfo in CurrentSymbolAnalyzer.Symbols.Values)
|
|
{
|
|
symbolInfo.SetNewMemPools(CurrentSymbolAnalyzer.MemPools);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void exportCsvToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (loadPDBBackgroundWorker.IsBusy || loadCSVBackgroundWorker.IsBusy)
|
|
return;
|
|
if (saveCsvDialog.ShowDialog() == DialogResult.OK)
|
|
using (var writer = new StreamWriter(saveCsvDialog.FileName))
|
|
{
|
|
writer.WriteLine(
|
|
"Name,Size,Padding,Padding zones,Total padding,Num Instances,Total size,Total waste,");
|
|
|
|
foreach (var symbolInfo in CurrentSymbolAnalyzer.Symbols.Values)
|
|
writer.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},", symbolInfo.Name, symbolInfo.Size,
|
|
symbolInfo.Padding, symbolInfo.PaddingZonesCount, symbolInfo.TotalPadding.Value,
|
|
symbolInfo.NumInstances, symbolInfo.NumInstances * symbolInfo.Size,
|
|
symbolInfo.NumInstances * symbolInfo.Padding);
|
|
}
|
|
}
|
|
|
|
private void CruncherSharpForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
if (loadCSVBackgroundWorker.IsBusy)
|
|
{
|
|
e.Cancel = true; // Can't close form while background worker is busy!
|
|
loadCSVBackgroundWorker.CancelAsync();
|
|
_CloseRequested = true;
|
|
}
|
|
if (loadPDBBackgroundWorker.IsBusy)
|
|
{
|
|
e.Cancel = true; // Can't close form while background worker is busy!
|
|
loadPDBBackgroundWorker.CancelAsync();
|
|
_CloseRequested = true;
|
|
}
|
|
|
|
}
|
|
|
|
private void findUnusedVtablesToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (SearchCategory == SearchType.UnusedVTables)
|
|
SearchCategory = SearchType.None;
|
|
else
|
|
SearchCategory = SearchType.UnusedVTables;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void Reset_Click(object sender, EventArgs e)
|
|
{
|
|
chkShowTemplates.Checked = false;
|
|
checkBoxSmartCacheLines.Checked = true;
|
|
checkBoxSubclasses.Checked = false;
|
|
checkBoxMember.Checked = false;
|
|
|
|
restrictToSymbolsImportedFroCSVToolStripMenuItem.Checked = false;
|
|
restrictToUObjectsToolStripMenuItem.Checked = false;
|
|
|
|
for (var i = 0; i < checkedListBoxNamespaces.Items.Count; i++)
|
|
checkedListBoxNamespaces.SetItemChecked(i, false);
|
|
|
|
textBoxFilter.Clear();
|
|
SearchCategory = SearchType.None;
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void findMSVCExtraPaddingToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (SearchCategory == SearchType.MSVCExtraPadding)
|
|
SearchCategory = SearchType.None;
|
|
else
|
|
SearchCategory = SearchType.MSVCExtraPadding;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void findMSVCEmptyBaseClassToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (SearchCategory == SearchType.MSVCEmptyBaseClass)
|
|
SearchCategory = SearchType.None;
|
|
else
|
|
SearchCategory = SearchType.MSVCEmptyBaseClass;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void findUnusedInterfacesToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (SearchCategory == SearchType.UnusedInterfaces)
|
|
SearchCategory = SearchType.None;
|
|
else
|
|
SearchCategory = SearchType.UnusedInterfaces;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void findUnusedVirtualToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (SearchCategory == SearchType.UnusedVirtual)
|
|
SearchCategory = SearchType.None;
|
|
else
|
|
SearchCategory = SearchType.UnusedVirtual;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void dataGridViewFunctionsInfo_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
var row = dataGridViewFunctionsInfo.Rows[e.RowIndex];
|
|
var info = row.Tag as SymbolFunctionInfo;
|
|
if (_FunctionsToIgnore.Contains(info.Name))
|
|
e.CellStyle.BackColor = Color.LightGray;
|
|
else
|
|
switch (info.Category)
|
|
{
|
|
case SymbolFunctionInfo.FunctionCategory.Constructor:
|
|
e.CellStyle.BackColor = Color.LightBlue;
|
|
break;
|
|
case SymbolFunctionInfo.FunctionCategory.Destructor:
|
|
e.CellStyle.BackColor = Color.LightGreen;
|
|
break;
|
|
case SymbolFunctionInfo.FunctionCategory.StaticFunction:
|
|
e.CellStyle.BackColor = Color.LightPink;
|
|
break;
|
|
default:
|
|
switch (SearchCategory)
|
|
{
|
|
case SearchType.UnusedVirtual:
|
|
if (info.UnusedVirtual) e.CellStyle.BackColor = Color.IndianRed;
|
|
|
|
break;
|
|
case SearchType.MaskingFunction:
|
|
if (info.IsMasking) e.CellStyle.BackColor = Color.IndianRed;
|
|
|
|
break;
|
|
case SearchType.RemovedInline:
|
|
if (info.WasInlineRemoved) e.CellStyle.BackColor = Color.IndianRed;
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void findMaskingFunctionsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (SearchCategory == SearchType.MaskingFunction)
|
|
SearchCategory = SearchType.None;
|
|
else
|
|
SearchCategory = SearchType.MaskingFunction;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void ignoreFunctionToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (dataGridViewFunctionsInfo.SelectedRows.Count != 0)
|
|
{
|
|
var selectedRow = dataGridViewFunctionsInfo.SelectedRows[0];
|
|
var info = selectedRow.Tag as SymbolFunctionInfo;
|
|
if (!_FunctionsToIgnore.Contains(info.Name))
|
|
{
|
|
_FunctionsToIgnore.Add(info.Name);
|
|
PopulateDataTable();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dataGridViewFunctionsInfo_MouseClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Right)
|
|
{
|
|
var currentMouseOverRow = dataGridViewFunctionsInfo.HitTest(e.X, e.Y).RowIndex;
|
|
if (currentMouseOverRow >= 0)
|
|
{
|
|
dataGridViewFunctionsInfo.Rows[currentMouseOverRow].Selected = true;
|
|
contextMenuStripFunctions.Show(dataGridViewFunctionsInfo, new Point(e.X, e.Y));
|
|
}
|
|
}
|
|
else if (e.Button == MouseButtons.XButton1)
|
|
{
|
|
ShowPreviousSymbolInfo();
|
|
}
|
|
else if (e.Button == MouseButtons.XButton2)
|
|
{
|
|
ShowNextSymbolInfo();
|
|
}
|
|
}
|
|
|
|
private void dataGridSymbols_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
var row = dataGridSymbols.Rows[e.RowIndex];
|
|
var column= dataGridSymbols.Columns[e.ColumnIndex];
|
|
|
|
var symbolName = row.Cells[0].Value.ToString();
|
|
SymbolInfo CurrentSymbol = CurrentSymbolAnalyzer.FindSymbolInfo(symbolName);
|
|
|
|
if (column.Name == InstancesRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Number of instances of this class";
|
|
}
|
|
else if (column.Name == TotalCountRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Number of instances of this class, including derived classes and aggregated objects";
|
|
}
|
|
else if (column.Name == PaddingRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Memory padding in this class";
|
|
}
|
|
else if (column.Name == TotalSizeRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Size of the object multiplied by total count";
|
|
}
|
|
else if (column.Name == TotalPaddingRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Memory padding in this class, including parent classes and aggregated objects";
|
|
}
|
|
else if (column.Name == MempoolUsageRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = String.Format("Number of instances multiplied by current memory pool ({0})", CurrentSymbol.CurrentMemPool);
|
|
}
|
|
else if (column.Name == MempoolTotalUsageRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = "Number of instances multiplied by current memory pool for current class and subclasses";
|
|
}
|
|
else if (column.Name == MempoolDeltaRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = String.Format("Delta with the lower memory pool ({0})", CurrentSymbol.LowerMemPool);
|
|
if (CurrentSymbol.Padding >= (CurrentSymbol.Size - CurrentSymbol.LowerMemPool))
|
|
{
|
|
row.Cells[e.ColumnIndex].Style.BackColor = Color.Green;
|
|
row.Cells[e.ColumnIndex].ToolTipText += "\nPadding is bigger than delta";
|
|
|
|
}
|
|
else if (CurrentSymbol.PotentialSaving >= (CurrentSymbol.Size - CurrentSymbol.LowerMemPool))
|
|
{
|
|
row.Cells[e.ColumnIndex].Style.BackColor = Color.LightGreen;
|
|
row.Cells[e.ColumnIndex].ToolTipText += "\nTotal padding is bigger than delta";
|
|
}
|
|
}
|
|
else if (column.Name == PotentialWinRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = String.Format("Memory saving with potential saving");
|
|
}
|
|
else if (column.Name == NewSizeRowName)
|
|
{
|
|
row.Cells[e.ColumnIndex].ToolTipText = String.Format("New memory pool ({0})", CurrentSymbol.NewMemPool);
|
|
}
|
|
}
|
|
|
|
|
|
private void dataGridSymbols_MouseClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Right)
|
|
{
|
|
var currentMouseOverRow = dataGridSymbols.HitTest(e.X, e.Y).RowIndex;
|
|
if (currentMouseOverRow >= 0)
|
|
{
|
|
foreach (DataGridViewRow selectedRow in dataGridSymbols.SelectedRows)
|
|
selectedRow.Selected = false;
|
|
dataGridSymbols.Rows[currentMouseOverRow].Selected = true;
|
|
|
|
toolStripMenuItemDerivedClasses.DropDownItems.Clear();
|
|
var info = FindSelectedSymbolInfo();
|
|
if (info != null)
|
|
{
|
|
if (info.DerivedClasses != null)
|
|
{
|
|
toolStripMenuItemDerivedClasses.Enabled = true;
|
|
foreach (var DerivedClass in info.DerivedClasses)
|
|
{
|
|
toolStripMenuItemDerivedClasses.DropDownItems.Add(DerivedClass.Name, null, dataGridSymbols_DerivedClassSelected);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
toolStripMenuItemDerivedClasses.Enabled = false;
|
|
}
|
|
|
|
ShowSymbolInfo(info);
|
|
}
|
|
|
|
contextMenuStripClassInfo.Show(dataGridSymbols, new Point(e.X, e.Y));
|
|
}
|
|
}
|
|
else if (e.Button == MouseButtons.XButton1)
|
|
{
|
|
ShowPreviousSymbolInfo();
|
|
}
|
|
else if (e.Button == MouseButtons.XButton2)
|
|
{
|
|
ShowNextSymbolInfo();
|
|
}
|
|
}
|
|
|
|
private void findRemovedInlineToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
SearchCategory = SearchType.RemovedInline;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void UpdateCheckedOption()
|
|
{
|
|
findUnusedVtablesToolStripMenuItem.Checked = SearchCategory == SearchType.UnusedVTables;
|
|
findUnusedVirtualToolStripMenuItem.Checked = SearchCategory == SearchType.UnusedVirtual;
|
|
findMSVCExtraPaddingToolStripMenuItem.Checked = SearchCategory == SearchType.MSVCExtraPadding;
|
|
findMSVCEmptyBaseClassToolStripMenuItem.Checked = SearchCategory == SearchType.MSVCEmptyBaseClass;
|
|
findUnusedInterfacesToolStripMenuItem.Checked = SearchCategory == SearchType.UnusedInterfaces;
|
|
findMaskingFunctionsToolStripMenuItem.Checked = SearchCategory == SearchType.MaskingFunction;
|
|
findRemovedInlineToolStripMenuItem.Checked = SearchCategory == SearchType.RemovedInline;
|
|
}
|
|
|
|
private void TryAddSymbolToTable(SymbolInfo symbolInfo)
|
|
{
|
|
if (restrictToSymbolsImportedFroCSVToolStripMenuItem.Checked && !symbolInfo.IsImportedFromCSV)
|
|
{
|
|
return;
|
|
}
|
|
if (restrictToUObjectsToolStripMenuItem.Checked && !symbolInfo.IsA("UObject", CurrentSymbolAnalyzer))
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (SearchCategory)
|
|
{
|
|
case SearchType.None:
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
case SearchType.UnusedVTables:
|
|
if (symbolInfo.HasUnusedVTable())
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
case SearchType.MSVCExtraPadding:
|
|
if (symbolInfo.HasMSVCExtraPadding())
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
case SearchType.MSVCEmptyBaseClass:
|
|
if (symbolInfo.HasMSVCEmptyBaseClass)
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
case SearchType.UnusedInterfaces:
|
|
if (symbolInfo.IsAbstract && symbolInfo.DerivedClasses == null)
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
case SearchType.UnusedVirtual:
|
|
if (symbolInfo.Functions == null)
|
|
break;
|
|
foreach (var function in symbolInfo.Functions)
|
|
if (function.UnusedVirtual)
|
|
if (!_FunctionsToIgnore.Contains(function.Name))
|
|
{
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
case SearchType.MaskingFunction:
|
|
if (symbolInfo.Functions == null)
|
|
break;
|
|
foreach (var function in symbolInfo.Functions)
|
|
if (function.IsMasking)
|
|
if (!_FunctionsToIgnore.Contains(function.Name))
|
|
{
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
case SearchType.RemovedInline:
|
|
if (symbolInfo.Functions == null)
|
|
break;
|
|
foreach (var function in symbolInfo.Functions)
|
|
if (function.WasInlineRemoved)
|
|
if (!_FunctionsToIgnore.Contains(function.Name))
|
|
{
|
|
AddSymbolToTable(symbolInfo);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void TryAddSubclassesToTable(SymbolInfo symbolInfo)
|
|
{
|
|
if (symbolInfo != null && symbolInfo.DerivedClasses != null)
|
|
{
|
|
foreach (SymbolInfo DerivedClassInfo in symbolInfo.DerivedClasses)
|
|
{
|
|
TryAddSymbolToTable(DerivedClassInfo);
|
|
TryAddSubclassesToTable(DerivedClassInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private void PopulateDataTable()
|
|
{
|
|
_Table.Rows.Clear();
|
|
|
|
_Table.BeginLoadData();
|
|
|
|
if (checkBoxSubclasses.Checked)
|
|
{
|
|
if (textBoxFilter.Text.Length > 0)
|
|
{
|
|
SymbolInfo ClassInfo = CurrentSymbolAnalyzer.FindSymbolInfo(textBoxFilter.Text);
|
|
if (ClassInfo != null)
|
|
{
|
|
TryAddSymbolToTable(ClassInfo);
|
|
TryAddSubclassesToTable(ClassInfo);
|
|
}
|
|
}
|
|
}
|
|
else if (checkBoxMember.Checked)
|
|
{
|
|
if (textBoxFilter.Text.Length > 0)
|
|
{
|
|
SymbolInfo ClassInfo = CurrentSymbolAnalyzer.FindSymbolInfo(textBoxFilter.Text);
|
|
if (ClassInfo != null)
|
|
{
|
|
foreach (SymbolInfo symbolInfo in CurrentSymbolAnalyzer.Symbols.Values)
|
|
{
|
|
bool foundMember = false;
|
|
foreach(SymbolMemberInfo member in symbolInfo.Members)
|
|
{
|
|
if (member.Category == SymbolMemberInfo.MemberCategory.Base)
|
|
{
|
|
continue;
|
|
}
|
|
if (member.TypeName != textBoxFilter.Text)
|
|
{
|
|
continue;
|
|
}
|
|
foundMember = true;
|
|
break;
|
|
}
|
|
if (foundMember)
|
|
TryAddSymbolToTable(symbolInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var symbolInfo in CurrentSymbolAnalyzer.Symbols.Values)
|
|
{
|
|
TryAddSymbolToTable(symbolInfo);
|
|
}
|
|
}
|
|
|
|
UpdateFilter();
|
|
|
|
_Table.EndLoadData();
|
|
}
|
|
|
|
private void btnLoad_Click(object sender, EventArgs e)
|
|
{
|
|
if (loadCSVBackgroundWorker.IsBusy)
|
|
{
|
|
loadCSVBackgroundWorker.CancelAsync();
|
|
toolStripStatusLabel.Text = "Canceling...";
|
|
}
|
|
else if (loadPDBBackgroundWorker.IsBusy)
|
|
{
|
|
loadPDBBackgroundWorker.CancelAsync();
|
|
toolStripStatusLabel.Text = "Canceling...";
|
|
}
|
|
else
|
|
{
|
|
LoadPdb(CurrentSymbolAnalyzer.FileName, false);
|
|
btnLoad.Text = "Cancel";
|
|
}
|
|
}
|
|
|
|
private void checkBoxMatchCase_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
UpdateFilter();
|
|
}
|
|
|
|
private void checkBoxMatchWholeExpression_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
UpdateFilter();
|
|
}
|
|
|
|
private void checkBoxRegularExpressions_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (checkBoxRegularExpressions.Checked)
|
|
{
|
|
checkBoxMatchWholeExpression.Checked = false;
|
|
checkBoxMatchWholeExpression.Enabled = false;
|
|
}
|
|
else
|
|
{
|
|
checkBoxMatchWholeExpression.Enabled = true;
|
|
}
|
|
|
|
UpdateFilter();
|
|
}
|
|
|
|
private void checkBoxPadding_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (dataGridViewSymbolInfo.SelectedRows.Count != 0)
|
|
{
|
|
var selectedRow = dataGridViewSymbolInfo.SelectedRows[0];
|
|
RefreshSymbolGrid(selectedRow.Index);
|
|
}
|
|
else
|
|
{
|
|
RefreshSymbolGrid(0);
|
|
}
|
|
}
|
|
|
|
private void checkBoxBitPadding_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (dataGridViewSymbolInfo.SelectedRows.Count != 0)
|
|
{
|
|
var selectedRow = dataGridViewSymbolInfo.SelectedRows[0];
|
|
RefreshSymbolGrid(selectedRow.Index);
|
|
}
|
|
else
|
|
{
|
|
RefreshSymbolGrid(0);
|
|
}
|
|
}
|
|
|
|
private void checkBoxFunctionAnalysis_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
CurrentSymbolAnalyzer.FunctionAnalysis = checkBoxFunctionAnalysis.Checked;
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
|
|
private void restrictToSymbolsImportedFroCSVToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
restrictToSymbolsImportedFroCSVToolStripMenuItem.Checked = !restrictToSymbolsImportedFroCSVToolStripMenuItem.Checked;
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void useRawPDBToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
useRawPDBToolStripMenuItem.Checked = !useRawPDBToolStripMenuItem.Checked;
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void checkBoxNamespaces_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
checkedListBoxNamespaces.Enabled = checkBoxNamespaces.Checked;
|
|
checkedListBoxNamespaces.Visible = checkBoxNamespaces.Checked;
|
|
checkedListBoxNamespaces.Items.Clear();
|
|
if (checkedListBoxNamespaces.Enabled)
|
|
{
|
|
foreach (var name in CurrentSymbolAnalyzer.RootNamespaces) checkedListBoxNamespaces.Items.Add(name);
|
|
}
|
|
}
|
|
|
|
private void restrictToUObjectsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
restrictToUObjectsToolStripMenuItem.Checked = !restrictToUObjectsToolStripMenuItem.Checked;
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void checkBoxSubclasses_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (checkBoxSubclasses.Checked && _SelectedSymbol != null)
|
|
{
|
|
textBoxFilter.Text = _SelectedSymbol.Name;
|
|
}
|
|
checkBoxMember.Checked = false;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void checkBoxMember_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (checkBoxMember.Checked && _SelectedSymbol != null)
|
|
{
|
|
textBoxFilter.Text = _SelectedSymbol.Name;
|
|
}
|
|
checkBoxSubclasses.Checked = false;
|
|
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void customMBToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
mB2ToolStripMenuItem.Checked = false;
|
|
mB3ToolStripMenuItem.Checked = false;
|
|
customMBToolStripMenuItem.Checked = true;
|
|
|
|
var memPoolsForm = new AddMemPoolsForm();
|
|
memPoolsForm.SetMemPools(CurrentSymbolAnalyzer.MemPools);
|
|
memPoolsForm.ShowDialog();
|
|
CurrentSymbolAnalyzer.MemPools = memPoolsForm.GetMemPool();
|
|
if (!_HasMemPools && CurrentSymbolAnalyzer.MemPools.Count > 0)
|
|
{
|
|
_HasMemPools = true;
|
|
}
|
|
PopulateDataTable();
|
|
}
|
|
|
|
private void mB2ToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (ShowMemPool("MB2"))
|
|
{
|
|
mB2ToolStripMenuItem.Checked = true;
|
|
mB3ToolStripMenuItem.Checked = false;
|
|
customMBToolStripMenuItem.Checked = false;
|
|
}
|
|
}
|
|
|
|
private void mB3ToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (ShowMemPool("MB3"))
|
|
{
|
|
mB2ToolStripMenuItem.Checked = false;
|
|
mB3ToolStripMenuItem.Checked = true;
|
|
customMBToolStripMenuItem.Checked = false;
|
|
}
|
|
}
|
|
|
|
private bool ShowMemPool(string memPoolName)
|
|
{
|
|
string MemoryPoolsSettings = ConfigurationManager.AppSettings.Get(memPoolName);
|
|
if (MemoryPoolsSettings == null)
|
|
return false;
|
|
string[] MemoryPools = MemoryPoolsSettings.Split(',');
|
|
List<uint> MemoryPoolsSize = new List<uint>();
|
|
foreach (var memPool in MemoryPools)
|
|
{
|
|
MemoryPoolsSize.Add(UInt32.Parse(memPool));
|
|
}
|
|
if (MemoryPoolsSize.Count > 0)
|
|
{
|
|
_SymbolAnalyzerDia.MemPools = MemoryPoolsSize;
|
|
#if RAWPDB
|
|
_SymbolAnalyzerRawPDB.MemPools = MemoryPoolsSize;
|
|
#endif
|
|
|
|
_HasMemPools = true;
|
|
|
|
PopulateDataTable();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
}
|
|
} |