119 lines
4.3 KiB
C#
119 lines
4.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using MemoryProfiler.source;
|
|
using UAF.Remoting;
|
|
|
|
namespace MemoryProfiler
|
|
{
|
|
/// <summary>
|
|
/// Interaction logic for MainWindow.xaml
|
|
/// </summary>
|
|
public partial class MainWindow : INotifyPropertyChanged
|
|
{
|
|
private const string RelativeMapFilePath = "engine\\UA_Bin\\win32_ITF_AppFramework_r.map";
|
|
|
|
private readonly MemoryProfilerPlugin _plugin;
|
|
private readonly CallstackFactory _factory;
|
|
|
|
private UInt64 _baseAddress;
|
|
private readonly Translator _translator;
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
|
|
_translator = new Translator();
|
|
_factory = new CallstackFactory(_translator);
|
|
_callstacks = new List<CallstackViewModel>();
|
|
|
|
_plugin = new MemoryProfilerPlugin(Dispatcher);
|
|
_plugin.RegisterHandler(MemoryProfilerPlugin.DataRootCmdName, HandleDataRootCmd);
|
|
_plugin.RegisterHandler(MemoryProfilerPlugin.CallstackCmdName, HandleCallstackCmd);
|
|
_plugin.RegisterHandler(MemoryProfilerPlugin.BaseAddressCmdName, HandleBaseAddressCmd);
|
|
_plugin.Start();
|
|
|
|
DataContext = this;
|
|
}
|
|
|
|
private bool _isMapFileLoaded;
|
|
public bool IsMapFileLoaded {
|
|
get { return _isMapFileLoaded; }
|
|
private set {
|
|
_isMapFileLoaded = value;
|
|
OnPropertyChanged("IsMapFileLoaded");
|
|
}
|
|
}
|
|
|
|
private List<CallstackViewModel> _callstacks;
|
|
public List<CallstackViewModel> Callstacks
|
|
{
|
|
get { return _callstacks; }
|
|
}
|
|
|
|
private void HandleDataRootCmd(IBlob blob)
|
|
{
|
|
var mapFilePath = Path.Combine(blob.ExtractString(), "..", RelativeMapFilePath);
|
|
|
|
IsMapFileLoaded = _translator.LoadMapFile(mapFilePath, MapFile.MapFormat.Pc);
|
|
if (!IsMapFileLoaded)
|
|
{
|
|
MessageBox.Show(string.Format("Could not load map file: {0}.", mapFilePath),
|
|
"Map file error",
|
|
MessageBoxButton.OK,
|
|
MessageBoxImage.Error);
|
|
}
|
|
}
|
|
|
|
private void HandleCallstackCmd(IBlob blob)
|
|
{
|
|
string extractInfo;
|
|
do
|
|
{
|
|
extractInfo = blob.ExtractString();
|
|
if (extractInfo.Contains("id"))
|
|
_factory.PushId(blob.ExtractUInt());
|
|
else if (extractInfo.Contains("ad"))
|
|
_factory.PushAddress(blob.ExtractUInt() - _baseAddress);
|
|
else if (extractInfo.Contains("ca"))
|
|
_factory.PushAllocationCount(blob.ExtractUInt());
|
|
else if (extractInfo.Contains("sa"))
|
|
_factory.PushAllocatedMemory(blob.ExtractUInt());
|
|
else if (extractInfo.Contains("cr"))
|
|
_factory.PushReleaseCount(blob.ExtractUInt());
|
|
else if (extractInfo.Contains("sr"))
|
|
_factory.PushReleasedMemory(blob.ExtractUInt());
|
|
else if (extractInfo.Contains("CALLSTACK"))
|
|
_callstacks.Add(new CallstackViewModel(_factory.MakeCallstack()));
|
|
else if (extractInfo.Contains("pi"))
|
|
blob.ExtractInt(); // Not used
|
|
else if (extractInfo == "ENDOFDUMP")
|
|
{
|
|
_callstacks = _callstacks.OrderBy(cs => -cs.TotalMemory).ToList();
|
|
OnPropertyChanged("Callstacks");
|
|
break;
|
|
}
|
|
} while (extractInfo != "ENDOFBLOB");
|
|
}
|
|
|
|
private void HandleBaseAddressCmd(IBlob blob)
|
|
{
|
|
_baseAddress = blob.ExtractULong();
|
|
}
|
|
|
|
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
|
{
|
|
_plugin.Send(new Message(MemoryProfilerPlugin.CallstackCmdName));
|
|
}
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
private void OnPropertyChanged(string property)
|
|
{
|
|
if (PropertyChanged != null)
|
|
PropertyChanged(this, new PropertyChangedEventArgs(property));
|
|
}
|
|
}
|
|
}
|