JD2022-TU1/main/tools/legacy/MemoryViewer/FormMemoryViewer.cs

772 lines
29 KiB
C#

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Globalization;
using System.Diagnostics;
using UAF.Remoting;
namespace MemoryViewer
{
public delegate void callbackAction(string source, string action, params object[] args);
public partial class FormMemoryViewer : Form
{
private MemoryViewerPlugin _plugin = null;
public MemoryViewerPlugin Plugin { get { return _plugin; } }
// engine manager object that manages the connection with the engine
private EngineConnectionLib.EngineManager _engineManager = null;
private string[] _categoryNames;
MemoryFile memFile = null;
protected bool updateGridLocked = true;
private bool changed = false;
private SlotViewer m_slotViewer = null;
private CallstackViewer m_CallStackViewer = null;
public callbackAction m_callbackAction = null;
private string myNamespace = "MemoryViewer.";
public Form currentFormTab = null;
String IPAdress;
String IPAdressDebugXBox;
int m_port = 1001;
public FormMemoryViewer()
{
InitializeComponent();
openMemoryFile();
m_callbackAction = new callbackAction(callbackExecuteAction);
Text = "MemoryViewer [Disconnected]";
CultureInfo tmp_ci = (CultureInfo)CultureInfo.CurrentCulture.Clone();
tmp_ci.NumberFormat.NumberDecimalSeparator = ".";
System.Threading.Thread.CurrentThread.CurrentCulture = tmp_ci;
if (memFile != null)
memFile.findLowHighMemoryAddress();
// Parse command line
string[] args = Environment.GetCommandLineArgs();
foreach (string arg in args)
{
if (IsCommandLineSwitch(arg, "port"))
{
m_port = Convert.ToInt32(GetCommandLineSwitchParam(arg));
}
}
updateGridLocked = false;
/*
m_CallStackViewer = new CallstackViewer();
m_CallStackViewer.Visible = true;*/
//refreshDataGrid();
tabControlSelection.TabPages[0].Tag = new TabUser(this,"AllocationViewer","Global view");
tabControlSelection.TabPages[1].Tag = new TabUser(this,"TopAllocationViewer","Top allocation view");
tabControlSelection.TabPages[2].Tag = new TabUser(this,"SlotViewer","Slot view");
tabControlSelection.TabPages[3].Tag = new TabUser(this, "MemoryEvent", "Memory event view");
tabControlSelection.TabPages[4].Tag = new TabUser(this, "FrameAllocation", "FrameAllocation view");
tabControlSelection.TabPages[5].Tag = new TabUser(this,"SettingsForm","Settings");
tabControlSelection.TabPages[6].Tag = new TabUser(this, "ClassSize", "Class Size");
tabControlSelection.TabPages[7].Tag = new TabUser(this, "ActorSize", "Actor Size");
tabControlSelection.TabPages[8].Tag = new TabUser(this, "DetailedActor", "Detailed Actor");
}
public void RegisterPlugin(MemoryViewerPlugin plugin)
{
if (plugin == null)
throw new ArgumentNullException("abstractPlugin Plugin can not be null at register");
_plugin = plugin;
_plugin.RegisterHandler("dump_allocationidresult", processAllocationIDDump, dispatchOnMainThread: false);
_plugin.RegisterHandler("capturedone", processMemoryDump, dispatchOnMainThread: false);
_plugin.RegisterHandler("stats", processStatsCategoryDump, dispatchOnMainThread: true);
_plugin.RegisterHandler("dump_capturetopallocation", processTopAllocationDump, dispatchOnMainThread: false);
_plugin.RegisterHandler("dump_captureframeallocation", processFrameAllocationDump, dispatchOnMainThread: false);
_plugin.RegisterHandler("dump_address_result", processTopAllocationDump_Address, dispatchOnMainThread: false);
_plugin.RegisterHandler("dump_memoryevents_result", processMemoryEvents, dispatchOnMainThread: false);
_plugin.RegisterHandler("dump_classsize_result", processDumpClassSize, dispatchOnMainThread: false);
_plugin.RegisterHandler("dump_actorsize_result", processDumpActorSize, dispatchOnMainThread: false);
_plugin.RegisterHandler("dump_detailedactor_result", processDumpDetailedActor, dispatchOnMainThread: false);
_plugin.RegisterHandler("eventresult", processEventResult, dispatchOnMainThread: false);
_plugin.RegisterHandler("statsName", processCategoryStatsName, dispatchOnMainThread: false);
_plugin.ConnectedChanged += delegate(object sender, EventArgs e)
{
String newText;
if (_plugin.IsConnected)
{
newText = "MemoryViewer [Connected]";
}
else
{
newText = "MemoryViewer [Disconnected]";
}
this.BeginInvoke((MethodInvoker) delegate()
{
Text = newText;
labelPlatform.Text = string.Empty;
});
};
// create engine manager
_engineManager = new EngineConnectionLib.EngineManager(_plugin);
// set engine control statis manager property
_engineConnectionStatusUserControl.EngineManager = _engineManager;
}
private bool IsCommandLineSwitch(string cmdLineArg, string cmdSwitch)
{
return (cmdLineArg.IndexOf(cmdSwitch) == 0);
}
private string GetCommandLineSwitchParam(string cmdLineArg)
{
int equal = cmdLineArg.IndexOf('=');
if(equal < 0)
return null;
return cmdLineArg.Substring(equal + 1);
}
protected void sendCommand(string command, params object[] args)
{
_plugin.Send(command, blob =>
{
blob.Push("MemoryViewer_Plugin");
blob.Push(command);
if (args != null)
{
for (UInt32 index = 0; index < args.Length; ++index)
{
if (args[index].GetType().Name == "UInt32[]")
{
UInt32[] array = (UInt32[])args[index];
blob.Push((UInt32)array.Length);
foreach (var value in array)
blob.Push(value);
}
else if (args[index].GetType().Name == "UInt32")
{
blob.Push((UInt32)args[index]);
}
else if (args[index].GetType().Name == "String")
{
blob.Push((String)args[index]);
}
}
}
});
}
protected void callbackExecuteAction(string source, string action, params object[] args)
{
string key = source.Replace(myNamespace,"");
sendCommand(action.ToLower(), args);
/*switch (key)
{
case "TopAllocationViewer":
switch (action)
{
case "capture":
sendCommand("capture_topallocation", args);
break;
case "dump_address":
sendCommand("dump_address", args);
break;
}
break;
default:
break;
}*/
}
void closeAll()
{
foreach (TabPage tabpage in tabControlSelection.TabPages)
{
TabUser tabuser = (TabUser)tabpage.Tag;
tabuser.close();
}
}
void openMemoryFile()
{
/*
memFile = new MemoryFile();
//initialize filter;
memFile.openFile(@"c:\\dump.bin");
int count = 0;
uint globalMemoryUsage = 0;
foreach (MemoryFile.XALLOC_ALLOCATOR_IDS filter in Enum.GetValues(typeof(MemoryFile.XALLOC_ALLOCATOR_IDS)))
{
listBoxFilter.Items.Add(filter);
listBoxFilter.SetSelected(count++, false);
uint valuetoDisplay = 0;
MemoryFile.CategoryAllocation category = (MemoryFile.CategoryAllocation)(memFile.m_HashCategoryMemoryUsage[filter]);
if (memFile.m_HashCategoryMemoryUsage.ContainsKey(filter))
{
valuetoDisplay = category.MemoryUsage;
}
if (category != null)
globalMemoryUsage += category.MemoryUsage;
listBoxCategoryUsage.Items.Add(valuetoDisplay.ToString());
}
textBoxMemoryUsage.Text = globalMemoryUsage.ToString();
*/
/* debug purpose
foreach (DictionaryEntry de in memFile.m_HashCallStack)
{
MemoryFile.callStack cStack = (MemoryFile.callStack)(de.Value);
dataGridViewMemory.Rows.Add(cStack.getAllocatorId().ToString(),"");
}
*/
}
void refreshDataGrid()
{/*
if (memFile == null)
return;
//build a table with allowed enum
Hashtable hashAllowedFlags = new Hashtable();
for (int index = 0;index<listBoxFilter.Items.Count;++index)
{
if (listBoxFilter.GetSelected(index))
hashAllowedFlags[listBoxFilter.Items[index]] = true;
}
dataGridViewMemory.Rows.Clear();
foreach (MemoryFile.allocationInfo allocInfo in memFile.m_ListAllocation)
{
MemoryFile.callStack callstack = (MemoryFile.callStack)(memFile.m_HashCallStack[allocInfo.crc]);
MemoryFile.XALLOC_ALLOCATOR_IDS allocID = callstack.getAllocatorId();
if (hashAllowedFlags.ContainsKey(allocID))
{
dataGridViewMemory.Rows.Add(allocInfo, allocID.ToString(), allocInfo.size_allocation, callstack.AllocationCount, callstack.getCRC());
DataGridViewTextBoxCell element = (DataGridViewTextBoxCell)dataGridViewMemory.Rows[dataGridViewMemory.Rows.Count - 2].Cells[0];
element.Tag = allocInfo;
}
}
*/
}
public int getDataGridColumnNumber(FormMemoryViewer.ITFDataGridView dataGridStyle, string columnName)
{/*
int columnNumber = -1;
foreach (DataGridViewColumn column in dataGridViewMemory.Columns)
{
columnNumber = columnNumber + 1;
if (column.Name.CompareTo(columnName) == 0)
return columnNumber;
}
columnNumber = -1;
return columnNumber;*/
return 0;
}
private void dataGridViewMemory_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{/*
if (e.RowIndex == -1)
return;
int column = getDataGridColumnNumber(dataGridViewMemory,"Reference");
DataGridViewTextBoxCell element = (DataGridViewTextBoxCell)dataGridViewMemory.Rows[e.RowIndex].Cells[column];
MemoryFile.allocationInfo allocInfo = (MemoryFile.allocationInfo)element.Tag;
listBoxCallStackView.Items.Clear();
if (memFile.m_HashCallStack.ContainsKey(allocInfo.crc))
{
MemoryFile.callStack callstack = (MemoryFile.callStack)memFile.m_HashCallStack[allocInfo.crc];
listBoxCallStackView.Tag = callstack;
foreach (uint address in callstack.m_vAddress)
{
MemoryFile.SymbolInfo symbolInfo = (MemoryFile.SymbolInfo)memFile.m_HashSymbolTable[address];
if (symbolInfo != null)
{
string composite = "0x"+address.ToString("X8") + " " + symbolInfo.symbolName + " (" + symbolInfo.lineNumber+")";
listBoxCallStackView.Items.Add(composite);
}
}
}*/
}
private void listBoxCallStackView_SelectedIndexChanged(object sender, EventArgs e)
{/*
if (listBoxCallStackView.SelectedIndex == -1)
return;
MemoryFile.callStack callstack = (MemoryFile.callStack) listBoxCallStackView.Tag;
MemoryFile.SymbolInfo symbolInfo = (MemoryFile.SymbolInfo)memFile.m_HashSymbolTable[callstack.m_vAddress[listBoxCallStackView.SelectedIndex]];
listBoxFile.Items.Clear();
if (symbolInfo != null)
{
if (File.Exists(symbolInfo.fileName))
{
StreamReader re = File.OpenText(symbolInfo.fileName);
string input = null;
while ((input = re.ReadLine()) != null)
{
listBoxFile.Items.Add(input);
}
listBoxFile.SelectedIndex = (int)symbolInfo.lineNumber-1;
re.Close();
}
}
*/
}
private void listBoxFilter_SelectedIndexChanged(object sender, EventArgs e)
{/*
if (listBoxFilter.SelectedIndex == -1 || updateGridLocked)
return;
refreshDataGrid();*/
}
public void Execute(string exeName, string Arguments, ref string output)
{
ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
startInfo.Arguments = Arguments;
string error = "";
if (output != null)
{
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
}
else
{
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
}
Process process = null;
process = Process.Start(startInfo);
if (output != null)
{
output = process.StandardOutput.ReadToEnd();
error = process.StandardError.ReadToEnd();
}
process.WaitForExit();
}
public void CopyFileFromConsole(string source, string Destination)
{
string Command = "/t /y /d /x " + IPAdressDebugXBox + " " + source + " " + Destination;
string Output = null;
Execute(@"C:\Program Files\Microsoft Xbox 360 SDK\bin\win32\xbcp",Command, ref Output);
}
private void processStatsCategoryDump(IBlob _currentBlob)
{
string platform = "";
_currentBlob.Extract(out platform);
labelPlatform.Text = platform;
bool used = false;
_currentBlob.Extract(out used);
UInt32 countCategory = 0;
_currentBlob.Extract(out countCategory);
int[] memAllocated = new int[countCategory];
int[] memCountGlobal = new int[countCategory];
int[] memCountCurrent = new int[countCategory];
int[] memPeak = new int[countCategory];
int[] memCategoryAllocByFrame = new int[countCategory];
UInt32[] memCategoryDeAllocByFrame = new UInt32[countCategory];
UInt32 globalMemoryUser = 0;
//required to consume the blob
for (UInt32 index = 0; index < countCategory; index++)
{
_currentBlob.Extract(out memAllocated[index]);
globalMemoryUser += (UInt32)memAllocated[index];
_currentBlob.Extract(out memCountGlobal[index]);
_currentBlob.Extract(out memCountCurrent[index]);
_currentBlob.Extract(out memPeak[index]);
_currentBlob.Extract(out memCategoryAllocByFrame[index]);
_currentBlob.Extract(out memCategoryDeAllocByFrame[index]);
}
labelGlobalMemory.Text = "Global Memory : " + MemoryUtils.convertBytesToString(globalMemoryUser) + " " + (globalMemoryUser);
AllocationViewer allocationViewer = null;
if (currentFormTab!= null && currentFormTab.GetType().ToString() == "MemoryViewer.AllocationViewer")
allocationViewer = (AllocationViewer) currentFormTab;
if (allocationViewer != null && allocationViewer.checkBoxFreeze.Checked == false && allocationViewer.Visible == true)
{
// m_AllocationViewer.dataGridViewAllocation.Rows.Clear();
bool update = allocationViewer.dataGridViewAllocation.Rows.Count > 1;
Int32 indexRow = 0;
DataGridViewColumn ColumnKeepSort = allocationViewer.dataGridViewAllocation.SortedColumn;
for (Int32 index = 0; index < countCategory; index++)
{
Int32 categoryID = index + 1; // categories start at 1 (not at 0)
// new version (with stats names) which is to be finalized
//if (_categoryNames == null || categoryID >= _categoryNames.Length)
// break;
//var allocatorName = _categoryNames[categoryID];
//if (string.IsNullOrEmpty(allocatorName))
// continue;
//if (!update)
//{
// allocationViewer.dataGridViewAllocation.Rows.Add(allocatorName, memAllocated[categoryID], memCountGlobal[categoryID], memCountCurrent[categoryID], memPeak[categoryID], memCategoryAllocByFrame[categoryID]);
//}
//else
//{
// allocationViewer.dataGridViewAllocation.Rows[indexRow].SetValues(allocatorName, memAllocated[categoryID], memCountGlobal[categoryID], memCountCurrent[categoryID], memPeak[categoryID], memCategoryAllocByFrame[categoryID]);
//}
//indexRow++;
// old version (with enums) (to be removed when the new version is finished)
if (Enum.IsDefined(typeof(MemoryFile.XALLOC_ALLOCATOR_IDS), categoryID) == true)
{
MemoryFile.XALLOC_ALLOCATOR_IDS eAlloc = (MemoryFile.XALLOC_ALLOCATOR_IDS)categoryID;
string allocatorName = eAlloc.ToString();
if (!update)
{
allocationViewer.dataGridViewAllocation.Rows.Add(allocatorName, memAllocated[categoryID], memCountGlobal[categoryID], memCountCurrent[categoryID], memPeak[categoryID], memCategoryAllocByFrame[categoryID]);
}
else
{
allocationViewer.dataGridViewAllocation.Rows[indexRow].SetValues(allocatorName, memAllocated[categoryID], memCountGlobal[categoryID], memCountCurrent[categoryID], memPeak[categoryID], memCategoryAllocByFrame[categoryID]);
}
indexRow++;
}
}
if (ColumnKeepSort != null)
{
ListSortDirection direction;
if (allocationViewer.dataGridViewAllocation.SortOrder == SortOrder.Ascending)
direction = ListSortDirection.Ascending;
else
direction = ListSortDirection.Descending;
allocationViewer.dataGridViewAllocation.Sort(ColumnKeepSort, direction);
}
}
/*
if (Enum.IsDefined(typeof(MemoryFile.XALLOC_ALLOCATOR_IDS),index) == true)
{
MemoryFile.XALLOC_ALLOCATOR_IDS eAlloc = (MemoryFile.XALLOC_ALLOCATOR_IDS)index;
string tmp = eAlloc.ToString();
for (int j=0;j<listBoxFilter.Items.Count;j++)
{
if (listBoxFilter.Items[j].ToString() == tmp)
{
listBoxCategoryUsage.Items[j] = memcategory;
break;
}
}
}*/
if (m_slotViewer != null)
processStatsSlotDump(_currentBlob);
}
private void processTopAllocationDump(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.TopAllocationViewer")
{
TopAllocationViewer allocationViewer = (TopAllocationViewer)currentFormTab;
allocationViewer.dumpAllocation(_currentBlob);
}
}
private void processFrameAllocationDump(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.FrameAllocation")
{
FrameAllocation allocationViewer = (FrameAllocation)currentFormTab;
allocationViewer.dumpAllocation(_currentBlob);
}
}
private void processDumpClassSize(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.ClassSize")
{
ClassSize allocationViewer = (ClassSize)currentFormTab;
allocationViewer.dump(_currentBlob);
}
}
private void processDumpActorSize(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.ActorSize")
{
ActorSize allocationViewer = (ActorSize)currentFormTab;
allocationViewer.dump(_currentBlob);
}
}
private void processDumpDetailedActor(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.DetailedActor")
{
DetailedActor allocationViewer = (DetailedActor)currentFormTab;
allocationViewer.dump(_currentBlob);
}
}
private void processTopAllocationDump_Address(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.TopAllocationViewer")
{
TopAllocationViewer allocationViewer = (TopAllocationViewer)currentFormTab;
allocationViewer.dumpAddress(_currentBlob);
}
}
private void processAllocationIDDump(IBlob _currentBlob)
{
UInt32 crcCount = 0;
_currentBlob.Extract(out crcCount);
m_CallStackViewer = new CallstackViewer();
m_CallStackViewer.Visible = true;
m_CallStackViewer.callStackText.Clear();
string filename = "";
string symbolname = "";
UInt32 line = 0;
string tmp = "";
string globaltext = "";
for (UInt32 index = 0; index < crcCount; ++index)
{
tmp = "---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\r\n";
globaltext += tmp;
UInt32 callstackSize = 0;
//allocation design
UInt32 globalCountAllocation = 0;
UInt32 sizeAllocation = 0;
UInt32 countAllocation = 0;
_currentBlob.Extract(out globalCountAllocation);
for (UInt32 i = 0; i < globalCountAllocation; ++i)
{
_currentBlob.Extract(out sizeAllocation);
_currentBlob.Extract(out countAllocation);
tmp = ">>Allocation: " + sizeAllocation.ToString() + " byte(s) count:" + countAllocation.ToString() + "\r\n";
globaltext += tmp;
}
//callstack design
_currentBlob.Extract(out callstackSize);
for (UInt32 cb = 0; cb < callstackSize; ++cb)
{
_currentBlob.Extract(out filename);
_currentBlob.Extract(out symbolname);
_currentBlob.Extract(out line);
tmp = filename + "("+line.ToString()+"):"+symbolname+"\r\n";
globaltext += tmp;
}
globaltext += "\r\n";
}
m_CallStackViewer.callStackText.Text = globaltext;
m_CallStackViewer.Invalidate(true);
}
private void processStatsSlotDump(IBlob _currentBlob)
{
UInt32 slotCount = 0;
UInt32 memoryUsage = 0;
UInt32 used = 0;
if (used == 0)
return;
_currentBlob.Extract(out used);
_currentBlob.Extract(out memoryUsage);
_currentBlob.Extract(out slotCount);
m_slotViewer.createSlot(slotCount);
m_slotViewer.updateCommon(memoryUsage);
for (UInt32 index=0;index<slotCount;index++)
{
UInt32 slotByteSize = 0;
UInt32 freeSlot = 0;
UInt32 maxSlot = 0;
UInt32 alignment = 0;
UInt32 flags = 0;
UInt32 globalMemorySize = 0;
_currentBlob.Extract(out slotByteSize);
_currentBlob.Extract(out freeSlot);
_currentBlob.Extract(out maxSlot);
_currentBlob.Extract(out alignment);
_currentBlob.Extract(out flags);
_currentBlob.Extract(out globalMemorySize);
m_slotViewer.updateSlot(index, slotByteSize, maxSlot, freeSlot, alignment, flags, globalMemorySize);
}
String warnings = "";
_currentBlob.Extract(out warnings);
m_slotViewer.updateWarnings(warnings);
}
private void processEventResult(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.MemoryEvent")
{
MemoryEvent memEventForm = (MemoryEvent)currentFormTab;
memEventForm.fillResult(_currentBlob);
}
}
private void processMemoryEvents(IBlob _currentBlob)
{
if (currentFormTab != null && currentFormTab.GetType().ToString() == "MemoryViewer.MemoryEvent")
{
MemoryEvent memEventForm = (MemoryEvent)currentFormTab;
memEventForm.fill(_currentBlob);
}
}
//TODO remove hard coded path
private void processMemoryDump(IBlob _currentBlob)
{
//get the file from the x360 directory
CopyFileFromConsole(@"DEVKIT:\guillaume.gernez\technowithtools\dump.dat", @"e:\dump.dat");
string Output = null;
Execute(@"E:\DepotMK\bin\CallStackDisplay.exe","", ref Output);
openMemoryFile();
}
private void processCategoryStatsName(IBlob _currentBlob)
{
var used = false;
UInt32 count = 0;
_currentBlob.Extract(out used);
_currentBlob.Extract(out count);
_categoryNames = new string[count];
for (var i = 0; i < count; ++i)
_currentBlob.Extract(out _categoryNames[i]);
}
private void btnCapture_Click(object sender, EventArgs e)
{
_plugin.Send("capture");
}
private void btnConnect_Click(object sender, EventArgs e)
{
if (_engineManager.IsConnected)
_engineManager.Disconnect();
_engineManager.Connect();
}
private void tabControlSelection_SelectedIndexChanged(object sender, EventArgs e)
{
int tabSelected = tabControlSelection.SelectedIndex;
if (tabSelected != -1)
{
TabPage page = tabControlSelection.TabPages[tabSelected];
TabUser user = (TabUser)page.Tag;
closeAll();
if (user != null)
user.show();
}
}
private void FormMemoryViewer_Load(object sender, EventArgs e)
{
Debug.Assert(_plugin != null, "You must initialize the form with an abstract plugin");
}
private void FormMemoryViewer_FormClosed(object sender, FormClosedEventArgs e)
{
if (_plugin.IsConnected)
{
_plugin.Stop();
}
_plugin.Dispose();
}
private void textBoxIp_TextChanged(object sender, EventArgs e)
{
changed = true;
}
private void textBoxIpDebug_TextChanged(object sender, EventArgs e)
{
changed = true;
}
}
}