├── tool ├── .gitignore ├── MemTraceTool │ ├── luna.ico │ ├── icons │ │ ├── asset.png │ │ ├── delta.png │ │ ├── folder.png │ │ ├── gear.png │ │ ├── heap.png │ │ ├── pacman.png │ │ ├── symbol.png │ │ ├── namespace.png │ │ └── sourcefile.png │ ├── packages.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Program.cs │ ├── App.config │ ├── WarningWindow.cs │ ├── TimeControlHelpers.cs │ ├── TODO.txt │ ├── FragmentationWidget.Designer.cs │ ├── TraceListItem.cs │ ├── TreePerspective.cs │ ├── WarningWindow.Designer.cs │ ├── DeltaWindow.cs │ ├── FragmentationWidget.cs │ ├── SymbolResolveDialog.Designer.cs │ ├── SymbolResolveDialog.cs │ ├── Options.cs │ ├── RangeQueryWindow.cs │ ├── FragmentationWidget.resx │ ├── DeltaWindow.Designer.cs │ ├── OptionsDialog.cs │ └── TreeBuilder.cs ├── MemTraceWidgets │ ├── dots.png │ ├── Resources │ │ └── Dots.png │ ├── packages.config │ ├── app.config │ ├── MemBlockView.Designer.cs │ ├── FragmentationWidget.Designer.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── MemTreeNode.cs │ ├── HeapTreeList.cs │ ├── TimeControl.cs │ ├── WidgetResources.Designer.cs │ ├── MemBlockView.cs │ ├── TimeControl.Designer.cs │ ├── TimeControl.resx │ ├── FragmentationWidget.resx │ ├── WidgetResources.resx │ ├── MemTraceWidgets.csproj │ └── HeapTreeList.Designer.cs ├── MemTrace │ ├── packages.config │ ├── MemTrace.yaml │ ├── app.config │ ├── EventCode.cs │ ├── ISymbolResolver.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── TraceListener.cs │ ├── DbgHelpSymbolResolver.cs │ ├── MemTrace.csproj │ ├── TraceRecorder.cs │ ├── AsyncStreamPump.cs │ └── OrbisSymbolResolver.cs └── MemTraceUI.sln ├── runtime ├── vs2012 │ ├── .gitignore │ ├── MemTraceDemo.vcxproj.filters │ ├── MemTrace.sln │ ├── MemTrace.vcxproj.filters │ ├── MemTraceDemo.vcxproj │ └── MemTrace.vcxproj ├── minhook-bin │ └── MinHook.x64.dll ├── Makefile ├── MemTrace.h ├── DemoMain.cpp ├── MemTraceInit.h ├── MemTraceSys.cpp └── MemTraceSys.h ├── .gitignore ├── docs ├── addrquery.png ├── deltaview.png ├── heapview.png ├── mainwindow.png ├── opt_files.png ├── opt_network.png ├── fragmentation.png ├── opt_symbolpaths.png ├── opt_symbolremap.png ├── opt_symbolsupp.png ├── symbolresolve.png └── heapview_perspective.png ├── .gitmodules ├── DefaultOptions.json └── COPYING /tool/.gitignore: -------------------------------------------------------------------------------- 1 | packages 2 | -------------------------------------------------------------------------------- /runtime/vs2012/.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Release 3 | x64 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | *.pdb 4 | *.suo 5 | *.user 6 | pingme.txt 7 | -------------------------------------------------------------------------------- /docs/addrquery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/addrquery.png -------------------------------------------------------------------------------- /docs/deltaview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/deltaview.png -------------------------------------------------------------------------------- /docs/heapview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/heapview.png -------------------------------------------------------------------------------- /docs/mainwindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/mainwindow.png -------------------------------------------------------------------------------- /docs/opt_files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/opt_files.png -------------------------------------------------------------------------------- /docs/opt_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/opt_network.png -------------------------------------------------------------------------------- /docs/fragmentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/fragmentation.png -------------------------------------------------------------------------------- /docs/opt_symbolpaths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/opt_symbolpaths.png -------------------------------------------------------------------------------- /docs/opt_symbolremap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/opt_symbolremap.png -------------------------------------------------------------------------------- /docs/opt_symbolsupp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/opt_symbolsupp.png -------------------------------------------------------------------------------- /docs/symbolresolve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/symbolresolve.png -------------------------------------------------------------------------------- /tool/MemTraceTool/luna.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/luna.ico -------------------------------------------------------------------------------- /docs/heapview_perspective.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/docs/heapview_perspective.png -------------------------------------------------------------------------------- /tool/MemTraceWidgets/dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceWidgets/dots.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "runtime/minhook"] 2 | path = runtime/minhook 3 | url = https://github.com/TsudaKageyu/minhook.git 4 | -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/asset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/asset.png -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/delta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/delta.png -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/folder.png -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/gear.png -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/heap.png -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/pacman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/pacman.png -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/symbol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/symbol.png -------------------------------------------------------------------------------- /runtime/minhook-bin/MinHook.x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/runtime/minhook-bin/MinHook.x64.dll -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/namespace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/namespace.png -------------------------------------------------------------------------------- /tool/MemTraceTool/icons/sourcefile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceTool/icons/sourcefile.png -------------------------------------------------------------------------------- /tool/MemTraceWidgets/Resources/Dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deplinenoise/ig-memtrace/HEAD/tool/MemTraceWidgets/Resources/Dots.png -------------------------------------------------------------------------------- /tool/MemTrace/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tool/MemTraceTool/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tool/MemTrace/MemTrace.yaml: -------------------------------------------------------------------------------- 1 | Name: MemTrace 2 | Type: CSharpLib 3 | UseDiskSources: true 4 | 5 | NuGetPackages: 6 | - { id: "Netwonsoft.Json", version: "6.0.8", targetFramework: "net45" } 7 | - { id: "ObjectListView", version: "2.7.1", targetFramework: "net45" } 8 | 9 | -------------------------------------------------------------------------------- /tool/MemTraceTool/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DefaultOptions.json: -------------------------------------------------------------------------------- 1 | { 2 | "SuppressedSymbols": [ 3 | "MemTrace::Encoder::BeginEvent", 4 | "MemTrace::HeapAllocate", 5 | "__tmainCRTStartup", 6 | "RtlUserThreadStart", 7 | "BaseThreadInitThunk", 8 | "wWinMainCRTStartup", 9 | "MemTrace::HeapFree" 10 | ], 11 | "EnableSuppression": true, 12 | "BindAddress": "0.0.0.0", 13 | "BindPort": 9811, 14 | "SymbolPaths": [ 15 | ], 16 | "ModulePathRemappings": [ 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /runtime/Makefile: -------------------------------------------------------------------------------- 1 | all: Demo 2 | 3 | DEFINES += -DMEMTRACE_USE_TEMP_FILE 4 | 5 | .cpp.o: 6 | clang++ -c $(DEFINES) -std=c++11 -Wall -o $@ $< 7 | 8 | MemTrace.o: MemTrace.cpp MemTrace.h MemTraceSys.h MemTraceInit.h 9 | 10 | MemTraceSys.o: MemTraceSys.cpp MemTrace.h MemTraceSys.h 11 | 12 | DemoMain.o: DemoMain.cpp MemTrace.h MemTraceInit.h 13 | 14 | Demo: DemoMain.o MemTrace.o MemTraceSys.o 15 | clang++ -std=c++11 -Wall -o $@ $^ 16 | 17 | clean: 18 | rm -f Demo *.o 19 | -------------------------------------------------------------------------------- /tool/MemTraceTool/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace MemTraceTool 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new MainWindow()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tool/MemTrace/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tool/MemTraceTool/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tool/MemTraceTool/WarningWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace MemTraceTool 12 | { 13 | public partial class WarningWindow : Form 14 | { 15 | public void SetWarnings(ICollection data) 16 | { 17 | m_TextBox.Clear(); 18 | m_TextBox.Text = String.Join("\r\n", data); 19 | m_TextBox.Select(0, -1); 20 | } 21 | 22 | public WarningWindow() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/MemBlockView.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTrace.Widgets 2 | { 3 | partial class MemBlockView 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | #region Component Designer generated code 11 | 12 | /// 13 | /// Required method for Designer support - do not modify 14 | /// the contents of this method with the code editor. 15 | /// 16 | private void InitializeComponent() 17 | { 18 | components = new System.ComponentModel.Container(); 19 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 20 | } 21 | 22 | #endregion 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tool/MemTrace/EventCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MemTrace 8 | { 9 | // Event codes - keep in sync with native code side. 10 | public enum EventCode 11 | { 12 | BeginStream = 1, 13 | EndStream, 14 | ModuleDump, 15 | Mark, 16 | 17 | AddressAllocate = 10, 18 | AddressFree, 19 | VirtualCommit, 20 | VirtualDecommit, 21 | 22 | PhysicalAllocate, 23 | PhysicalFree, 24 | PhysicalMap, 25 | PhysicalUnmap, 26 | 27 | HeapCreate, 28 | HeapDestroy, 29 | HeapAddCore, 30 | HeapRemoveCore, 31 | HeapAllocate, 32 | HeapReallocate, 33 | HeapFree, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /runtime/vs2012/MemTraceDemo.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /tool/MemTraceTool/TimeControlHelpers.cs: -------------------------------------------------------------------------------- 1 | using MemTrace; 2 | using MemTrace.Widgets; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MemTraceTool 10 | { 11 | class TimeControlHelpers 12 | { 13 | public static void CreateTimeControlMarks(TimeControl tc, TraceProcessorBase trace) 14 | { 15 | // Build set of times stamps from marks 16 | { 17 | var m = new List(); 18 | m.Add(new TimeControl.Mark { Name = "Start", Time = 0.0 }); 19 | var marks = new List(); 20 | trace.MetaData.GetTraceMarks(marks); 21 | foreach (var mark in marks) 22 | { 23 | m.Add(new TimeControl.Mark 24 | { 25 | Name = mark.Name, 26 | Time = mark.TimeStamp / (double)trace.MetaData.TimerFrequency 27 | }); 28 | } 29 | tc.MinTime = 0; 30 | tc.MaxTime = trace.MetaData.MaxTimeStamp / (double)trace.MetaData.TimerFrequency; 31 | m.Add(new TimeControl.Mark { Name = "End", Time = tc.MaxTime }); 32 | tc.SetMarks(m); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tool/MemTraceTool/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MemTraceTool.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tool/MemTrace/ISymbolResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MemTrace 8 | { 9 | public sealed class ModulePathRemapping 10 | { 11 | public string Platform { get; set; } 12 | public string Path { get; set; } 13 | public string ReplacementPath { get; set; } 14 | 15 | public ModulePathRemapping Clone() 16 | { 17 | return new ModulePathRemapping 18 | { 19 | Platform = Platform, 20 | Path = Path, 21 | ReplacementPath = ReplacementPath 22 | }; 23 | } 24 | } 25 | 26 | public interface ISymbolProgressListener 27 | { 28 | void UpdateProgress(string status, double pct); 29 | void UpdateMessage(string status, params object[] args); 30 | void Done(); 31 | void UpdateError(string p); 32 | } 33 | 34 | public interface ISymbolResolver 35 | { 36 | bool NeedsExePath { get; } 37 | string ExeExtension { get; } 38 | 39 | void BeginResolve(string exePath, ISymbolProgressListener listener, TraceReplayStateful replay, ICollection symbolPaths, ICollection remappings); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tool/MemTraceTool/TODO.txt: -------------------------------------------------------------------------------- 1 | 2 | Initial JSON file to live next to checked-in binary. 3 | 4 | Find dialog in heap view. 5 | 6 | Need new delta view now that the time control is in. 7 | 8 | Asset heap not working on PC. 9 | 10 | Clean up File menu/open options. How to get trace files from locutus to your own machine? 11 | 12 | Detect code branch via LunaServer to figure out bin directory? 13 | 14 | Options menu access from heap view. 15 | 16 | Fragmentation view: 17 | - Select one heap/container? 18 | - Colorize allocs based on topic? 19 | - Fade out to white with age? 20 | - How to map? Customizable? 21 | 22 | After stopping a trace buttons should be accessible. 23 | 24 | Better crash proofing againt bad trace files on disk. 25 | 26 | Figure out deployment of Durango wrapped DLLs. 27 | 28 | Figure out if we can hook lower-level stuff like ntdll!NtVirtualAllocate to catch *everything* 29 | 30 | HeapAllocate() and friends should definitely be hooked. Hook HeapCreate() to figure out name? 31 | 32 | Symbol resolution dialog: 33 | - Fix ghetto flickering text box 34 | - Show report at the end with # of symbols resolved and # failed 35 | 36 | Nice to have: 37 | - Rename dump filenames or at least add a comment to dump. 38 | - Mark time recorded and length of recording in h/m/s. 39 | 40 | 41 | [DONE] 42 | Initial setup needs settings in the registry. 43 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Insomniac Games All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /runtime/vs2012/MemTrace.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemTrace", "MemTrace.vcxproj", "{C9F9CA93-3A01-41E8-A601-66C45AA7FEA6}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemTraceDemo", "MemTraceDemo.vcxproj", "{635A9485-BB33-4886-BE78-797A2693B987}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C9F9CA93-3A01-41E8-A601-66C45AA7FEA6}.Debug|x64.ActiveCfg = Debug|x64 15 | {C9F9CA93-3A01-41E8-A601-66C45AA7FEA6}.Debug|x64.Build.0 = Debug|x64 16 | {C9F9CA93-3A01-41E8-A601-66C45AA7FEA6}.Release|x64.ActiveCfg = Release|x64 17 | {C9F9CA93-3A01-41E8-A601-66C45AA7FEA6}.Release|x64.Build.0 = Release|x64 18 | {635A9485-BB33-4886-BE78-797A2693B987}.Debug|x64.ActiveCfg = Debug|x64 19 | {635A9485-BB33-4886-BE78-797A2693B987}.Debug|x64.Build.0 = Debug|x64 20 | {635A9485-BB33-4886-BE78-797A2693B987}.Release|x64.ActiveCfg = Release|x64 21 | {635A9485-BB33-4886-BE78-797A2693B987}.Release|x64.Build.0 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /runtime/vs2012/MemTrace.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /tool/MemTraceTool/FragmentationWidget.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTraceTool 2 | { 3 | partial class FragmentationWidget 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // FragmentationWidget 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.BackColor = System.Drawing.SystemColors.AppWorkspace; 38 | this.Name = "FragmentationWidget"; 39 | this.ResumeLayout(false); 40 | 41 | } 42 | 43 | #endregion 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/FragmentationWidget.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTrace.Widgets 2 | { 3 | partial class FragmentationWidget 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // FragmentationWidget 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.BackColor = System.Drawing.SystemColors.ControlLight; 38 | this.Name = "FragmentationWidget"; 39 | this.ResumeLayout(false); 40 | 41 | } 42 | 43 | #endregion 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tool/MemTraceTool/TraceListItem.cs: -------------------------------------------------------------------------------- 1 | using MemTrace; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MemTraceTool 9 | { 10 | class TraceListItem 11 | { 12 | private string m_FileName; 13 | public TraceMeta Meta { get; internal set; } 14 | public TraceRecorder Recorder { get; internal set; } 15 | 16 | public string FileName { get { return m_FileName; } set { m_FileName = value; } } 17 | public string SourceMachine { get { return Meta.SourceMachine; } } 18 | public long EventCount { get { return Meta.EventCount; } } 19 | public long WireSize { get { return Meta.WireSizeBytes; } } 20 | public long OutputSize { get { return Meta.EncodedDataSizeBytes; } } 21 | public string PlatformName { get { return Meta.PlatformName; } } 22 | public string IsResolved { get { return Meta.ResolvedSymbols.Count > 0 ? "Yes" : "No"; } } 23 | public TraceStatus Status { get { return Meta.Status; } } 24 | public string ExecutableName { get { return Meta.ExecutableName; } } 25 | public int WarningCount { get { return Meta.WarningCount; } } 26 | 27 | internal TraceListItem(string fn, TraceMeta meta, TraceRecorder recorder) 28 | { 29 | m_FileName = fn; 30 | Meta = meta; 31 | Recorder = recorder; 32 | } 33 | 34 | public ICollection Warnings { get { return Meta.Warnings; } } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tool/MemTrace/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MemTraceDecode")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MemTraceDecode")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1202b419-3b4b-4ed1-9c7d-5b44aeab1be6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /tool/MemTraceTool/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MemTraceTool")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MemTraceTool")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9c53455f-a919-4a5f-8f48-dbd4b3140580")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MemTraceWidgets")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MemTraceWidgets")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("dcdffe31-aab6-4842-8651-d853c8db0d6d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /tool/MemTraceTool/TreePerspective.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MemTraceTool 4 | { 5 | enum TreeAxis 6 | { 7 | CallStack, 8 | CallStackReverse, 9 | FileName, 10 | Heap, 11 | AssetType, 12 | AssetPath, 13 | ComponentType 14 | } 15 | 16 | sealed class TreePerspective 17 | { 18 | internal static readonly TreePerspective Default = new TreePerspective("Heap/Stack", new TreeAxis[] { TreeAxis.Heap, TreeAxis.CallStack }); 19 | internal static readonly TreePerspective Reverse = new TreePerspective("Heap/Stack (Reverse)", new TreeAxis[] { TreeAxis.Heap, TreeAxis.CallStackReverse }); 20 | internal static readonly TreePerspective Asset = new TreePerspective("Heap/Asset Type/Asset Path", new TreeAxis[] { TreeAxis.Heap, TreeAxis.AssetType, TreeAxis.AssetPath, TreeAxis.CallStack }); 21 | internal static readonly TreePerspective AssetType = new TreePerspective("Asset Type/Heap", new TreeAxis[] { TreeAxis.AssetType, TreeAxis.Heap }); 22 | internal static readonly TreePerspective Component = new TreePerspective("Heap/Component Type/Stack", new TreeAxis[] { TreeAxis.Heap, TreeAxis.ComponentType, TreeAxis.CallStack }); 23 | 24 | internal static readonly TreePerspective[] AllItems = new TreePerspective[] { 25 | Default, 26 | Reverse, 27 | Asset, 28 | AssetType, 29 | Component 30 | }; 31 | 32 | internal string Name { get; private set; } 33 | internal TreeAxis[] Axes { get; private set; } 34 | 35 | private TreePerspective(string name, TreeAxis[] axes) 36 | { 37 | Name = name; 38 | Axes = axes; 39 | } 40 | 41 | public override string ToString() 42 | { 43 | return Name; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /tool/MemTraceWidgets/MemTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MemTraceTool 8 | { 9 | public sealed class MemTreeNode 10 | { 11 | private Dictionary m_Children = new Dictionary(); 12 | private MemTreeNode[] m_ChildArray = null; 13 | 14 | public MemTreeNode[] Children { get { return m_ChildArray; } } 15 | public bool HasChildren { get { return m_ChildArray != null; } } 16 | 17 | public MemTreeNode Parent { get; private set; } 18 | public string Key { get; private set; } 19 | public string FileName { get; set; } 20 | public int LineNumber { get; set; } 21 | public string Icon { get; set; } 22 | public long SizeBytes { get; set; } 23 | public ulong Count { get; set; } 24 | 25 | public MemTreeNode(MemTreeNode parent, string key) 26 | { 27 | Parent = parent; 28 | Key = key; 29 | } 30 | 31 | public MemTreeNode GetChild(string key) 32 | { 33 | MemTreeNode child; 34 | if (m_Children.TryGetValue(key, out child)) 35 | return child; 36 | 37 | child = new MemTreeNode(this, key); 38 | m_Children.Add(key, child); 39 | return child; 40 | } 41 | 42 | public void Freeze() 43 | { 44 | if (m_Children.Count > 0) 45 | { 46 | m_ChildArray = m_Children.Values.ToArray(); 47 | foreach (var child in m_ChildArray) 48 | { 49 | child.Freeze(); 50 | } 51 | } 52 | else 53 | { 54 | m_ChildArray = null; 55 | } 56 | m_Children = null; 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /tool/MemTraceUI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemTrace", "MemTrace\MemTrace.csproj", "{2E43CDC0-AC81-4172-85E7-4126EED64656}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemTraceTool", "MemTraceTool\MemTraceTool.csproj", "{2FBF023A-ACDB-4526-AEBF-8C72FFC40E9A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemTraceWidgets", "MemTraceWidgets\MemTraceWidgets.csproj", "{DE94B6DF-8E75-4623-A12C-BE2A1756A128}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2E43CDC0-AC81-4172-85E7-4126EED64656}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {2E43CDC0-AC81-4172-85E7-4126EED64656}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {2E43CDC0-AC81-4172-85E7-4126EED64656}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {2E43CDC0-AC81-4172-85E7-4126EED64656}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {2FBF023A-ACDB-4526-AEBF-8C72FFC40E9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {2FBF023A-ACDB-4526-AEBF-8C72FFC40E9A}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {2FBF023A-ACDB-4526-AEBF-8C72FFC40E9A}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {2FBF023A-ACDB-4526-AEBF-8C72FFC40E9A}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {DE94B6DF-8E75-4623-A12C-BE2A1756A128}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {DE94B6DF-8E75-4623-A12C-BE2A1756A128}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {DE94B6DF-8E75-4623-A12C-BE2A1756A128}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {DE94B6DF-8E75-4623-A12C-BE2A1756A128}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/HeapTreeList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using MemTraceTool; 11 | 12 | namespace MemTrace.Widgets 13 | { 14 | public partial class HeapTreeList : UserControl 15 | { 16 | public HeapTreeList() 17 | { 18 | InitializeComponent(); 19 | 20 | // Hook up treelist view stuff. 21 | m_TreeList.CanExpandGetter = (object o) => 22 | { 23 | return ((MemTreeNode)o).HasChildren; 24 | }; 25 | m_TreeList.ChildrenGetter = (object o) => 26 | { 27 | return ((MemTreeNode)o).Children; 28 | }; 29 | m_KeyColumn.ImageGetter = (object o) => 30 | { 31 | return ((MemTreeNode)o).Icon; 32 | }; 33 | m_LineNumberColumn.AspectGetter = (object o) => 34 | { 35 | int value = ((MemTreeNode)o).LineNumber; 36 | if (value == 0) 37 | return null; 38 | return value; 39 | }; 40 | m_SizeColumn.AspectToStringConverter = (object o) => 41 | { 42 | long size = (long)o; 43 | long abs = Math.Abs(size); 44 | if ((abs >> 30) > 0) 45 | { 46 | return String.Format("{0:n2} GB", size / (1024.0 * 1024.0 * 1024.0)); 47 | } 48 | if ((abs >> 20) > 0) 49 | { 50 | return String.Format("{0:n2} MB", size / (1024.0 * 1024.0)); 51 | } 52 | if ((abs >> 10) > 0) 53 | { 54 | return String.Format("{0:n2} KB", size / (1024.0)); 55 | } 56 | return String.Format("{0:n0} B", size); 57 | }; 58 | } 59 | 60 | public MemTreeNode SelectedNode 61 | { 62 | get { return (MemTreeNode)m_TreeList.SelectedObject; } 63 | } 64 | 65 | public void SetRoot(MemTreeNode root) 66 | { 67 | m_TreeList.Roots = new object[] { root }; 68 | m_TreeList.RebuildAll(true); 69 | m_TreeList.Expand(root); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tool/MemTraceTool/WarningWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTraceTool 2 | { 3 | partial class WarningWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WarningWindow)); 32 | this.m_TextBox = new System.Windows.Forms.TextBox(); 33 | this.SuspendLayout(); 34 | // 35 | // m_TextBox 36 | // 37 | this.m_TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 38 | | System.Windows.Forms.AnchorStyles.Left) 39 | | System.Windows.Forms.AnchorStyles.Right))); 40 | this.m_TextBox.Location = new System.Drawing.Point(13, 13); 41 | this.m_TextBox.Multiline = true; 42 | this.m_TextBox.Name = "m_TextBox"; 43 | this.m_TextBox.ReadOnly = true; 44 | this.m_TextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 45 | this.m_TextBox.Size = new System.Drawing.Size(629, 399); 46 | this.m_TextBox.TabIndex = 0; 47 | // 48 | // WarningWindow 49 | // 50 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 51 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 52 | this.ClientSize = new System.Drawing.Size(654, 424); 53 | this.Controls.Add(this.m_TextBox); 54 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 55 | this.Name = "WarningWindow"; 56 | this.Text = "Warnings"; 57 | this.ResumeLayout(false); 58 | this.PerformLayout(); 59 | 60 | } 61 | 62 | #endregion 63 | 64 | private System.Windows.Forms.TextBox m_TextBox; 65 | } 66 | } -------------------------------------------------------------------------------- /tool/MemTraceTool/DeltaWindow.cs: -------------------------------------------------------------------------------- 1 | using MemTrace; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace MemTraceTool 13 | { 14 | public partial class DeltaWindow : Form 15 | { 16 | private TraceReplayStateful m_Trace; 17 | private Options m_Options; 18 | 19 | internal DeltaWindow(string fn, Options options) 20 | { 21 | InitializeComponent(); 22 | 23 | m_Trace = new TraceReplayStateful(fn); 24 | m_Options = options; 25 | 26 | TimeControlHelpers.CreateTimeControlMarks(m_StartTimeControl, m_Trace); 27 | TimeControlHelpers.CreateTimeControlMarks(m_EndTimeControl, m_Trace); 28 | 29 | m_Perspective.Items.AddRange(TreePerspective.AllItems); 30 | m_Perspective.SelectedIndex = 0; 31 | } 32 | 33 | protected override void OnClosed(EventArgs e) 34 | { 35 | m_Trace.Dispose(); 36 | } 37 | 38 | private void OnRefreshButtonClick(object sender, EventArgs e) 39 | { 40 | m_RefreshButton.Enabled = false; 41 | m_StartTimeControl.Enabled = false; 42 | m_EndTimeControl.Enabled = false; 43 | 44 | var perspective = (TreePerspective) m_Perspective.SelectedItem; 45 | var startTime = m_StartTimeControl.CurrentTime; 46 | var endTime = m_EndTimeControl.CurrentTime; 47 | 48 | Task.Run(() => { this.UpdateDeltaViewAsync(startTime, endTime, perspective); }); 49 | } 50 | 51 | private void UpdateDeltaViewAsync(double startTime, double endTime, TreePerspective perspective) 52 | { 53 | this.Invoke((Action)delegate() { m_StripStatus.Text = "Replaying events.."; }); 54 | 55 | TraceReplayStateful.StatusDelegate replayCallback = (double ratio) => 56 | { 57 | this.Invoke((Action)delegate() 58 | { 59 | m_ReplayProgress.Value = (int)Math.Round(1000.0 * ratio); 60 | }); 61 | }; 62 | 63 | TreeBuilderBase tree_builder; 64 | tree_builder = new DeltaTreeBuilder(m_Trace, startTime, endTime, replayCallback, perspective, m_Options); 65 | 66 | this.Invoke((Action)delegate() { m_StripStatus.Text = "Building report tree.."; }); 67 | 68 | var root = tree_builder.BuildReportTree(); 69 | 70 | this.Invoke((Action)delegate() 71 | { 72 | OnTreeUpdated(root); 73 | }); 74 | } 75 | 76 | private void OnTreeUpdated(MemTreeNode root) 77 | { 78 | m_HeapTree.SetRoot(root); 79 | m_StripStatus.Text = "Ready"; 80 | m_ReplayProgress.Value = 0; 81 | m_RefreshButton.Enabled = true; 82 | m_StartTimeControl.Enabled = true; 83 | m_EndTimeControl.Enabled = true; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tool/MemTraceTool/FragmentationWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | using System.Diagnostics; 9 | 10 | namespace MemTraceTool 11 | { 12 | public interface IMemoryInfo 13 | { 14 | ulong MinAddress { get; } 15 | ulong MaxAddress { get; } 16 | 17 | void GetOccupancyMask(uint[] out_bits, ulong addr_lo, ulong addr_hi); 18 | 19 | void GetAllocationInfo(ulong address); 20 | } 21 | 22 | public partial class FragmentationWidget : UserControl, IDisposable 23 | { 24 | public IMemoryInfo MemoryInfo { get; set; } 25 | 26 | public int BytesPerPixelLog2 { get; set; } 27 | 28 | private Brush m_BackgroundBrush; 29 | private uint[] m_Buffer = new uint[1024]; 30 | 31 | public FragmentationWidget() 32 | { 33 | m_BackgroundBrush = new SolidBrush(Color.DarkGray); 34 | InitializeComponent(); 35 | } 36 | 37 | protected override void OnPaint(PaintEventArgs e) 38 | { 39 | var g = e.Graphics; 40 | Draw(g); 41 | } 42 | 43 | private Point AddressToPoint(ulong address) 44 | { 45 | var mem = MemoryInfo; 46 | if (null == mem) 47 | return new Point(0, 0); 48 | 49 | var sz = this.ClientSize; 50 | ulong w = (ulong) sz.Width; 51 | int bbp = BytesPerPixelLog2; 52 | 53 | ulong offset = (address - mem.MinAddress); 54 | int yoff = (int) ((offset >> bbp) / w); 55 | int xoff = (int) ((offset >> bbp) % w); 56 | 57 | return new Point(xoff, yoff); 58 | } 59 | 60 | private ulong PointToAddress(Point p) 61 | { 62 | var mem = MemoryInfo; 63 | var sz = this.ClientSize; 64 | 65 | if (mem == null || p.X < 0 || p.X >= sz.Width || p.Y <0 || p.Y >= sz.Height) 66 | return 0; 67 | 68 | int bbp = BytesPerPixelLog2; 69 | ulong x = (ulong) p.X; 70 | ulong y = (ulong) p.Y; 71 | 72 | ulong off = (x + y * (ulong)sz.Width) << bbp; 73 | 74 | return mem.MinAddress + off; 75 | } 76 | 77 | private void Draw(Graphics g) 78 | { 79 | var mem = MemoryInfo; 80 | var rect = g.ClipBounds; 81 | g.FillRectangle(m_BackgroundBrush, rect); 82 | 83 | if (null == mem) 84 | return; 85 | 86 | ulong start_addr = PointToAddress(new Point((int)rect.Left, (int)rect.Top)); 87 | ulong end_addr = PointToAddress(new Point((int)rect.Right, (int)rect.Bottom)); 88 | 89 | // Make sure the buffer is large enough. 90 | int bytes = (int)(end_addr - start_addr); 91 | int count = (bytes + 31) / 32; 92 | if (count > m_Buffer.Length) 93 | m_Buffer = new uint[count + 1024]; 94 | 95 | mem.GetOccupancyMask(m_Buffer, start_addr, end_addr); 96 | 97 | for (ulong addr = start_addr; addr < end_addr; ++addr) 98 | { 99 | 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /tool/MemTraceTool/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MemTraceTool.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MemTraceTool.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/TimeControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace MemTrace.Widgets 12 | { 13 | public partial class TimeControl : UserControl 14 | { 15 | public double MinTime { get; set; } 16 | public double MaxTime { get; set; } 17 | 18 | public string TimeLabel 19 | { 20 | get { return m_Label.Text; } 21 | set { m_Label.Text = value; } 22 | } 23 | 24 | public double CurrentTime 25 | { 26 | get; private set; 27 | } 28 | 29 | public delegate void TimeChangedDelegate(object sender, TimeChangedEvent e); 30 | public event TimeChangedDelegate TimeChanged; 31 | 32 | public sealed class Mark 33 | { 34 | public string Name; 35 | public double Time; 36 | 37 | public override string ToString() 38 | { 39 | return String.Format("{1:0.000}s ({0})", Name, Time); 40 | } 41 | } 42 | 43 | public void SetMarks(ICollection marks) 44 | { 45 | m_Time.Items.Clear(); 46 | m_Time.Items.AddRange(marks.ToArray()); 47 | } 48 | 49 | public TimeControl() 50 | { 51 | InitializeComponent(); 52 | m_Time.Text = "0.000"; 53 | } 54 | 55 | private void OnRev2Button_Click(object sender, EventArgs e) 56 | { 57 | CurrentTime = Math.Max(0, CurrentTime - 1.0); 58 | UpdateTime(); 59 | } 60 | 61 | private void OnRev1Button_Click(object sender, EventArgs e) 62 | { 63 | CurrentTime = Math.Max(0, CurrentTime - 0.033); 64 | UpdateTime(); 65 | } 66 | 67 | private void OnFwd1Button_Click(object sender, EventArgs e) 68 | { 69 | CurrentTime = Math.Min(MaxTime, CurrentTime + 0.033); 70 | UpdateTime(); 71 | } 72 | 73 | private void OnFwd2Button_Click(object sender, EventArgs e) 74 | { 75 | CurrentTime = Math.Min(MaxTime, CurrentTime + 1.0); 76 | UpdateTime(); 77 | } 78 | 79 | private void OnComboKeyDown(object sender, KeyEventArgs e) 80 | { 81 | if (e.KeyValue == (int) Keys.Enter || e.KeyValue == (int) Keys.Return) 82 | { 83 | try 84 | { 85 | CurrentTime = Double.Parse(m_Time.Text); 86 | } 87 | catch (Exception) 88 | { 89 | } 90 | UpdateTime(); 91 | } 92 | } 93 | 94 | private void OnTimeValueSelected(object sender, EventArgs e) 95 | { 96 | var item = (Mark) m_Time.SelectedItem; 97 | CurrentTime = item.Time; 98 | UpdateTime(); 99 | } 100 | 101 | private void UpdateTime() 102 | { 103 | var ev = new TimeChangedEvent { Time = CurrentTime }; 104 | if (null != TimeChanged) 105 | { 106 | TimeChanged(this, ev); 107 | } 108 | CurrentTime = ev.Time; 109 | BeginInvoke(new Action(() => m_Time.Text = String.Format("{0:0.000}", CurrentTime))); 110 | } 111 | } 112 | 113 | public sealed class TimeChangedEvent 114 | { 115 | public double Time { get; set; } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/WidgetResources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MemTrace.Widgets { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class WidgetResources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal WidgetResources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MemTrace.Widgets.WidgetResources", typeof(WidgetResources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap dots { 67 | get { 68 | object obj = ResourceManager.GetObject("dots", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tool/MemTrace/TraceListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | using System.IO; 9 | 10 | namespace MemTrace 11 | { 12 | class TraceSession : IDisposable 13 | { 14 | public TraceRecorder Recorder { get; private set; } 15 | public Socket Socket { get; private set; } 16 | 17 | public TraceSession(ITraceFileHandler handler, Socket socket, string filename) 18 | { 19 | Socket = socket; 20 | Recorder = new TraceRecorder(handler, socket, filename); 21 | } 22 | 23 | ~TraceSession() 24 | { 25 | Dispose(false); 26 | } 27 | 28 | public void Dispose() 29 | { 30 | Dispose(true); 31 | } 32 | 33 | private void Dispose(bool disposing) 34 | { 35 | if (Recorder != null) 36 | { 37 | Recorder.Dispose(); 38 | Recorder = null; 39 | } 40 | if (Socket != null) 41 | { 42 | Socket.Dispose(); 43 | Socket = null; 44 | } 45 | 46 | if (disposing) 47 | { 48 | GC.SuppressFinalize(this); 49 | } 50 | } 51 | } 52 | 53 | // Sets up a TCP/IP end point for collecting traces. 54 | public class TraceListener : IDisposable 55 | { 56 | public string TraceDirectory { get; set; } 57 | public IPAddress BindAddress { get; set; } 58 | public int BindPort { get; set; } 59 | 60 | public ITraceFileHandler TraceFileHandler { get; private set; } 61 | 62 | private TcpListener m_Socket; 63 | private List m_Sessions = new List(); 64 | 65 | public TraceListener(ITraceFileHandler handler) 66 | { 67 | TraceFileHandler = handler; 68 | BindAddress = IPAddress.Loopback; 69 | BindPort = 9811; 70 | } 71 | 72 | ~TraceListener() 73 | { 74 | Dispose(false); 75 | } 76 | 77 | public void Start() 78 | { 79 | if (String.IsNullOrEmpty(TraceDirectory)) 80 | throw new ApplicationException("TraceDirectory is not valid"); 81 | 82 | if (BindAddress == null) 83 | throw new ApplicationException("BindAddress is not valid"); 84 | 85 | if (!Directory.Exists(TraceDirectory)) 86 | { 87 | Directory.CreateDirectory(TraceDirectory); 88 | } 89 | 90 | m_Socket = new TcpListener(BindAddress, BindPort); 91 | 92 | m_Socket.Start(); 93 | 94 | m_Socket.BeginAcceptSocket(OnIncomingConnection, null); 95 | } 96 | 97 | private void OnIncomingConnection(IAsyncResult ar) 98 | { 99 | if (m_Socket == null) 100 | return; 101 | 102 | Socket client = m_Socket.EndAcceptSocket(ar); 103 | 104 | // Pick a filename for this trace. 105 | string fn = String.Format("trace_{0}.mtrace", DateTime.Now.ToFileTimeUtc()); 106 | string path = Path.Combine(TraceDirectory, fn); 107 | 108 | m_Sessions.Add(new TraceSession(TraceFileHandler, client, path)); 109 | 110 | // Immediately accept a new client. 111 | m_Socket.BeginAcceptSocket(OnIncomingConnection, null); 112 | } 113 | 114 | public void Dispose() 115 | { 116 | Dispose(true); 117 | } 118 | 119 | private void Dispose(bool disposing) 120 | { 121 | if (m_Socket != null) 122 | { 123 | m_Socket.Stop(); 124 | m_Socket = null; 125 | } 126 | 127 | if (disposing) 128 | { 129 | GC.SuppressFinalize(this); 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/MemBlockView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.Drawing.Imaging; 11 | 12 | namespace MemTrace.Widgets 13 | { 14 | public partial class MemBlockView : UserControl 15 | { 16 | private List m_Allocs = null; 17 | 18 | private long m_LoAddress; 19 | private long m_HiAddress; 20 | private int[] m_Pixels = new int[256 * 256]; 21 | private bool m_BitmapValid = false; 22 | private Bitmap m_Bitmap = new Bitmap(256, 256); 23 | 24 | public MemBlockView() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | /// 30 | /// Clean up any resources being used. 31 | /// 32 | /// true if managed resources should be disposed; otherwise, false. 33 | protected override void Dispose(bool disposing) 34 | { 35 | if (disposing && (components != null)) 36 | { 37 | components.Dispose(); 38 | } 39 | if (disposing && (m_Bitmap != null)) 40 | { 41 | m_Bitmap.Dispose(); 42 | } 43 | base.Dispose(disposing); 44 | } 45 | 46 | 47 | public void SetBlock(ulong start, ulong end, List allocs) 48 | { 49 | m_Allocs = allocs; 50 | m_LoAddress = (long) start; 51 | m_HiAddress = (long) end; 52 | 53 | m_BitmapValid = false; 54 | Invalidate(); 55 | } 56 | 57 | protected override void OnPaintBackground(PaintEventArgs e) 58 | { 59 | if (DesignMode) 60 | { 61 | base.OnPaintBackground(e); 62 | } 63 | } 64 | 65 | protected override void OnPaint(PaintEventArgs ev) 66 | { 67 | base.OnPaint(ev); 68 | 69 | var g = ev.Graphics; 70 | 71 | var w = Width; 72 | var h = Height; 73 | var lo = m_LoAddress; 74 | var hi = m_HiAddress; 75 | var rng = hi - lo; 76 | double bytes_per_row = (double) rng / (double)w; 77 | double bytes_per_pixel = (double)w / bytes_per_row; 78 | 79 | if (m_Allocs == null) 80 | { 81 | g.Clear(BackColor); 82 | return; 83 | } 84 | 85 | if (!m_BitmapValid) 86 | { 87 | UpdateBitmap(); 88 | } 89 | 90 | g.DrawImage(m_Bitmap, 0, 0); 91 | 92 | } 93 | 94 | private void UpdateBitmap() 95 | { 96 | var pixels = m_Pixels; 97 | var bg = BackColor.ToArgb(); 98 | 99 | for (int i = 0; i < pixels.Length; ++i) 100 | { 101 | pixels[i] = bg; 102 | } 103 | 104 | foreach (var a in m_Allocs) 105 | { 106 | long s = (long) a.Alloc.Address - m_LoAddress; 107 | long e = s + (long) a.Alloc.SizeBytes; 108 | 109 | s = Math.Max(s, 0); 110 | e = Math.Min(e, 256 * 256); 111 | 112 | for (; s < e; ++s) 113 | { 114 | pixels[s] = a.Color.ToArgb(); 115 | } 116 | } 117 | 118 | var bm = m_Bitmap; 119 | var rect = new Rectangle(0, 0, 256, 256); 120 | 121 | BitmapData data = null; 122 | 123 | try 124 | { 125 | data = bm.LockBits(rect, ImageLockMode.ReadWrite, bm.PixelFormat); 126 | System.Runtime.InteropServices.Marshal.Copy(pixels, 0, data.Scan0, Math.Abs(data.Stride) * bm.Height / 4); 127 | } 128 | finally 129 | { 130 | if (data != null) 131 | { 132 | bm.UnlockBits(data); 133 | } 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tool/MemTrace/DbgHelpSymbolResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using MemTrace; 7 | using System.IO; 8 | 9 | namespace MemTrace 10 | { 11 | public sealed class DbgHelpSymbolResolver : ISymbolResolver 12 | { 13 | public bool NeedsExePath { get { return false; } } 14 | 15 | public string ExeExtension { get { return ".exe"; } } 16 | 17 | public void BeginResolve(string ignored, ISymbolProgressListener listener, TraceReplayStateful replay, ICollection symbolPaths, ICollection remappings) 18 | { 19 | Task.Run(() => 20 | { 21 | var result = new Dictionary(); 22 | var metadata = replay.MetaData; 23 | var platform = metadata.PlatformName; 24 | 25 | using (var dbghelp = new DbgHelp(symbolPaths)) 26 | { 27 | for (int i = 0, count = metadata.Modules.Count; i < count; ++i) 28 | { 29 | var mod = metadata.Modules[i]; 30 | 31 | listener.UpdateProgress(String.Format("Loading module {0}/{1}..", i + 1, count), (i + 1) / (double)count); 32 | 33 | // TEMP! Ignore empty module from Durango. 34 | if (mod.Name == "") 35 | continue; 36 | 37 | var fn = mod.Name; 38 | foreach (var rm in remappings) 39 | { 40 | if (0 != StringComparer.InvariantCultureIgnoreCase.Compare(rm.Platform, platform)) 41 | continue; 42 | 43 | if (fn.ToLower().StartsWith(rm.Path.ToLower())) 44 | { 45 | var oldfn = fn; 46 | fn = rm.ReplacementPath + fn.Substring(rm.Path.Length); 47 | listener.UpdateMessage(String.Format("Remapped {0} -> {1}", oldfn, fn)); 48 | } 49 | } 50 | 51 | listener.UpdateMessage(String.Format("Loading {0} at {1:x16}, size={2:n0} bytes", fn, mod.BaseAddress, mod.SizeBytes)); 52 | dbghelp.LoadModule(fn, mod.BaseAddress, mod.SizeBytes); 53 | } 54 | 55 | int x = 0; 56 | foreach (ulong address in metadata.Symbols) 57 | { 58 | if (x % 100 == 0) 59 | { 60 | listener.UpdateProgress(String.Format("Resolving symbol {0}/{1}..", x + 1, metadata.Symbols.Count), (x + 1) / (double)metadata.Symbols.Count); 61 | } 62 | 63 | SymbolInfo sym; 64 | if (dbghelp.LookupSymbol(address, out sym)) 65 | { 66 | result[address] = sym; 67 | } 68 | else 69 | { 70 | sym.Symbol = "(unknown)"; 71 | foreach (var mod in metadata.Modules) 72 | { 73 | if (address >= mod.BaseAddress && address <= mod.BaseAddress + mod.SizeBytes) 74 | { 75 | sym.Symbol = String.Format("{0}!0x{1:x16}", Path.GetFileNameWithoutExtension(mod.Name), address); 76 | result[address] = sym; 77 | break; 78 | } 79 | } 80 | //UpdateMessage(String.Format("Failed to resolve address {0:x}\n", address)); 81 | } 82 | 83 | ++x; 84 | } 85 | } 86 | 87 | listener.UpdateProgress("Saving..", 1.0); 88 | listener.UpdateMessage("Writing resolved symbols back to trace file"); 89 | 90 | replay.UpdateResolvedSymbols(result); 91 | 92 | listener.UpdateProgress("Done", 1.0); 93 | listener.UpdateMessage("Finished!"); 94 | 95 | listener.Done(); 96 | }); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /runtime/MemTrace.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Insomniac Games All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | // You can control this with a build macro if desired to compile MemTrace out. 32 | #define MEMTRACE_ENABLE 1 33 | 34 | namespace MemTrace 35 | { 36 | typedef uint32_t HeapId; 37 | 38 | enum ScopeKind 39 | { 40 | kScopeNone, 41 | kScopeAsset, 42 | kScopeComponent 43 | }; 44 | 45 | #if MEMTRACE_ENABLE 46 | 47 | // Get connection parameters specified on the command line, if any (returns true) 48 | // Useful to forward memtrace configuration along to spawned child processes. 49 | bool GetSocketData(char (&ip_addr_out)[128], int* port_out); 50 | 51 | void InitFile(const char *trace_temp_file); 52 | 53 | void InitSocket(const char *server_ip_address, int server_port); 54 | 55 | void Shutdown(); 56 | 57 | void UserMark(const char* label, ...); 58 | 59 | void Flush(); 60 | 61 | void AddressAllocate(const void* base, size_t size_bytes, const char* name); 62 | void AddressFree(const void* base); 63 | 64 | void VirtualCommit(const void* base, size_t size_bytes); 65 | void VirtualDecommit(const void* base, size_t size_bytes); 66 | 67 | HeapId HeapCreate(const char* name); 68 | void HeapDestroy(HeapId heap_id); 69 | void HeapAddCore(HeapId heap_id, const void* base, size_t size_bytes); 70 | void HeapRemoveCore(HeapId heap_id, const void* base, size_t size_bytes); 71 | void HeapAllocate(HeapId heap_id, const void* ptr, size_t size_bytes); 72 | void HeapReallocate(HeapId heap_id, const void* ptr_in, const void* ptr_out, size_t new_size_bytes); 73 | void HeapFree(HeapId heap_id, const void* ptr); 74 | 75 | void PushScope(ScopeKind kind, const char* str, ScopeKind* old_kind, const char** old_str); 76 | void RestoreScope(ScopeKind kind, const char* str); 77 | 78 | class ScopeHelper 79 | { 80 | ScopeKind m_Kind; 81 | const char *m_String; 82 | 83 | public: 84 | ScopeHelper(ScopeKind kind, const char* str) 85 | { 86 | PushScope(kind, str, &m_Kind, &m_String); 87 | } 88 | 89 | ~ScopeHelper() 90 | { 91 | RestoreScope(m_Kind, m_String); 92 | } 93 | private: 94 | ScopeHelper(const ScopeHelper&); 95 | ScopeHelper& operator=(const ScopeHelper&); 96 | }; 97 | 98 | void DummyInitFunction(char dummy); 99 | 100 | #define MEMTRACE_SCOPE(kind, text) \ 101 | ::MemTrace::ScopeHelper memtrace_scope_(kind, text) 102 | 103 | #else 104 | 105 | #define MEMTRACE_SCOPE(kind, text) \ 106 | do {} while(0) 107 | 108 | #endif 109 | 110 | } 111 | -------------------------------------------------------------------------------- /tool/MemTraceTool/SymbolResolveDialog.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTraceTool 2 | { 3 | partial class SymbolResolveDialog 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SymbolResolveDialog)); 32 | this.m_LogText = new System.Windows.Forms.TextBox(); 33 | this.m_ProgressBar = new System.Windows.Forms.ProgressBar(); 34 | this.m_StatusLabel = new System.Windows.Forms.Label(); 35 | this.SuspendLayout(); 36 | // 37 | // m_LogText 38 | // 39 | this.m_LogText.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 40 | | System.Windows.Forms.AnchorStyles.Left) 41 | | System.Windows.Forms.AnchorStyles.Right))); 42 | this.m_LogText.Location = new System.Drawing.Point(10, 58); 43 | this.m_LogText.MaxLength = 128000; 44 | this.m_LogText.Multiline = true; 45 | this.m_LogText.Name = "m_LogText"; 46 | this.m_LogText.ReadOnly = true; 47 | this.m_LogText.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 48 | this.m_LogText.Size = new System.Drawing.Size(606, 354); 49 | this.m_LogText.TabIndex = 0; 50 | // 51 | // m_ProgressBar 52 | // 53 | this.m_ProgressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 54 | | System.Windows.Forms.AnchorStyles.Right))); 55 | this.m_ProgressBar.Location = new System.Drawing.Point(10, 29); 56 | this.m_ProgressBar.Maximum = 1000; 57 | this.m_ProgressBar.Name = "m_ProgressBar"; 58 | this.m_ProgressBar.Size = new System.Drawing.Size(605, 23); 59 | this.m_ProgressBar.TabIndex = 1; 60 | // 61 | // m_StatusLabel 62 | // 63 | this.m_StatusLabel.AutoSize = true; 64 | this.m_StatusLabel.Location = new System.Drawing.Point(9, 13); 65 | this.m_StatusLabel.Name = "m_StatusLabel"; 66 | this.m_StatusLabel.Size = new System.Drawing.Size(37, 13); 67 | this.m_StatusLabel.TabIndex = 2; 68 | this.m_StatusLabel.Text = "Status"; 69 | // 70 | // SymbolResolveDialog 71 | // 72 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 73 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 74 | this.ClientSize = new System.Drawing.Size(627, 422); 75 | this.Controls.Add(this.m_StatusLabel); 76 | this.Controls.Add(this.m_ProgressBar); 77 | this.Controls.Add(this.m_LogText); 78 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 79 | this.Name = "SymbolResolveDialog"; 80 | this.Text = "Resolving Symbols.."; 81 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing); 82 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.OnFormClosed); 83 | this.Shown += new System.EventHandler(this.OnFormShown); 84 | this.ResumeLayout(false); 85 | this.PerformLayout(); 86 | 87 | } 88 | 89 | #endregion 90 | 91 | private System.Windows.Forms.TextBox m_LogText; 92 | private System.Windows.Forms.ProgressBar m_ProgressBar; 93 | private System.Windows.Forms.Label m_StatusLabel; 94 | } 95 | } -------------------------------------------------------------------------------- /tool/MemTraceTool/SymbolResolveDialog.cs: -------------------------------------------------------------------------------- 1 | using MemTrace; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Diagnostics; 6 | using System.Drawing; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Forms; 12 | 13 | namespace MemTraceTool 14 | { 15 | public partial class SymbolResolveDialog : Form, ISymbolProgressListener 16 | { 17 | private TraceListItem m_Item; 18 | private TraceReplayStateful m_Replay; 19 | private Options m_Options; 20 | private volatile bool m_Done; 21 | 22 | internal SymbolResolveDialog(TraceListItem trace, Options options) 23 | { 24 | InitializeComponent(); 25 | 26 | m_Options = options; 27 | m_Item = trace; 28 | m_Replay = new TraceReplayStateful(trace.FileName); 29 | 30 | } 31 | 32 | private ISymbolResolver CreateResolver(TraceReplayStateful m_Replay) 33 | { 34 | var platformName = m_Replay.MetaData.PlatformName; 35 | switch (platformName) 36 | { 37 | case "Windows": 38 | case "Durango": 39 | return new DbgHelpSymbolResolver(); 40 | 41 | case "Orbis": 42 | return new OrbisSymbolResolver(); 43 | 44 | default: 45 | return null; 46 | } 47 | } 48 | 49 | private List m_LogLines = new List(); 50 | 51 | private void OnFormClosed(object sender, FormClosedEventArgs e) 52 | { 53 | m_Replay.Dispose(); 54 | } 55 | 56 | private void OnFormClosing(object sender, FormClosingEventArgs e) 57 | { 58 | if (!m_Done) 59 | { 60 | e.Cancel = true; 61 | return; 62 | } 63 | } 64 | 65 | public TraceMeta UpdatedMeta { get { return m_Replay.MetaData; } } 66 | 67 | public void UpdateProgress(string status, double pct) 68 | { 69 | this.Invoke((Action)delegate() { 70 | m_ProgressBar.Value = (int) Math.Round(pct * m_ProgressBar.Maximum); 71 | m_StatusLabel.Text = status; 72 | }); 73 | } 74 | 75 | public void UpdateMessage(string status, params object[] args) 76 | { 77 | this.Invoke((Action)delegate() { 78 | m_LogLines.Add(String.Format(status, args)); 79 | m_LogText.Lines = m_LogLines.ToArray(); 80 | m_LogText.SelectionStart = m_LogText.Text.Length; 81 | m_LogText.ScrollToCaret(); 82 | m_LogText.Refresh(); 83 | }); 84 | } 85 | 86 | public void Done() 87 | { 88 | m_Done = true; 89 | UpdateProgress("Done", 1.0); 90 | } 91 | 92 | 93 | public void UpdateError(string p) 94 | { 95 | UpdateMessage("ERROR: " + p); 96 | Done(); 97 | } 98 | 99 | private void OnFormShown(object sender, EventArgs e) 100 | { 101 | ISymbolResolver resolver = CreateResolver(m_Replay); 102 | if (resolver != null) 103 | { 104 | if (resolver.NeedsExePath) 105 | { 106 | using (var fd = new OpenFileDialog()) 107 | { 108 | fd.Title = "Select Executable File"; 109 | fd.CheckFileExists = true; 110 | var ext = resolver.ExeExtension; 111 | fd.Filter = "Executable Files (*" + ext + ")|*" + ext + "|All files(*.*)|*.*"; 112 | 113 | switch (fd.ShowDialog()) 114 | { 115 | case DialogResult.OK: 116 | resolver.BeginResolve(fd.FileName, this, m_Replay, m_Options.SymbolPaths, m_Options.ModulePathRemappings); 117 | break; 118 | default: 119 | m_Done = true; 120 | this.Close(); 121 | break; 122 | } 123 | } 124 | } 125 | else 126 | { 127 | resolver.BeginResolve(null, this, m_Replay, m_Options.SymbolPaths, m_Options.ModulePathRemappings); 128 | } 129 | } 130 | else 131 | { 132 | MessageBox.Show("Sorry, don't know how to resolve symbols for this platform yet"); 133 | m_Done = true; 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tool/MemTrace/MemTrace.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2E43CDC0-AC81-4172-85E7-4126EED64656} 8 | Library 9 | Properties 10 | MemTrace 11 | MemTrace 12 | v4.5.1 13 | 512 14 | 15 | 16 | 17 | true 18 | bin\x64\Debug\ 19 | DEBUG;TRACE 20 | full 21 | x64 22 | prompt 23 | MinimumRecommendedRules.ruleset 24 | false 25 | 26 | 27 | bin\x64\Release\ 28 | TRACE 29 | true 30 | pdbonly 31 | x64 32 | prompt 33 | MinimumRecommendedRules.ruleset 34 | false 35 | 36 | 37 | true 38 | bin\Debug\ 39 | DEBUG;TRACE 40 | full 41 | AnyCPU 42 | prompt 43 | MinimumRecommendedRules.ruleset 44 | false 45 | 46 | 47 | bin\Release\ 48 | TRACE 49 | true 50 | pdbonly 51 | AnyCPU 52 | prompt 53 | MinimumRecommendedRules.ruleset 54 | false 55 | 56 | 57 | 58 | ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll 59 | 60 | 61 | ..\packages\ObjectListView.2.7.1\lib\ObjectListView.dll 62 | 63 | 64 | ..\packages\ObjectListView.2.7.1\lib\SparkleLibrary.dll 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 94 | -------------------------------------------------------------------------------- /runtime/DemoMain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Insomniac Games All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "MemTrace.h" 27 | #include "MemTraceInit.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | static void TestCRTAllocs() 35 | { 36 | // This is ridiculous, but shows CRT allocating grabbing working. 37 | 38 | MemTrace::UserMark("CRT Test Starting"); 39 | 40 | std::map > blah; // Wee!! 41 | 42 | for (int i = 0; i < 512; ++i) 43 | { 44 | std::string key = "k"; 45 | for (int k = 0; k < 10; ++k) 46 | { 47 | blah[key].push_back("Gah!"); 48 | blah[key].push_back("This is for demo purposes to make sure we're capturing CRT allocations"); 49 | 50 | key += "a"; 51 | } 52 | } 53 | 54 | MemTrace::UserMark("CRT Test Ending"); 55 | } 56 | 57 | class BlockAllocator 58 | { 59 | struct Hdr 60 | { 61 | Hdr *m_Next; 62 | }; 63 | 64 | char* m_MemRange; 65 | Hdr* m_FreeList; 66 | size_t m_ElemSize; 67 | size_t m_ElemCount; 68 | size_t m_MemSize; 69 | MemTrace::HeapId m_HeapId; 70 | 71 | private: 72 | Hdr* GetHeader(size_t index) 73 | { 74 | char* ptr = m_MemRange + index * m_ElemSize; 75 | assert(ptr >= m_MemRange && ptr < m_MemRange + m_MemSize); 76 | return (Hdr*) ptr; 77 | } 78 | 79 | public: 80 | BlockAllocator(size_t elem_size, size_t elem_count, const char* name) 81 | { 82 | assert(elem_size >= sizeof(char*)); 83 | size_t mem_size = elem_size * elem_count; 84 | m_MemSize = mem_size; 85 | m_MemRange = (char*) malloc(mem_size); 86 | m_ElemSize = elem_size; 87 | m_ElemCount = elem_count; 88 | 89 | m_HeapId = MemTrace::HeapCreate(name); 90 | MemTrace::HeapAddCore(m_HeapId, m_MemRange, mem_size); 91 | 92 | for (size_t i = 0; i < elem_count - 1; ++i) 93 | { 94 | GetHeader(i)->m_Next = GetHeader(i + 1); 95 | } 96 | 97 | GetHeader(elem_count-1)->m_Next = nullptr; 98 | 99 | m_FreeList = GetHeader(0); 100 | } 101 | 102 | ~BlockAllocator() 103 | { 104 | MemTrace::HeapRemoveCore(m_HeapId, m_MemRange, m_ElemSize * m_ElemCount); 105 | MemTrace::HeapDestroy(m_HeapId); 106 | free(m_MemRange); 107 | } 108 | 109 | void* Alloc() 110 | { 111 | if (Hdr* hdr = m_FreeList) 112 | { 113 | m_FreeList = hdr->m_Next; 114 | MemTrace::HeapAllocate(m_HeapId, hdr, m_ElemSize); 115 | return hdr; 116 | } 117 | return nullptr; 118 | } 119 | 120 | void Free(void *ptr_) 121 | { 122 | MemTrace::HeapFree(m_HeapId, ptr_); 123 | Hdr* hdr = (Hdr*) ptr_; 124 | hdr->m_Next = m_FreeList; 125 | m_FreeList = hdr; 126 | } 127 | }; 128 | 129 | static void TestCustomAllocator() 130 | { 131 | MemTrace::UserMark("Custom Allocator Test Starting"); 132 | 133 | BlockAllocator a(16, 256, "Allocator A"); 134 | BlockAllocator b(32, 256, "Allocator B"); 135 | 136 | for (int i = 0; i < 200; ++i) 137 | { 138 | if (i & 2) a.Alloc(); 139 | if (i & 3) b.Alloc(); 140 | } 141 | 142 | MemTrace::UserMark("Custom Allocator Test Ending"); 143 | } 144 | 145 | int main(int argc, char* argv[]) 146 | { 147 | TestCRTAllocs(); 148 | 149 | TestCustomAllocator(); 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /tool/MemTrace/TraceRecorder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Net.Sockets; 6 | using System.Text; 7 | using System.Threading; 8 | using System.IO.Compression; 9 | using System.Net; 10 | 11 | namespace MemTrace 12 | { 13 | public struct ModuleInfo 14 | { 15 | public string Name; 16 | public ulong BaseAddress; 17 | public ulong SizeBytes; 18 | } 19 | 20 | public struct TraceMark 21 | { 22 | public string Name; 23 | public ulong TimeStamp; 24 | 25 | public override string ToString() 26 | { 27 | return Name; 28 | } 29 | } 30 | 31 | public interface ITraceFileHandler 32 | { 33 | object OnRecordingStarted(string filename, TraceMeta meta, TraceRecorder recorder); 34 | void OnRecordingProgress(object context, TraceMeta meta); 35 | void OnRecordingEnded(object context); 36 | } 37 | 38 | public class TraceRecorder : IDisposable 39 | { 40 | private readonly string m_FileName; 41 | private Socket m_Socket; 42 | private FileStream m_OutputFile; 43 | private object m_Lock = new object(); 44 | private readonly TraceTranscoder m_Analyzer; 45 | private readonly ITraceFileHandler m_Handler; 46 | private object m_Context; 47 | private byte[] m_Buffer = new byte[65536]; 48 | 49 | public TraceRecorder(ITraceFileHandler handler, Socket input, string output_filename) 50 | { 51 | m_Handler = handler; 52 | m_FileName = output_filename; 53 | m_OutputFile = new FileStream(output_filename, FileMode.Create, FileAccess.Write); 54 | 55 | m_Analyzer = new TraceTranscoder(m_OutputFile); 56 | 57 | m_Analyzer.MetaData.Status = TraceStatus.Recording; 58 | m_Analyzer.MetaData.SourceMachine = input.RemoteEndPoint.ToString(); 59 | 60 | m_Socket = input; 61 | m_Context = handler.OnRecordingStarted(output_filename, m_Analyzer.MetaData, this); 62 | 63 | m_Socket.BeginReceive(m_Buffer, 0, m_Buffer.Length, SocketFlags.None, OnDataRead, null); 64 | } 65 | 66 | ~TraceRecorder() 67 | { 68 | Dispose(false); 69 | } 70 | 71 | public void Dispose() 72 | { 73 | Dispose(true); 74 | } 75 | 76 | private void Dispose(bool disposing) 77 | { 78 | lock (m_Lock) 79 | { 80 | if (m_Socket != null) 81 | { 82 | m_Socket.Close(); 83 | m_Socket.Dispose(); 84 | m_Socket = null; 85 | } 86 | } 87 | 88 | if (m_OutputFile != null) 89 | { 90 | m_OutputFile.Dispose(); 91 | m_OutputFile = null; 92 | } 93 | 94 | if (disposing) 95 | { 96 | GC.SuppressFinalize(this); 97 | } 98 | } 99 | 100 | void OnDataRead(IAsyncResult res) 101 | { 102 | int bytes_read = 0; 103 | 104 | try 105 | { 106 | bytes_read = m_Socket.EndReceive(res); 107 | } 108 | catch (SocketException ex) 109 | { 110 | Debug.WriteLine("Exception: {0}", ex.Message); 111 | // Ignore - treat as EOF. 112 | } 113 | catch (EndOfStreamException ex) 114 | { 115 | Debug.WriteLine("Exception: {0}", ex.Message); 116 | // Ignore - owner has forcibly closed the socket because we're shutting down. 117 | } 118 | catch (ObjectDisposedException ex) 119 | { 120 | Debug.WriteLine("Exception: {0}", ex.Message); 121 | // Ignore - owner has forcibly closed the socket because we're shutting down. 122 | } 123 | catch (Exception ex) 124 | { 125 | Debug.WriteLine("Exception: {0}", ex.Message); 126 | } 127 | 128 | m_Analyzer.Update(m_Buffer, bytes_read); 129 | 130 | m_Handler.OnRecordingProgress(m_Context, m_Analyzer.MetaData); 131 | 132 | if (0 == bytes_read || !m_Socket.Connected) 133 | { 134 | OnEndOfInput(); 135 | } 136 | else 137 | { 138 | m_Socket.BeginReceive(m_Buffer, 0, m_Buffer.Length, SocketFlags.None, OnDataRead, null); 139 | } 140 | } 141 | 142 | void OnEndOfInput() 143 | { 144 | if (m_Socket != null) 145 | { 146 | m_Socket.Close(); 147 | } 148 | 149 | m_Analyzer.Flush(); 150 | m_OutputFile.Close(); 151 | 152 | m_Handler.OnRecordingProgress(m_Context, m_Analyzer.MetaData); 153 | m_Handler.OnRecordingEnded(m_Context); 154 | } 155 | 156 | public void Cancel() 157 | { 158 | m_Socket.Close(); 159 | } 160 | 161 | public void AddTraceMarkFromUI() 162 | { 163 | m_Analyzer.MetaData.AddMark(new TraceMark { Name = "UI Mark", TimeStamp = m_Analyzer.CurrentTimeStamp }); 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /tool/MemTraceTool/Options.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.IO; 7 | using Newtonsoft.Json; 8 | using MemTrace; 9 | 10 | namespace MemTraceTool 11 | { 12 | sealed class Options 13 | { 14 | private static readonly string RegKeyBase = @"Software\Insomniac Games\Trace Viewer"; 15 | 16 | public List SuppressedSymbols { get; private set; } 17 | public bool EnableSuppression { get; set; } 18 | public string BindAddress { get; set; } 19 | public int BindPort { get; set; } 20 | public string TraceDirectory { get; set; } 21 | public List SymbolPaths { get; private set; } 22 | public List ModulePathRemappings { get; private set; } 23 | 24 | public Options() 25 | { 26 | SuppressedSymbols = new List(); 27 | ModulePathRemappings = new List(); 28 | SymbolPaths = new List(); 29 | ModulePathRemappings = new List(); 30 | SymbolPaths = new List(); 31 | BindAddress = "0.0.0.0"; 32 | BindPort = 9811; 33 | } 34 | 35 | public Options Clone() 36 | { 37 | var result = new Options(); 38 | result.SuppressedSymbols.AddRange(SuppressedSymbols); 39 | result.EnableSuppression = EnableSuppression; 40 | result.BindAddress = BindAddress; 41 | result.BindPort = BindPort; 42 | result.TraceDirectory = TraceDirectory; 43 | result.SymbolPaths.AddRange(SymbolPaths); 44 | foreach (var m in ModulePathRemappings) 45 | { 46 | result.ModulePathRemappings.Add(m.Clone()); 47 | } 48 | return result; 49 | } 50 | 51 | private static string GetSingle(RegistryKey key, string name, string default_value) 52 | { 53 | object val = key.GetValue(name); 54 | string sval = val as string; 55 | 56 | if (sval != null) 57 | { 58 | return sval; 59 | } 60 | return default_value; 61 | } 62 | 63 | private static string[] GetMulti(RegistryKey key, string name) 64 | { 65 | object vals = key.GetValue(name); 66 | string[] array = vals as string[]; 67 | 68 | if (array != null) 69 | { 70 | return array; 71 | } 72 | return new string[] { }; 73 | } 74 | 75 | public bool LoadFromRegistry() 76 | { 77 | using (var key = Registry.CurrentUser.OpenSubKey(RegKeyBase)) 78 | { 79 | if (null == key) 80 | return false; 81 | 82 | SuppressedSymbols.AddRange(GetMulti(key, "SuppressedSymbols")); 83 | EnableSuppression = Boolean.Parse(GetSingle(key, "EnableSuppression", "false")); 84 | BindAddress = GetSingle(key, "BindAddress", "0.0.0.0"); 85 | BindPort = Int32.Parse(GetSingle(key, "BindPort", "9811")); 86 | TraceDirectory = GetSingle(key, "TraceDirectory", null); 87 | foreach (var s in GetMulti(key, "ModulePathRemappings")) 88 | { 89 | var elems = s.Split('|'); 90 | ModulePathRemappings.Add(new ModulePathRemapping 91 | { 92 | Platform = elems[0], 93 | Path = elems[1], 94 | ReplacementPath = elems[2] 95 | }); 96 | } 97 | SymbolPaths.AddRange(GetMulti(key, "SymbolPaths")); 98 | return true; 99 | } 100 | } 101 | 102 | public void SaveToRegistry() 103 | { 104 | using (var key = Registry.CurrentUser.CreateSubKey(RegKeyBase)) 105 | { 106 | key.SetValue("SuppressedSymbols", SuppressedSymbols.ToArray()); 107 | key.SetValue("EnableSuppression", EnableSuppression.ToString()); 108 | key.SetValue("BindAddress", BindAddress.ToString()); 109 | key.SetValue("BindPort", BindPort.ToString()); 110 | key.SetValue("TraceDirectory", TraceDirectory.ToString()); 111 | var vals = new List(); 112 | foreach (var rm in ModulePathRemappings) 113 | { 114 | vals.Add(String.Format("{0}|{1}|{2}", rm.Platform, rm.Path, rm.ReplacementPath)); 115 | } 116 | key.SetValue("ModulePathRemappings", vals.ToArray()); 117 | key.SetValue("SymbolPaths", SymbolPaths.ToArray()); 118 | } 119 | } 120 | 121 | public static Options LoadFromFile(string fn) 122 | { 123 | return (Options) JsonConvert.DeserializeObject(File.ReadAllText(fn), typeof(Options)); 124 | } 125 | 126 | public void SaveToFile(string fn) 127 | { 128 | string data = JsonConvert.SerializeObject(this, typeof(Options), new JsonSerializerSettings { Formatting = Formatting.Indented } ); 129 | File.WriteAllText(fn, data, Encoding.UTF8); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /runtime/MemTraceInit.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Insomniac Games All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | 28 | // MemTraceInit.h 29 | // 30 | // Initialization code to start MemTrace as early as possible, before any CRT 31 | // allocations are done ideally. This is highly compiler specific. Consider 32 | // these two examples as inspiration. 33 | 34 | #include "MemTrace.h" 35 | 36 | #if defined(MEMTRACE_ENABLE) 37 | 38 | #include 39 | 40 | #if defined(MEMTRACE_USE_TEMP_FILE) 41 | // Platform agnostic and uses a temporary file. 42 | // Always starts tracing to the temporary file. 43 | // Application code should check command line options itself and either call 44 | // MemTrace::InitSocket() (to upgrade to a socket connection) or 45 | // MemTrace::Shutdown() to abandon the temporary file 46 | struct MemTraceInitObject 47 | { 48 | MemTraceInitObject() 49 | { 50 | MemTrace::InitFile("memtrace.tmp"); 51 | } 52 | 53 | ~MemTraceInitObject() 54 | { 55 | MemTrace::Shutdown(); 56 | } 57 | }; 58 | 59 | MemTraceInitObject __attribute__((init_priority(101))) g_MemTraceInit; 60 | 61 | #elif defined(__ORBIS__) 62 | // Example startup handler for Orbis. Checks for -memtrace on the command line. 63 | struct MemTraceInitObject 64 | { 65 | MemTraceInitObject() 66 | { 67 | int argc = getargc(); 68 | char** argv= getargv(); 69 | for (int i = 0; i < argc; ++i) 70 | { 71 | if (0 == strcmp("-memtrace", argv[i]) && i + 1 < argc) 72 | { 73 | MemTrace::InitSocket(argv[i + 1], 9811); 74 | break; 75 | } 76 | } 77 | } 78 | 79 | ~MemTraceInitObject() 80 | { 81 | MemTrace::Shutdown(); 82 | } 83 | }; 84 | MemTraceInitObject __attribute__((init_priority(101))) g_MemTraceInit; 85 | 86 | #elif defined(_MSC_VER) 87 | 88 | #include 89 | #include 90 | 91 | // Example startup handler for Windows. Checks for -memtrace on the command line. 92 | struct MemTraceInitObject 93 | { 94 | MemTraceInitObject() 95 | { 96 | const wchar_t* cmdline = GetCommandLineW(); 97 | static const wchar_t prefix[] = L"-memtrace "; 98 | if (const wchar_t* arg = wcsstr(cmdline, prefix)) 99 | { 100 | wchar_t ip_addr_u[64]; 101 | wcsncpy_s(ip_addr_u, sizeof(ip_addr_u)/sizeof(ip_addr_u[0]), arg + (sizeof(prefix)/sizeof(prefix[0])) - 1, _TRUNCATE); 102 | if (wchar_t* space = wcschr(ip_addr_u, L' ')) 103 | *space = L'\0'; 104 | 105 | char ip_addr[64]; 106 | wcstombs_s( NULL, ip_addr, sizeof(ip_addr), ip_addr_u, _TRUNCATE ); 107 | 108 | MemTrace::InitSocket(ip_addr, 9811); 109 | } 110 | } 111 | 112 | ~MemTraceInitObject() 113 | { 114 | MemTrace::Shutdown(); 115 | } 116 | }; 117 | 118 | #pragma warning(disable:4074) 119 | #pragma init_seg(compiler) 120 | MemTraceInitObject g_MemTraceInit; 121 | 122 | #elif defined(MEMTRACE_USE_ARGC_ARGV) 123 | // Platform agnostic, but assumes we can get to __argc and __argv before static initializers. 124 | // Checks for -memtrace on the command line. 125 | struct MemTraceInitObject 126 | { 127 | MemTraceInitObject() 128 | { 129 | extern char **__argv; 130 | extern int __argc; 131 | int argc = __argc; 132 | char** argv= __argv; 133 | for (int i = 0; i < argc; ++i) 134 | { 135 | if (0 == strcmp("-memtrace", argv[i]) && i + 1 < argc) 136 | { 137 | MemTrace::InitSocket(argv[i + 1], 9811); 138 | break; 139 | } 140 | } 141 | } 142 | 143 | ~MemTraceInitObject() 144 | { 145 | MemTrace::Shutdown(); 146 | } 147 | }; 148 | 149 | MemTraceInitObject __attribute__((init_priority(101))) g_MemTraceInit; 150 | 151 | #else 152 | #error Sorry, no compatible init protocol for this platform. Make your own! 153 | #endif 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /tool/MemTraceTool/RangeQueryWindow.cs: -------------------------------------------------------------------------------- 1 | using MemTrace; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Globalization; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Forms; 12 | 13 | namespace MemTraceTool 14 | { 15 | public partial class RangeQueryWindow : Form, IMemEventHandler 16 | { 17 | public RangeQueryWindow(string trace_fn) 18 | { 19 | m_FileName = trace_fn; 20 | 21 | InitializeComponent(); 22 | } 23 | 24 | /// 25 | /// Clean up any resources being used. 26 | /// 27 | /// true if managed resources should be disposed; otherwise, false. 28 | protected override void Dispose(bool disposing) 29 | { 30 | if (disposing) 31 | { 32 | if (components != null) 33 | { 34 | components.Dispose(); 35 | } 36 | } 37 | 38 | base.Dispose(disposing); 39 | } 40 | 41 | private ulong m_Start; 42 | private ulong m_End; 43 | 44 | private void SearchButton_Click(object sender, EventArgs e) 45 | { 46 | try 47 | { 48 | var sat = m_StartAddress.Text; 49 | var szt = m_SizeBytes.Text; 50 | 51 | var size = 0ul; 52 | 53 | if (sat.StartsWith("0x", true, CultureInfo.InvariantCulture)) 54 | { 55 | sat = sat.Substring(2); 56 | } 57 | 58 | m_Start = Convert.ToUInt64(sat, 16); 59 | 60 | if (szt.StartsWith("0x", true, CultureInfo.InvariantCulture)) 61 | { 62 | size = Convert.ToUInt64(szt.Substring(2), 16); 63 | } 64 | else 65 | { 66 | size = Convert.ToUInt64(szt, 10); 67 | } 68 | 69 | m_End = m_Start + size; 70 | } 71 | catch (Exception) 72 | { 73 | MessageBox.Show("Invalid number format"); 74 | return; 75 | } 76 | 77 | m_StatusText.Text = "Replaying trace file.."; 78 | m_SearchButton.Enabled = false; 79 | m_SearchResults.SetObjects(new Result[0]); 80 | m_SearchTask = Task.Run(() => { 81 | try 82 | { 83 | using (TraceReplayEventBased r = new TraceReplayEventBased(m_FileName)) 84 | { 85 | r.StreamEvents(this); 86 | this.OnSearchComplete(); 87 | } 88 | } 89 | catch (Exception ex) 90 | { 91 | this.OnSearchError(ex.Message); 92 | } 93 | }); 94 | } 95 | 96 | private void OnSearchError(string p) 97 | { 98 | this.Invoke(new Action(() => 99 | { 100 | m_StatusText.Text = String.Format("Error: {0}", p); 101 | m_ProgressBar.Value = 0; 102 | m_TrackedAddresses.Clear(); 103 | m_SearchTask = null; 104 | m_SearchButton.Enabled = true; 105 | })); 106 | } 107 | 108 | private void OnSearchComplete() 109 | { 110 | this.Invoke(new Action(() => 111 | { 112 | m_StatusText.Text = "Done"; 113 | m_ProgressBar.Value = 0; 114 | m_TrackedAddresses.Clear(); 115 | m_SearchTask = null; 116 | m_SearchButton.Enabled = true; 117 | })); 118 | } 119 | 120 | private sealed class Result 121 | { 122 | public string EventType { get; set; } 123 | public ulong Address { get; set; } 124 | public ulong Size { get; set; } 125 | public StackBackTrace BackTrace { get; set; } 126 | public double Time { get; set; } 127 | } 128 | 129 | private Dictionary m_TrackedAddresses = new Dictionary(); 130 | private Task m_SearchTask; 131 | private string m_FileName; 132 | 133 | void IMemEventHandler.OnHeapAllocate(ulong ptr, ulong size, int scope_type, string scope_data_str, StackBackTrace backtrace, double time) 134 | { 135 | if (ptr + size > m_Start && ptr < m_End) 136 | { 137 | m_SearchResults.AddObject(new Result { EventType = "Allocate", Address = ptr, Size = size, BackTrace = backtrace, Time = time }); 138 | m_TrackedAddresses.Add(ptr, size); 139 | } 140 | } 141 | 142 | void IMemEventHandler.OnHeapFree(ulong ptr, StackBackTrace backtrace, double time) 143 | { 144 | ulong size; 145 | if (m_TrackedAddresses.TryGetValue(ptr, out size)) 146 | { 147 | m_SearchResults.AddObject(new Result { EventType = "Free", Address = ptr, Size = size, BackTrace = backtrace, Time = time }); 148 | m_TrackedAddresses.Remove(ptr); 149 | } 150 | } 151 | 152 | void IMemEventHandler.OnProgress(double ratio) 153 | { 154 | this.Invoke(new Action(()=> { 155 | this.m_ProgressBar.Value = (int)Math.Max(Math.Min(ratio * this.m_ProgressBar.Maximum, this.m_ProgressBar.Maximum), 0.0); 156 | })); 157 | } 158 | 159 | private void OnToolTipShowing(object sender, BrightIdeasSoftware.ToolTipShowingEventArgs e) 160 | { 161 | var b = new StringBuilder(); 162 | var f = (Result) e.Model; 163 | foreach (var frame in f.BackTrace.Frames) 164 | { 165 | b.AppendFormat(" {0} ({1}:{2})\r\n", frame.Symbol, frame.FileName, frame.LineNumber); 166 | } 167 | e.Title = "Stack Backtrace"; 168 | e.Text = b.ToString(); 169 | } 170 | 171 | private void OnCancel(object sender, EventArgs e) 172 | { 173 | 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /runtime/MemTraceSys.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Insomniac Games All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "MemTraceSys.h" 27 | 28 | #if defined(MEMTRACE_UNIX) 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #endif 38 | 39 | #if defined(MEMTRACE_WINDOWS) 40 | #include 41 | #endif 42 | 43 | #if defined(MEMTRACE_MAC) 44 | #include // for backtrace(3) 45 | #endif 46 | 47 | #if defined(MEMTRACE_MAC) 48 | const char MemTrace::kPlatformName[] = "MacOS X"; 49 | #elif defined(MEMTRACE_FREEBSD) 50 | const char MemTrace::kPlatformName[] = "FreeBSD"; 51 | #elif defined(MEMTRACE_LINUX) 52 | const char MemTrace::kPlatformName[] = "Linux"; 53 | #elif defined(MEMTRACE_WINDOWS) 54 | const char MemTrace::kPlatformName[] = "Windows"; 55 | #endif 56 | 57 | void MemTrace::Strcpy(char* dest, size_t dest_size, const char* src) 58 | { 59 | size_t capacity = dest_size - 1; 60 | while (capacity--) 61 | { 62 | char ch = *src++; 63 | if (!ch) 64 | break; 65 | *dest++ = ch; 66 | } 67 | *dest++ = '\0'; 68 | } 69 | 70 | #if defined(MEMTRACE_UNIX) 71 | int64_t MemTrace::TimerGetSystemCounter() 72 | { 73 | struct timeval tv; 74 | gettimeofday(&tv, nullptr); 75 | return int64_t(tv.tv_sec) * 1000000 + tv.tv_usec; 76 | } 77 | 78 | int64_t MemTrace::TimerGetSystemFrequencyInt() 79 | { 80 | return 1000000; 81 | } 82 | 83 | void MemTrace::closesocket(SOCKET s) 84 | { 85 | close(s); 86 | } 87 | 88 | MemTrace::FileHandle MemTrace::FileOpenForReadWrite(const char* fn) 89 | { 90 | return open(fn, O_RDWR|O_CREAT, 0666); 91 | } 92 | 93 | void MemTrace::FileWrite(FileHandle fh, const void* data, size_t size) 94 | { 95 | write(fh, data, size); 96 | } 97 | 98 | void MemTrace::FileClose(FileHandle fh) 99 | { 100 | close(fh); 101 | } 102 | 103 | void MemTrace::FileSeekTo(FileHandle fh, int64_t pos) 104 | { 105 | lseek(fh, pos, SEEK_SET); 106 | } 107 | 108 | int64_t MemTrace::FileSize(FileHandle fh) 109 | { 110 | struct stat st; 111 | fstat(fh, &st); 112 | return st.st_size; 113 | } 114 | 115 | void MemTrace::FileRead(FileHandle fh, void* buffer, size_t size) 116 | { 117 | read(fh, buffer, size); 118 | } 119 | 120 | int MemTrace::Vsnprintf(char* buffer, size_t buffer_size, const char* fmt, va_list args) 121 | { 122 | int rc = vsnprintf(buffer, buffer_size, fmt, args); 123 | 124 | if (rc > buffer_size) 125 | return (int) buffer_size; 126 | else 127 | return rc; 128 | } 129 | 130 | void MemTrace::OutputDebugStringA(const char* str) 131 | { 132 | write(1, str, strlen(str)); 133 | } 134 | #endif 135 | 136 | #if defined(MEMTRACE_WINDOWS) 137 | int64_t MemTrace::TimerGetSystemFrequencyInt() 138 | { 139 | static int64_t s_TimerFrequency = 0; 140 | 141 | if (s_TimerFrequency != 0) 142 | { 143 | return s_TimerFrequency; 144 | } 145 | 146 | // Query the performance of the Windows high resolution timer. 147 | QueryPerformanceFrequency((LARGE_INTEGER*)&s_TimerFrequency); 148 | 149 | return s_TimerFrequency; 150 | } 151 | 152 | int64_t MemTrace::TimerGetSystemCounter() 153 | { 154 | int64_t ticks; 155 | QueryPerformanceCounter((LARGE_INTEGER*)&ticks); 156 | return ticks; 157 | } 158 | 159 | MemTrace::FileHandle MemTrace::FileOpenForReadWrite(const char* fn) 160 | { 161 | return CreateFileA(fn, FILE_GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 162 | } 163 | 164 | void MemTrace::FileWrite(FileHandle fh, const void* data, size_t size) 165 | { 166 | ::WriteFile(fh, data, (DWORD) size, NULL, NULL); 167 | } 168 | 169 | void MemTrace::FileClose(FileHandle fh) 170 | { 171 | ::CloseHandle(fh); 172 | } 173 | 174 | void MemTrace::FileSeekTo(FileHandle fh, int64_t pos) 175 | { 176 | LARGE_INTEGER l; 177 | l.QuadPart = pos; 178 | SetFilePointerEx(fh, l, NULL, FILE_BEGIN); 179 | } 180 | 181 | int64_t MemTrace::FileSize(FileHandle fh) 182 | { 183 | LARGE_INTEGER val; 184 | GetFileSizeEx(fh, &val); 185 | return val.QuadPart; 186 | } 187 | 188 | void MemTrace::FileRead(FileHandle fh, void* buffer, size_t size) 189 | { 190 | DWORD bytes_read; 191 | ::ReadFile(fh, buffer, (DWORD) size, &bytes_read, NULL); 192 | } 193 | 194 | int MemTrace::Vsnprintf(char* buffer, size_t buffer_size, const char* fmt, va_list args) 195 | { 196 | int rc = _vsnprintf(buffer, buffer_size, fmt, args); 197 | 198 | if (rc < 0) 199 | return (int) strlen(buffer); 200 | else 201 | return rc; 202 | } 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /tool/MemTraceTool/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/TimeControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTrace.Widgets 2 | { 3 | partial class TimeControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.m_Label = new System.Windows.Forms.Label(); 32 | this.m_Time = new System.Windows.Forms.ComboBox(); 33 | this.m_Rev2Button = new System.Windows.Forms.Button(); 34 | this.m_Rev1Button = new System.Windows.Forms.Button(); 35 | this.m_Fwd2Button = new System.Windows.Forms.Button(); 36 | this.m_Fwd1Button = new System.Windows.Forms.Button(); 37 | this.SuspendLayout(); 38 | // 39 | // m_Label 40 | // 41 | this.m_Label.AutoSize = true; 42 | this.m_Label.Location = new System.Drawing.Point(-3, 9); 43 | this.m_Label.Name = "m_Label"; 44 | this.m_Label.Size = new System.Drawing.Size(30, 13); 45 | this.m_Label.TabIndex = 0; 46 | this.m_Label.Text = "Time"; 47 | // 48 | // m_Time 49 | // 50 | this.m_Time.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 51 | | System.Windows.Forms.AnchorStyles.Right))); 52 | this.m_Time.FormattingEnabled = true; 53 | this.m_Time.Location = new System.Drawing.Point(33, 5); 54 | this.m_Time.Name = "m_Time"; 55 | this.m_Time.Size = new System.Drawing.Size(406, 21); 56 | this.m_Time.TabIndex = 1; 57 | this.m_Time.SelectionChangeCommitted += new System.EventHandler(this.OnTimeValueSelected); 58 | this.m_Time.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnComboKeyDown); 59 | // 60 | // m_Rev2Button 61 | // 62 | this.m_Rev2Button.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 63 | this.m_Rev2Button.Location = new System.Drawing.Point(445, 4); 64 | this.m_Rev2Button.Name = "m_Rev2Button"; 65 | this.m_Rev2Button.Size = new System.Drawing.Size(34, 23); 66 | this.m_Rev2Button.TabIndex = 3; 67 | this.m_Rev2Button.Text = "<<"; 68 | this.m_Rev2Button.UseVisualStyleBackColor = true; 69 | this.m_Rev2Button.Click += new System.EventHandler(this.OnRev2Button_Click); 70 | // 71 | // m_Rev1Button 72 | // 73 | this.m_Rev1Button.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 74 | this.m_Rev1Button.Location = new System.Drawing.Point(486, 4); 75 | this.m_Rev1Button.Name = "m_Rev1Button"; 76 | this.m_Rev1Button.Size = new System.Drawing.Size(34, 23); 77 | this.m_Rev1Button.TabIndex = 4; 78 | this.m_Rev1Button.Text = "<"; 79 | this.m_Rev1Button.UseVisualStyleBackColor = true; 80 | this.m_Rev1Button.Click += new System.EventHandler(this.OnRev1Button_Click); 81 | // 82 | // m_Fwd2Button 83 | // 84 | this.m_Fwd2Button.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 85 | this.m_Fwd2Button.Location = new System.Drawing.Point(574, 4); 86 | this.m_Fwd2Button.Name = "m_Fwd2Button"; 87 | this.m_Fwd2Button.Size = new System.Drawing.Size(34, 23); 88 | this.m_Fwd2Button.TabIndex = 6; 89 | this.m_Fwd2Button.Text = ">>"; 90 | this.m_Fwd2Button.UseVisualStyleBackColor = true; 91 | this.m_Fwd2Button.Click += new System.EventHandler(this.OnFwd2Button_Click); 92 | // 93 | // m_Fwd1Button 94 | // 95 | this.m_Fwd1Button.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 96 | this.m_Fwd1Button.Location = new System.Drawing.Point(533, 4); 97 | this.m_Fwd1Button.Name = "m_Fwd1Button"; 98 | this.m_Fwd1Button.Size = new System.Drawing.Size(34, 23); 99 | this.m_Fwd1Button.TabIndex = 5; 100 | this.m_Fwd1Button.Text = ">"; 101 | this.m_Fwd1Button.UseVisualStyleBackColor = true; 102 | this.m_Fwd1Button.Click += new System.EventHandler(this.OnFwd1Button_Click); 103 | // 104 | // TimeControl 105 | // 106 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 107 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 108 | this.Controls.Add(this.m_Fwd2Button); 109 | this.Controls.Add(this.m_Fwd1Button); 110 | this.Controls.Add(this.m_Rev1Button); 111 | this.Controls.Add(this.m_Rev2Button); 112 | this.Controls.Add(this.m_Time); 113 | this.Controls.Add(this.m_Label); 114 | this.Name = "TimeControl"; 115 | this.Size = new System.Drawing.Size(609, 32); 116 | this.ResumeLayout(false); 117 | this.PerformLayout(); 118 | 119 | } 120 | 121 | #endregion 122 | 123 | private System.Windows.Forms.Label m_Label; 124 | private System.Windows.Forms.ComboBox m_Time; 125 | private System.Windows.Forms.Button m_Rev2Button; 126 | private System.Windows.Forms.Button m_Rev1Button; 127 | private System.Windows.Forms.Button m_Fwd2Button; 128 | private System.Windows.Forms.Button m_Fwd1Button; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/TimeControl.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /tool/MemTraceTool/FragmentationWidget.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/FragmentationWidget.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /tool/MemTrace/AsyncStreamPump.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net.Sockets; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace MemTrace 12 | { 13 | interface IAsyncStreamHandler 14 | { 15 | void DataRead(byte[] data, int length); 16 | void IOCompleted(); 17 | } 18 | 19 | sealed class AsyncStreamPump 20 | { 21 | private readonly object m_Lock = new object(); 22 | private readonly Socket m_InputStream; 23 | private readonly Stream m_OutputStream; 24 | private readonly IAsyncStreamHandler m_Handler; 25 | 26 | private enum BufferState 27 | { 28 | Invalid, 29 | Reading, 30 | Read, 31 | Writing 32 | } 33 | 34 | private class Buffer 35 | { 36 | public readonly byte[] Bytes; 37 | 38 | public int Index { get; set; } 39 | public int ValidSize { get; set; } 40 | public BufferState State { get; set; } 41 | 42 | public Buffer(int size) 43 | { 44 | Bytes = new byte[size]; 45 | } 46 | } 47 | 48 | private int m_ReadIndex = 0; 49 | private int m_WriteIndex = 0; 50 | private int m_PendingReadCount = 0; 51 | private int m_PendingWriteCount = 0; 52 | 53 | private readonly Buffer[] m_Buffers; 54 | private bool m_EndOfInput; 55 | private bool m_EndOfOutput; 56 | 57 | public AsyncStreamPump(Socket input, Stream output, int buffer_size, IAsyncStreamHandler handler) 58 | { 59 | m_InputStream = input; 60 | m_OutputStream = output; 61 | m_Handler = handler; 62 | 63 | m_Buffers = new Buffer[2]; 64 | for (int i = 0; i < 2; ++i) 65 | { 66 | m_Buffers[i] = new Buffer(buffer_size); 67 | m_Buffers[i].Index = i; 68 | } 69 | 70 | KickRead(); 71 | } 72 | 73 | private Buffer GetNextReadBuffer() 74 | { 75 | Buffer result = null; 76 | if (m_Buffers[m_ReadIndex].State == BufferState.Invalid) 77 | { 78 | result = m_Buffers[m_ReadIndex]; 79 | m_ReadIndex = (m_ReadIndex + 1) & (m_Buffers.Length - 1); 80 | } 81 | return result; 82 | } 83 | 84 | private Buffer GetNextWriteBuffer() 85 | { 86 | Buffer result = null; 87 | if (m_Buffers[m_WriteIndex].State == BufferState.Read) 88 | { 89 | result = m_Buffers[m_WriteIndex]; 90 | m_WriteIndex = (m_WriteIndex + 1) & (m_Buffers.Length - 1); 91 | } 92 | return result; 93 | } 94 | 95 | private void KickRead() 96 | { 97 | if (0 != m_PendingReadCount || m_EndOfInput || !m_InputStream.Connected) 98 | return; 99 | 100 | var buf = GetNextReadBuffer(); 101 | if (buf != null) 102 | { 103 | ++m_PendingReadCount; 104 | buf.State = BufferState.Reading; 105 | m_InputStream.BeginReceive(buf.Bytes, 0, buf.Bytes.Length, SocketFlags.None, OnReadCompleted, buf); 106 | } 107 | } 108 | 109 | private void KickWrite() 110 | { 111 | if (0 != m_PendingWriteCount) 112 | return; 113 | 114 | var buf = GetNextWriteBuffer(); 115 | if (buf != null) 116 | { 117 | ++m_PendingWriteCount; 118 | buf.State = BufferState.Writing; 119 | m_OutputStream.BeginWrite(buf.Bytes, 0, buf.ValidSize, OnWriteCompleted, buf); 120 | } 121 | } 122 | 123 | private void OnReadCompleted(IAsyncResult ar) 124 | { 125 | lock (m_Lock) 126 | { 127 | Buffer buf = (Buffer)ar.AsyncState; 128 | int bytes_read = 0; 129 | Debug.Assert(buf.State == BufferState.Reading); 130 | 131 | try 132 | { 133 | bytes_read = m_InputStream.EndReceive(ar); 134 | } 135 | catch (SocketException ex) 136 | { 137 | Debug.WriteLine("Exception: {0}", ex.Message); 138 | // Ignore - treat as EOF. 139 | } 140 | catch (EndOfStreamException ex) 141 | { 142 | Debug.WriteLine("Exception: {0}", ex.Message); 143 | // Ignore - owner has forcibly closed the socket because we're shutting down. 144 | } 145 | catch (ObjectDisposedException ex) 146 | { 147 | Debug.WriteLine("Exception: {0}", ex.Message); 148 | // Ignore - owner has forcibly closed the socket because we're shutting down. 149 | } 150 | catch (Exception ex) 151 | { 152 | Debug.WriteLine("Exception: {0}", ex.Message); 153 | } 154 | 155 | --m_PendingReadCount; 156 | buf.ValidSize = bytes_read; 157 | buf.State = BufferState.Read; 158 | 159 | m_Handler.DataRead(buf.Bytes, bytes_read); 160 | 161 | if (0 == bytes_read) 162 | { 163 | OnEndOfInput(); 164 | if (m_PendingWriteCount == 0) 165 | { 166 | OnEndOfOutput(); 167 | } 168 | return; 169 | } 170 | 171 | KickWrite(); 172 | KickRead(); 173 | } 174 | } 175 | 176 | private void OnEndOfInput() 177 | { 178 | m_EndOfInput = true; 179 | 180 | if (0 == m_PendingWriteCount) 181 | { 182 | m_Handler.IOCompleted(); 183 | } 184 | } 185 | 186 | private void OnWriteCompleted(IAsyncResult ar) 187 | { 188 | lock (m_Lock) 189 | { 190 | Buffer buf = (Buffer)ar.AsyncState; 191 | Debug.Assert(buf.State == BufferState.Writing); 192 | m_OutputStream.EndWrite(ar); 193 | --m_PendingWriteCount; 194 | buf.State = BufferState.Invalid; 195 | 196 | if (!m_EndOfInput && !m_InputStream.Connected && 0 == m_PendingReadCount) 197 | { 198 | OnEndOfInput(); 199 | } 200 | 201 | if (m_EndOfInput) 202 | { 203 | OnEndOfOutput(); 204 | } 205 | else 206 | { 207 | KickRead(); 208 | KickWrite(); 209 | } 210 | } 211 | } 212 | 213 | private void OnEndOfOutput() 214 | { 215 | m_EndOfOutput = true; 216 | Monitor.Pulse(m_Lock); 217 | } 218 | 219 | 220 | internal void Shutdown() 221 | { 222 | lock (m_Lock) 223 | { 224 | while (!m_EndOfOutput) 225 | { 226 | Monitor.Wait(m_Lock); 227 | }; 228 | } 229 | } 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/WidgetResources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | dots.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/MemTraceWidgets.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {DE94B6DF-8E75-4623-A12C-BE2A1756A128} 8 | Library 9 | Properties 10 | MemTrace.Widgets 11 | MemTrace.Widgets 12 | v4.5.1 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | AnyCPU 25 | false 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | AnyCPU 35 | false 36 | 37 | 38 | true 39 | bin\x64\Debug\ 40 | DEBUG;TRACE 41 | full 42 | x64 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | false 46 | 47 | 48 | bin\x64\Release\ 49 | TRACE 50 | true 51 | pdbonly 52 | x64 53 | prompt 54 | MinimumRecommendedRules.ruleset 55 | false 56 | 57 | 58 | 59 | ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll 60 | 61 | 62 | ..\packages\ObjectListView.2.7.1\lib\ObjectListView.dll 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | UserControl 77 | 78 | 79 | FragmentationWidget.cs 80 | 81 | 82 | UserControl 83 | 84 | 85 | HeapTreeList.cs 86 | 87 | 88 | UserControl 89 | 90 | 91 | MemBlockView.cs 92 | 93 | 94 | 95 | 96 | True 97 | True 98 | WidgetResources.resx 99 | 100 | 101 | UserControl 102 | 103 | 104 | TimeControl.cs 105 | 106 | 107 | 108 | 109 | 110 | FragmentationWidget.cs 111 | 112 | 113 | HeapTreeList.cs 114 | 115 | 116 | ResXFileCodeGenerator 117 | WidgetResources.Designer.cs 118 | 119 | 120 | TimeControl.cs 121 | 122 | 123 | 124 | 125 | {2e43cdc0-ac81-4172-85e7-4126eed64656} 126 | MemTrace 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 145 | -------------------------------------------------------------------------------- /tool/MemTrace/OrbisSymbolResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Globalization; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace MemTrace 11 | { 12 | public sealed class OrbisSymbolResolver : ISymbolResolver 13 | { 14 | private static readonly string s_MangledWellKnownSymbol = "_ZN8MemTraceL10InitCommonEPFvPKvmE"; 15 | 16 | public bool NeedsExePath { get { return true; } } 17 | public string ExeExtension { get { return ".elf"; } } 18 | 19 | public void BeginResolve(string exePath, ISymbolProgressListener listener, TraceReplayStateful replay, ICollection symbolPaths, ICollection remappings) 20 | { 21 | Task.Run(() => 22 | { 23 | try 24 | { 25 | string sdkDir = Environment.GetEnvironmentVariable("SCE_ORBIS_SDK_DIR"); 26 | 27 | if (null == sdkDir) 28 | throw new ApplicationException("Environment variable SCE_ORBIS_SDK_DIR not set"); 29 | 30 | // Figure out the base address of the ELF 31 | ulong baseAddress = GetElfBaseAddress(listener, replay, exePath, sdkDir); 32 | 33 | ResolveSymbols(listener, replay, exePath, sdkDir, baseAddress); 34 | 35 | listener.Done(); 36 | } 37 | catch (Exception ex) 38 | { 39 | listener.UpdateError(ex.Message); 40 | } 41 | }); 42 | } 43 | 44 | private static ulong GetElfBaseAddress(ISymbolProgressListener listener, TraceReplayStateful replay, string elfFile, string sdkDir) 45 | { 46 | ulong wellKnownAddress = 0; 47 | 48 | listener.UpdateMessage("Finding symbol MemTrace::InitCommon in the ELF.."); 49 | 50 | var procInfo = new ProcessStartInfo 51 | { 52 | Arguments = String.Format("\"{0}\"", elfFile), 53 | UseShellExecute = false, 54 | WindowStyle = ProcessWindowStyle.Hidden, 55 | CreateNoWindow = true, 56 | FileName = Path.Combine(sdkDir, @"host_tools\bin\orbis-nm.exe"), 57 | RedirectStandardOutput = true 58 | }; 59 | 60 | using (var nm = Process.Start(procInfo)) 61 | { 62 | for (; ; ) 63 | { 64 | string line = nm.StandardOutput.ReadLine(); 65 | 66 | if (null == line) 67 | break; 68 | 69 | if (line.EndsWith(s_MangledWellKnownSymbol)) 70 | { 71 | wellKnownAddress = UInt64.Parse(line.Split()[0], NumberStyles.HexNumber); 72 | nm.Kill(); 73 | } 74 | } 75 | } 76 | 77 | listener.UpdateMessage("MemTrace::InitCommon at ELF address 0x{0:x16}, runtime 0x{1:x16}", wellKnownAddress, replay.MetaData.MemTraceInitCommonAddress); 78 | 79 | ulong baseAddress = replay.MetaData.MemTraceInitCommonAddress - wellKnownAddress; 80 | listener.UpdateMessage("ELF base address set to 0x{0:x16}", baseAddress); 81 | 82 | return baseAddress; 83 | } 84 | 85 | private void ResolveSymbols(ISymbolProgressListener listener, TraceReplayStateful replay, string elfFile, string sdkDir, ulong elfBase) 86 | { 87 | var result = new Dictionary(); 88 | 89 | var procInfo = new ProcessStartInfo 90 | { 91 | // Need to merge stdout and stderr together 92 | Arguments = String.Format("--infile=\"{0}\" -a2l", elfFile), 93 | UseShellExecute = false, 94 | WindowStyle = ProcessWindowStyle.Hidden, 95 | CreateNoWindow = true, 96 | FileName = Path.Combine(sdkDir, @"host_tools\bin\orbis-bin.exe"), 97 | RedirectStandardInput = true, 98 | RedirectStandardOutput = true, 99 | RedirectStandardError = true, 100 | }; 101 | 102 | var stdout = new List(); 103 | 104 | using (var proc = Process.Start(procInfo)) 105 | { 106 | proc.OutputDataReceived += (object sender, DataReceivedEventArgs args) => 107 | { 108 | if (!String.IsNullOrEmpty(args.Data) && !args.Data.StartsWith("WARNING:")) 109 | stdout.Add(args.Data); 110 | }; 111 | 112 | proc.ErrorDataReceived += (object sender, DataReceivedEventArgs args) => 113 | { 114 | // Throw it on the floor. 115 | }; 116 | 117 | proc.BeginOutputReadLine(); 118 | proc.BeginErrorReadLine(); 119 | 120 | int x = 0; 121 | var lastUpdate = DateTime.Now; 122 | var updateThres = new TimeSpan(0, 0, 0, 0, 100); 123 | 124 | foreach (ulong address in replay.MetaData.Symbols) 125 | { 126 | if (x % 100 == 0 || DateTime.Now - lastUpdate > updateThres) 127 | { 128 | listener.UpdateProgress(String.Format("Resolving symbol {0}/{1}..", x + 1, replay.MetaData.Symbols.Count), (x + 1) / (double)replay.MetaData.Symbols.Count); 129 | lastUpdate = DateTime.Now; 130 | } 131 | 132 | if (address != 0) 133 | { 134 | proc.StandardInput.WriteLine("0x{0:x16}", address - elfBase); 135 | } 136 | 137 | ++x; 138 | } 139 | 140 | proc.StandardInput.Close(); 141 | proc.WaitForExit(); 142 | } 143 | 144 | // Now deal with orbis-bin's wonky output format 145 | for (int k = 0; k < stdout.Count; ) 146 | { 147 | var addrStr = MatchPrefix(stdout[k++], "Address:"); 148 | ulong addr = UInt64.Parse(addrStr.Substring(2), NumberStyles.HexNumber); 149 | string directory = MatchPrefix(stdout[k++], "Directory:").Replace('/', Path.DirectorySeparatorChar); 150 | string filename = MatchPrefix(stdout[k++], "File Name:"); 151 | 152 | var sym = new SymbolInfo(); 153 | 154 | sym.Address = addr + elfBase; 155 | if (filename != "??") 156 | sym.FileName = Path.Combine(directory, filename); 157 | else 158 | sym.FileName = "Unknown"; 159 | sym.LineNumber = Int32.Parse(MatchPrefix(stdout[k++], "Line Number:")); 160 | sym.Symbol = MatchPrefix(stdout[k++], "Symbol:"); 161 | 162 | // Try to discard function signature data. 163 | int firstParenPos = sym.Symbol.IndexOf('('); 164 | if (-1 != firstParenPos) 165 | { 166 | sym.Symbol = sym.Symbol.Substring(0, firstParenPos); 167 | } 168 | 169 | result[addr + elfBase] = sym; 170 | } 171 | 172 | listener.UpdateProgress("Saving..", 1.0); 173 | listener.UpdateMessage("Writing resolved symbols back to trace file"); 174 | 175 | replay.UpdateResolvedSymbols(result); 176 | 177 | listener.UpdateProgress("Done", 1.0); 178 | listener.UpdateMessage("Finished!"); 179 | 180 | } 181 | 182 | private string MatchPrefix(string line, string prefix) 183 | { 184 | if (!line.StartsWith(prefix)) 185 | throw new ApplicationException("Expected '" + line + "' to start with " + prefix); 186 | var data = line.Substring(prefix.Length); 187 | return data.Trim(); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /runtime/MemTraceSys.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Insomniac Games All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #pragma once 27 | 28 | //----------------------------------------------------------------------------- 29 | // Try to auto-configure platform stuff as much as possible to reduce build 30 | // system complexity for this public release. 31 | 32 | #if defined(__APPLE__) 33 | #define MEMTRACE_UNIX 1 34 | #define MEMTRACE_MAC 1 35 | #endif 36 | 37 | #if defined(__FreeBSD__) 38 | #define MEMTRACE_UNIX 1 39 | #define MEMTRACE_FREEBSD 1 40 | #endif 41 | 42 | #if defined(linux) 43 | #define MEMTRACE_UNIX 1 44 | #define MEMTRACE_LINUX 1 45 | #endif 46 | 47 | #if defined(_WIN32) || defined(_MSC_VER) 48 | #define MEMTRACE_WINDOWS 1 49 | #ifndef WIN32_LEAN_AND_MEAN 50 | #define WIN32_LEAN_AND_MEAN 1 51 | #endif 52 | #ifndef _CRT_SECURE_NO_WARNINGS 53 | #define _CRT_SECURE_NO_WARNINGS 1 54 | #endif 55 | #endif 56 | 57 | //----------------------------------------------------------------------------- 58 | // Common includes 59 | 60 | #include 61 | #include 62 | #include 63 | 64 | //----------------------------------------------------------------------------- 65 | // MemTraceSys.h 66 | // 67 | // Wrappers, helpers etc that support MemTrace. These are a "just what's 68 | // needed" version of some of Insomniac's Foundation libraries. 69 | 70 | 71 | //----------------------------------------------------------------------------- 72 | // Macros for thread local storage, asserts and other misc stuff 73 | 74 | #if defined(MEMTRACE_UNIX) 75 | #define THREAD_LOCAL_STORAGE __thread 76 | #define ALIGN_TO(n) __attribute__((aligned(n))) 77 | #define ASSERT_FATAL(expr, msg, ...) assert(expr && msg) 78 | #endif 79 | 80 | #if defined(MEMTRACE_WINDOWS) 81 | #define THREAD_LOCAL_STORAGE __declspec(thread) 82 | #define ALIGN_TO(n) __declspec((align(n))) 83 | #define ASSERT_FATAL(expr, msg, ...) assert(expr && msg) 84 | #endif 85 | 86 | #define ARRAY_SIZE(expr) ((sizeof(expr))/sizeof(expr[0])) 87 | 88 | //----------------------------------------------------------------------------- 89 | // System includes needed for wrappers in this file. 90 | 91 | #if defined(MEMTRACE_WINDOWS) 92 | #include 93 | #endif 94 | 95 | #if defined(MEMTRACE_UNIX) 96 | #include 97 | #endif 98 | 99 | namespace MemTrace 100 | { 101 | extern const char kPlatformName[]; 102 | 103 | int64_t TimerGetSystemCounter(); 104 | int64_t TimerGetSystemFrequencyInt(); 105 | 106 | inline double TimerGetSystemDeltaInSeconds(int64_t t0) 107 | { 108 | int64_t t1 = TimerGetSystemCounter(); 109 | int64_t diff = t1 - t0; 110 | return diff / double(TimerGetSystemFrequencyInt()); 111 | } 112 | 113 | void Strcpy(char* dest, size_t dest_size, const char* src); 114 | 115 | // Critical section wrapper 116 | #if defined(MEMTRACE_UNIX) 117 | class CriticalSection 118 | { 119 | pthread_mutex_t m_Mutex; 120 | 121 | public: 122 | void Init() 123 | { 124 | pthread_mutex_init(&m_Mutex, nullptr); 125 | } 126 | 127 | void Destroy() 128 | { 129 | pthread_mutex_destroy(&m_Mutex); 130 | } 131 | 132 | void Enter() 133 | { 134 | pthread_mutex_lock(&m_Mutex); 135 | } 136 | 137 | void Leave() 138 | { 139 | pthread_mutex_unlock(&m_Mutex); 140 | } 141 | }; 142 | #elif defined(MEMTRACE_WINDOWS) 143 | class CriticalSection 144 | { 145 | CRITICAL_SECTION m_Mutex; 146 | 147 | public: 148 | void Init() 149 | { 150 | InitializeCriticalSection(&m_Mutex); 151 | } 152 | 153 | void Destroy() 154 | { 155 | DeleteCriticalSection(&m_Mutex); 156 | } 157 | 158 | void Enter() 159 | { 160 | EnterCriticalSection(&m_Mutex); 161 | } 162 | 163 | void Leave() 164 | { 165 | LeaveCriticalSection(&m_Mutex); 166 | } 167 | }; 168 | 169 | #endif 170 | 171 | class CSAutoLock 172 | { 173 | CriticalSection& m_CS; 174 | 175 | public: 176 | explicit CSAutoLock(CriticalSection& cs) : m_CS(cs) 177 | { 178 | cs.Enter(); 179 | } 180 | 181 | ~CSAutoLock() 182 | { 183 | m_CS.Leave(); 184 | } 185 | 186 | private: 187 | CSAutoLock(const CSAutoLock&); 188 | CSAutoLock& operator=(const CSAutoLock&); 189 | }; 190 | 191 | 192 | #if defined(MEMTRACE_UNIX) 193 | typedef int SOCKET; 194 | typedef int FileHandle; 195 | 196 | static const FileHandle kInvalidFileHandle = -1; 197 | static const SOCKET INVALID_SOCKET = -1; 198 | 199 | // For API compatibility with WinSock 200 | void closesocket(SOCKET s); 201 | 202 | // For API compatibility 203 | void OutputDebugStringA(const char* str); 204 | #endif 205 | 206 | #if defined(MEMTRACE_WINDOWS) 207 | // Use WinSock's idea of SOCKET and INVALID_SOCKET 208 | typedef HANDLE FileHandle; 209 | static const FileHandle kInvalidFileHandle = INVALID_HANDLE_VALUE; 210 | #endif 211 | 212 | //----------------------------------------------------------------------------- 213 | // File handling. Note that these HAVE to be implemented in terms of OS 214 | // primitives that don't allocate any user memory, or MemTrace will end up in 215 | // endless recursion. 216 | 217 | FileHandle FileOpenForReadWrite(const char* fn); 218 | 219 | void FileSeekTo(FileHandle fh, int64_t pos); 220 | 221 | int64_t FileSize(FileHandle fh); 222 | 223 | void FileRead(FileHandle fh, void* buffer, size_t size); 224 | 225 | void FileWrite(FileHandle fh, const void* data, size_t size); 226 | 227 | void FileClose(FileHandle fh); 228 | 229 | //----------------------------------------------------------------------------- 230 | // String formatting with sane return value. 231 | int Vsnprintf(char* buffer, size_t buffer_size, const char* fmt, va_list args); 232 | } 233 | -------------------------------------------------------------------------------- /tool/MemTraceTool/DeltaWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTraceTool 2 | { 3 | partial class DeltaWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeltaWindow)); 32 | this.m_StartTimeControl = new MemTrace.Widgets.TimeControl(); 33 | this.m_EndTimeControl = new MemTrace.Widgets.TimeControl(); 34 | this.m_HeapTree = new MemTrace.Widgets.HeapTreeList(); 35 | this.m_RefreshButton = new System.Windows.Forms.Button(); 36 | this.m_Perspective = new System.Windows.Forms.ComboBox(); 37 | this.m_StatusStrip = new System.Windows.Forms.StatusStrip(); 38 | this.m_StripStatus = new System.Windows.Forms.ToolStripStatusLabel(); 39 | this.m_ReplayProgress = new System.Windows.Forms.ToolStripProgressBar(); 40 | this.m_StatusStrip.SuspendLayout(); 41 | this.SuspendLayout(); 42 | // 43 | // m_StartTimeControl 44 | // 45 | this.m_StartTimeControl.Location = new System.Drawing.Point(12, 9); 46 | this.m_StartTimeControl.MaxTime = 0D; 47 | this.m_StartTimeControl.MinTime = 0D; 48 | this.m_StartTimeControl.Name = "m_StartTimeControl"; 49 | this.m_StartTimeControl.Size = new System.Drawing.Size(327, 32); 50 | this.m_StartTimeControl.TabIndex = 0; 51 | this.m_StartTimeControl.TimeLabel = "Start"; 52 | // 53 | // m_EndTimeControl 54 | // 55 | this.m_EndTimeControl.Location = new System.Drawing.Point(415, 9); 56 | this.m_EndTimeControl.MaxTime = 0D; 57 | this.m_EndTimeControl.MinTime = 0D; 58 | this.m_EndTimeControl.Name = "m_EndTimeControl"; 59 | this.m_EndTimeControl.Size = new System.Drawing.Size(327, 32); 60 | this.m_EndTimeControl.TabIndex = 1; 61 | this.m_EndTimeControl.TimeLabel = "End"; 62 | // 63 | // m_HeapTree 64 | // 65 | this.m_HeapTree.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 66 | | System.Windows.Forms.AnchorStyles.Left) 67 | | System.Windows.Forms.AnchorStyles.Right))); 68 | this.m_HeapTree.Location = new System.Drawing.Point(2, 51); 69 | this.m_HeapTree.Name = "m_HeapTree"; 70 | this.m_HeapTree.Size = new System.Drawing.Size(1117, 694); 71 | this.m_HeapTree.TabIndex = 2; 72 | // 73 | // m_RefreshButton 74 | // 75 | this.m_RefreshButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 76 | this.m_RefreshButton.Location = new System.Drawing.Point(1033, 12); 77 | this.m_RefreshButton.Name = "m_RefreshButton"; 78 | this.m_RefreshButton.Size = new System.Drawing.Size(75, 23); 79 | this.m_RefreshButton.TabIndex = 3; 80 | this.m_RefreshButton.Text = "Refresh"; 81 | this.m_RefreshButton.UseVisualStyleBackColor = true; 82 | this.m_RefreshButton.Click += new System.EventHandler(this.OnRefreshButtonClick); 83 | // 84 | // m_Perspective 85 | // 86 | this.m_Perspective.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 87 | this.m_Perspective.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 88 | this.m_Perspective.FormattingEnabled = true; 89 | this.m_Perspective.Location = new System.Drawing.Point(822, 14); 90 | this.m_Perspective.Name = "m_Perspective"; 91 | this.m_Perspective.Size = new System.Drawing.Size(180, 21); 92 | this.m_Perspective.TabIndex = 8; 93 | // 94 | // m_StatusStrip 95 | // 96 | this.m_StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 97 | this.m_StripStatus, 98 | this.m_ReplayProgress}); 99 | this.m_StatusStrip.Location = new System.Drawing.Point(0, 724); 100 | this.m_StatusStrip.Name = "m_StatusStrip"; 101 | this.m_StatusStrip.Size = new System.Drawing.Size(1120, 22); 102 | this.m_StatusStrip.TabIndex = 10; 103 | // 104 | // m_StripStatus 105 | // 106 | this.m_StripStatus.Name = "m_StripStatus"; 107 | this.m_StripStatus.Size = new System.Drawing.Size(703, 17); 108 | this.m_StripStatus.Spring = true; 109 | this.m_StripStatus.Text = "OK"; 110 | this.m_StripStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 111 | // 112 | // m_ReplayProgress 113 | // 114 | this.m_ReplayProgress.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; 115 | this.m_ReplayProgress.Maximum = 1000; 116 | this.m_ReplayProgress.Name = "m_ReplayProgress"; 117 | this.m_ReplayProgress.Size = new System.Drawing.Size(400, 16); 118 | // 119 | // DeltaWindow 120 | // 121 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 122 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 123 | this.ClientSize = new System.Drawing.Size(1120, 746); 124 | this.Controls.Add(this.m_StatusStrip); 125 | this.Controls.Add(this.m_Perspective); 126 | this.Controls.Add(this.m_RefreshButton); 127 | this.Controls.Add(this.m_HeapTree); 128 | this.Controls.Add(this.m_EndTimeControl); 129 | this.Controls.Add(this.m_StartTimeControl); 130 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 131 | this.Name = "DeltaWindow"; 132 | this.Text = "Memory Delta View"; 133 | this.m_StatusStrip.ResumeLayout(false); 134 | this.m_StatusStrip.PerformLayout(); 135 | this.ResumeLayout(false); 136 | this.PerformLayout(); 137 | 138 | } 139 | 140 | #endregion 141 | 142 | private MemTrace.Widgets.TimeControl m_StartTimeControl; 143 | private MemTrace.Widgets.TimeControl m_EndTimeControl; 144 | private MemTrace.Widgets.HeapTreeList m_HeapTree; 145 | private System.Windows.Forms.Button m_RefreshButton; 146 | private System.Windows.Forms.ComboBox m_Perspective; 147 | private System.Windows.Forms.StatusStrip m_StatusStrip; 148 | private System.Windows.Forms.ToolStripStatusLabel m_StripStatus; 149 | private System.Windows.Forms.ToolStripProgressBar m_ReplayProgress; 150 | } 151 | } -------------------------------------------------------------------------------- /tool/MemTraceTool/OptionsDialog.cs: -------------------------------------------------------------------------------- 1 | using BrightIdeasSoftware; 2 | using MemTrace; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Drawing; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Net; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Windows.Forms; 13 | 14 | namespace MemTraceTool 15 | { 16 | public partial class OptionsDialog : Form 17 | { 18 | internal Options Options { get; private set; } 19 | 20 | private void StringListPutHelper(ObjectListView list_view, List l, object row_object, object value) 21 | { 22 | for (int i = 0, count = l.Count; i < count; ++i) 23 | { 24 | if (Object.ReferenceEquals(row_object, l[i])) 25 | { 26 | l[i] = (string)value; 27 | break; 28 | } 29 | } 30 | list_view.SetObjects(l, true); 31 | } 32 | 33 | internal OptionsDialog(Options options) 34 | { 35 | Options = options.Clone(); 36 | 37 | InitializeComponent(); 38 | 39 | m_EnableSuppression.Checked = Options.EnableSuppression; 40 | m_BindAddress.Text = Options.BindAddress.ToString(); 41 | m_BindPort.Text = Options.BindPort.ToString(); 42 | 43 | if (null != Options.TraceDirectory) 44 | { 45 | m_TraceDirectory.Text = Options.TraceDirectory; 46 | } 47 | else 48 | { 49 | // Move to trace directory tab. 50 | m_Tabs.SelectTab(2); 51 | } 52 | 53 | m_SymbolColumn.AspectGetter = (object o) => { return o; }; 54 | m_SymbolColumn.AspectPutter = (object row_object, object value) => { StringListPutHelper(m_SuppressedSymbolList, Options.SuppressedSymbols, row_object, value); }; 55 | 56 | m_SymPathColumn.AspectGetter = (object o) => { return o; }; 57 | m_SymPathColumn.AspectPutter = (object row_object, object value) => { StringListPutHelper(m_SymbolPathsList, Options.SymbolPaths, row_object, value); }; 58 | 59 | m_SuppressedSymbolList.SetObjects(Options.SuppressedSymbols); 60 | m_SymbolMappingList.SetObjects(Options.ModulePathRemappings); 61 | m_SymbolPathsList.SetObjects(Options.SymbolPaths); 62 | } 63 | 64 | private void AddSymbolButton_Click(object sender, EventArgs e) 65 | { 66 | Options.SuppressedSymbols.Add("(new symbol)"); 67 | m_SuppressedSymbolList.SetObjects(Options.SuppressedSymbols); 68 | } 69 | 70 | private void SuppressedSymbolList_SelectedIndexChanged(object sender, EventArgs e) 71 | { 72 | m_RemoveSymbolButton.Enabled = m_SuppressedSymbolList.SelectedIndex != -1; 73 | } 74 | 75 | private void RemoveSymbolButton_Click(object sender, EventArgs e) 76 | { 77 | Options.SuppressedSymbols.RemoveAt(m_SuppressedSymbolList.SelectedIndex); 78 | m_SuppressedSymbolList.SetObjects(Options.SuppressedSymbols); 79 | } 80 | 81 | private void EnableSuppression_CheckedChanged(object sender, EventArgs e) 82 | { 83 | Options.EnableSuppression = m_EnableSuppression.Checked; 84 | } 85 | 86 | private void OnBindAddressValidating(object sender, CancelEventArgs e) 87 | { 88 | try 89 | { 90 | IPAddress.Parse(m_BindAddress.Text); 91 | } 92 | catch (Exception) 93 | { 94 | e.Cancel = true; 95 | } 96 | HighlightValidation(!e.Cancel, m_BindAddress); 97 | } 98 | 99 | private void OnBindPortValidating(object sender, CancelEventArgs e) 100 | { 101 | try 102 | { 103 | int val = Int32.Parse(m_BindPort.Text); 104 | 105 | if (val < 1 || val > 65535) 106 | e.Cancel = true; 107 | } 108 | catch (Exception) 109 | { 110 | e.Cancel = true; 111 | } 112 | HighlightValidation(!e.Cancel, m_BindPort); 113 | } 114 | 115 | private void OnFormClosing(object sender, FormClosingEventArgs e) 116 | { 117 | try 118 | { 119 | IPAddress.Parse(m_BindAddress.Text); 120 | Options.BindAddress = m_BindAddress.Text; 121 | } 122 | catch (Exception) 123 | { 124 | MessageBox.Show("Bind address is not valid."); 125 | e.Cancel = true; 126 | return; 127 | } 128 | 129 | try 130 | { 131 | Options.BindPort = Int32.Parse(m_BindPort.Text); 132 | } 133 | catch (Exception) 134 | { 135 | MessageBox.Show("Bind port is not valid."); 136 | e.Cancel = true; 137 | return; 138 | } 139 | 140 | try 141 | { 142 | Options.TraceDirectory = m_TraceDirectory.Text; 143 | if (Options.TraceDirectory == null || !Directory.Exists(Options.TraceDirectory)) 144 | throw new ApplicationException("blah"); 145 | } 146 | catch (Exception) 147 | { 148 | MessageBox.Show("Trace directory is not valid"); 149 | e.Cancel = true; 150 | return; 151 | } 152 | } 153 | 154 | private void BrowseButton_Click(object sender, EventArgs e) 155 | { 156 | using (var dlg = new FolderBrowserDialog()) 157 | { 158 | dlg.Description = "Select Trace File Directory"; 159 | if (DialogResult.OK == dlg.ShowDialog(this)) 160 | { 161 | m_TraceDirectory.Text = dlg.SelectedPath; 162 | } 163 | } 164 | } 165 | 166 | private void HighlightValidation(bool valid, Control control) 167 | { 168 | if (!valid) 169 | { 170 | control.BackColor = Color.LightPink; 171 | } 172 | else 173 | { 174 | control.BackColor = Color.White; 175 | } 176 | } 177 | 178 | private void OnTraceDirectoryValidating(object sender, CancelEventArgs e) 179 | { 180 | e.Cancel = !Directory.Exists(m_TraceDirectory.Text); 181 | HighlightValidation(!e.Cancel, m_TraceDirectory); 182 | } 183 | 184 | private void OnAddSymbolMapping(object sender, EventArgs e) 185 | { 186 | Options.ModulePathRemappings.Add(new ModulePathRemapping 187 | { 188 | Platform = "(edit me)", 189 | Path = "(edit me)", 190 | ReplacementPath = "(edit me)", 191 | }); 192 | m_SymbolMappingList.SetObjects(Options.ModulePathRemappings); 193 | } 194 | 195 | private void OnRemoveMapping(object sender, EventArgs e) 196 | { 197 | Options.ModulePathRemappings.RemoveAt(m_SymbolMappingList.SelectedIndex); 198 | m_SymbolMappingList.SetObjects(Options.ModulePathRemappings); 199 | } 200 | 201 | private void OnRemapSelectionChanged(object sender, EventArgs e) 202 | { 203 | m_RemoveMappingButton.Enabled = m_SymbolMappingList.SelectedIndex != -1; 204 | } 205 | 206 | private void OnAddSymbolPath(object sender, EventArgs e) 207 | { 208 | Options.SymbolPaths.Add("(edit me)"); 209 | m_SymbolPathsList.SetObjects(Options.SymbolPaths); 210 | } 211 | 212 | private void OnSymbolPathSelectionChanged(object sender, EventArgs e) 213 | { 214 | m_RemovePathButton.Enabled = m_SymbolPathsList.SelectedIndex != -1; 215 | } 216 | 217 | private void OnRemoveSymbolPath(object sender, EventArgs e) 218 | { 219 | Options.SymbolPaths.RemoveAt(m_SymbolPathsList.SelectedIndex); 220 | m_SymbolPathsList.SetObjects(Options.SymbolPaths); 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /tool/MemTraceTool/TreeBuilder.cs: -------------------------------------------------------------------------------- 1 | using MemTrace; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace MemTraceTool 11 | { 12 | public enum EventScope : byte 13 | { 14 | None, 15 | Asset, 16 | Component, 17 | } 18 | 19 | 20 | abstract class TreeBuilderBase 21 | { 22 | protected TraceReplayStateful Replay { get; private set; } 23 | protected TraceReplayStateful.StatusDelegate StatusCallback { get; private set; } 24 | protected MemTreeNode Root { get; private set; } 25 | protected TreePerspective Perspective { get; private set; } 26 | protected HashSet SuppressedSymbols { get; private set; } 27 | 28 | protected TreeBuilderBase(TraceReplayStateful replay, TraceReplayStateful.StatusDelegate status_delegate, TreePerspective perspective, Options options) 29 | { 30 | Replay = replay; 31 | StatusCallback = status_delegate; 32 | Perspective = perspective; 33 | Root = new MemTreeNode(null, "Everything"); 34 | SuppressedSymbols = new HashSet(); 35 | if (options.EnableSuppression) 36 | { 37 | foreach (var sym in options.SuppressedSymbols) 38 | { 39 | SuppressedSymbols.Add(sym); 40 | } 41 | } 42 | } 43 | 44 | protected void BuildBackTraceNodes(StackBackTrace backtrace, ref MemTreeNode leaf, bool reverse) 45 | { 46 | var frames = backtrace.Frames; 47 | int start, end, dir; 48 | 49 | if (reverse) 50 | { 51 | start = 0; 52 | end = frames.Count - 1; 53 | dir = 1; 54 | } 55 | else 56 | { 57 | start = frames.Count - 1; 58 | end = 0; 59 | dir = -1; 60 | } 61 | 62 | for (int i = start; i != end; i += dir) 63 | { 64 | var frame = frames[i]; 65 | var name = frame.Symbol; 66 | var filename = frame.FileName; 67 | var lineno = frame.LineNumber; 68 | 69 | if (SuppressedSymbols.Contains(name)) 70 | continue; 71 | 72 | leaf = leaf.GetChild(name); 73 | leaf.Icon = "symbol"; 74 | leaf.FileName = filename; 75 | leaf.LineNumber = lineno; 76 | } 77 | } 78 | 79 | protected void UpdateReplayStatus() 80 | { 81 | //++m_EventStatusCount; 82 | //if (m_EventStatusCount % 10000 == 1 && EndTimeStamp != 0) 83 | //{ 84 | //StatusCallback((double)Replay.CurrentTimeStamp / (double)EndTimeStamp); 85 | //} 86 | } 87 | 88 | protected void UpdateTree(HeapAllocationInfo info) 89 | { 90 | MemTreeNode leaf = Root; 91 | var heap = info.Heap; 92 | var stack = info.BackTrace; 93 | var scope = (EventScope) info.ScopeType; 94 | var scope_data = info.ScopeData; 95 | 96 | foreach (var axis in Perspective.Axes) 97 | { 98 | switch (axis) 99 | { 100 | case TreeAxis.Heap: 101 | leaf = leaf.GetChild(heap != null ? heap.Name : "(unknown heap)"); 102 | leaf.Icon = "heap"; 103 | break; 104 | 105 | case TreeAxis.CallStackReverse: 106 | BuildBackTraceNodes(stack, ref leaf, true); 107 | break; 108 | 109 | case TreeAxis.CallStack: 110 | BuildBackTraceNodes(stack, ref leaf, false); 111 | break; 112 | 113 | case TreeAxis.FileName: 114 | for (int i = stack.Frames.Count - 1; i >= 0; --i) 115 | { 116 | var frame = stack.Frames[i]; 117 | 118 | if (SuppressedSymbols.Contains(frame.Symbol)) 119 | continue; 120 | 121 | leaf = leaf.GetChild(Path.GetFileName(frame.FileName)); 122 | leaf.Icon = "file"; 123 | leaf.FileName = frame.FileName; 124 | leaf.LineNumber = frame.LineNumber; 125 | } 126 | break; 127 | 128 | case TreeAxis.AssetPath: 129 | if (scope == EventScope.Asset) 130 | { 131 | string[] elems = scope_data.Split('\\', '/'); 132 | for (int i = 0; i < elems.Length - 1; ++i) 133 | { 134 | leaf = leaf.GetChild(elems[i]); 135 | leaf.Icon = "folder"; 136 | } 137 | leaf = leaf.GetChild(elems[elems.Length - 1]); 138 | leaf.Icon = "asset"; 139 | } 140 | else 141 | { 142 | leaf = leaf.GetChild("(no asset)"); 143 | } 144 | break; 145 | 146 | case TreeAxis.AssetType: 147 | if (scope == EventScope.Asset) 148 | { 149 | leaf = leaf.GetChild(Path.GetExtension(scope_data)); 150 | leaf.Icon = "asset"; 151 | } 152 | else 153 | { 154 | leaf = leaf.GetChild("(no asset)"); 155 | } 156 | break; 157 | 158 | case TreeAxis.ComponentType: 159 | if (scope == EventScope.Component) 160 | { 161 | leaf = leaf.GetChild(scope_data); 162 | leaf.Icon = "component"; 163 | } 164 | else 165 | { 166 | leaf = leaf.GetChild("(no component)"); 167 | } 168 | break; 169 | } 170 | } 171 | 172 | do 173 | { 174 | leaf.SizeBytes += (long) info.SizeBytes; 175 | leaf.Count += 1; 176 | leaf = leaf.Parent; 177 | } while (leaf != null); 178 | } 179 | 180 | public abstract MemTreeNode BuildReportTree(); 181 | } 182 | 183 | sealed class SnapshotTreeBuilder : TreeBuilderBase 184 | { 185 | public SnapshotTreeBuilder(TraceReplayStateful t, double time, TraceReplayStateful.StatusDelegate status_delegate, TreePerspective perspective, Options options) 186 | : base(t, status_delegate, perspective, options) 187 | { 188 | Replay.SeekTo(time, StatusCallback); 189 | } 190 | 191 | // Return the tree nodes from a tree built from this snapshot. 192 | public override MemTreeNode BuildReportTree() 193 | { 194 | foreach (var alloc in Replay.HeapAllocations.Values) 195 | { 196 | UpdateTree(alloc); 197 | } 198 | 199 | Root.Freeze(); 200 | 201 | return Root; 202 | } 203 | } 204 | 205 | sealed class DeltaTreeBuilder : TreeBuilderBase 206 | { 207 | private double m_StartTime; 208 | 209 | public DeltaTreeBuilder(TraceReplayStateful t, double startTime, double endTime, TraceReplayStateful.StatusDelegate status_delegate, TreePerspective perspective, Options options) 210 | : base(t, status_delegate, perspective, options) 211 | { 212 | m_StartTime = startTime; 213 | 214 | Replay.SeekTo(endTime, StatusCallback); 215 | } 216 | 217 | // Return the tree nodes from a tree built from this snapshot. 218 | public override MemTreeNode BuildReportTree() 219 | { 220 | foreach (var alloc in Replay.HeapAllocations.Values) 221 | { 222 | if (alloc.TimeCreated >= m_StartTime) 223 | { 224 | UpdateTree(alloc); 225 | } 226 | } 227 | 228 | Root.Freeze(); 229 | 230 | return Root; 231 | } 232 | } 233 | 234 | } 235 | -------------------------------------------------------------------------------- /tool/MemTraceWidgets/HeapTreeList.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MemTrace.Widgets 2 | { 3 | partial class HeapTreeList 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HeapTreeList)); 33 | this.m_TreeList = new BrightIdeasSoftware.TreeListView(); 34 | this.m_KeyColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); 35 | this.m_FileNameColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); 36 | this.m_LineNumberColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); 37 | this.m_SizeColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); 38 | this.m_CountColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn())); 39 | this.m_ImageList = new System.Windows.Forms.ImageList(this.components); 40 | ((System.ComponentModel.ISupportInitialize)(this.m_TreeList)).BeginInit(); 41 | this.SuspendLayout(); 42 | // 43 | // m_TreeList 44 | // 45 | this.m_TreeList.AllColumns.Add(this.m_KeyColumn); 46 | this.m_TreeList.AllColumns.Add(this.m_FileNameColumn); 47 | this.m_TreeList.AllColumns.Add(this.m_LineNumberColumn); 48 | this.m_TreeList.AllColumns.Add(this.m_SizeColumn); 49 | this.m_TreeList.AllColumns.Add(this.m_CountColumn); 50 | this.m_TreeList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 51 | | System.Windows.Forms.AnchorStyles.Left) 52 | | System.Windows.Forms.AnchorStyles.Right))); 53 | this.m_TreeList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { 54 | this.m_KeyColumn, 55 | this.m_FileNameColumn, 56 | this.m_LineNumberColumn, 57 | this.m_SizeColumn, 58 | this.m_CountColumn}); 59 | this.m_TreeList.FullRowSelect = true; 60 | this.m_TreeList.GridLines = true; 61 | this.m_TreeList.Location = new System.Drawing.Point(0, 0); 62 | this.m_TreeList.Name = "m_TreeList"; 63 | this.m_TreeList.OwnerDraw = true; 64 | this.m_TreeList.ShowGroups = false; 65 | this.m_TreeList.Size = new System.Drawing.Size(1000, 500); 66 | this.m_TreeList.SmallImageList = this.m_ImageList; 67 | this.m_TreeList.TabIndex = 2; 68 | this.m_TreeList.UseCompatibleStateImageBehavior = false; 69 | this.m_TreeList.View = System.Windows.Forms.View.Details; 70 | this.m_TreeList.VirtualMode = true; 71 | // 72 | // m_KeyColumn 73 | // 74 | this.m_KeyColumn.AspectName = "Key"; 75 | this.m_KeyColumn.CellPadding = null; 76 | this.m_KeyColumn.IsEditable = false; 77 | this.m_KeyColumn.MinimumWidth = 200; 78 | this.m_KeyColumn.Text = "Item"; 79 | this.m_KeyColumn.Width = 253; 80 | // 81 | // m_FileNameColumn 82 | // 83 | this.m_FileNameColumn.AspectName = "FileName"; 84 | this.m_FileNameColumn.CellPadding = null; 85 | this.m_FileNameColumn.IsEditable = false; 86 | this.m_FileNameColumn.Text = "File Name"; 87 | this.m_FileNameColumn.Width = 177; 88 | // 89 | // m_LineNumberColumn 90 | // 91 | this.m_LineNumberColumn.AspectName = "LineNumber"; 92 | this.m_LineNumberColumn.AspectToStringFormat = "{0:n0}"; 93 | this.m_LineNumberColumn.CellPadding = null; 94 | this.m_LineNumberColumn.IsEditable = false; 95 | this.m_LineNumberColumn.Text = "Line Number"; 96 | // 97 | // m_SizeColumn 98 | // 99 | this.m_SizeColumn.AspectName = "SizeBytes"; 100 | this.m_SizeColumn.AspectToStringFormat = "{0:n0}"; 101 | this.m_SizeColumn.CellPadding = null; 102 | this.m_SizeColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right; 103 | this.m_SizeColumn.IsEditable = false; 104 | this.m_SizeColumn.MinimumWidth = 80; 105 | this.m_SizeColumn.Text = "Size"; 106 | this.m_SizeColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; 107 | this.m_SizeColumn.Width = 112; 108 | // 109 | // m_CountColumn 110 | // 111 | this.m_CountColumn.AspectName = "Count"; 112 | this.m_CountColumn.AspectToStringFormat = "{0:n0}"; 113 | this.m_CountColumn.CellPadding = null; 114 | this.m_CountColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right; 115 | this.m_CountColumn.IsEditable = false; 116 | this.m_CountColumn.MinimumWidth = 80; 117 | this.m_CountColumn.Text = "Count"; 118 | this.m_CountColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; 119 | this.m_CountColumn.Width = 105; 120 | // 121 | // m_ImageList 122 | // 123 | this.m_ImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("m_ImageList.ImageStream"))); 124 | this.m_ImageList.TransparentColor = System.Drawing.Color.Transparent; 125 | this.m_ImageList.Images.SetKeyName(0, "folder"); 126 | this.m_ImageList.Images.SetKeyName(1, "sourcefile"); 127 | this.m_ImageList.Images.SetKeyName(2, "heap"); 128 | this.m_ImageList.Images.SetKeyName(3, "asset"); 129 | this.m_ImageList.Images.SetKeyName(4, "namespace"); 130 | this.m_ImageList.Images.SetKeyName(5, "component"); 131 | this.m_ImageList.Images.SetKeyName(6, "arrow"); 132 | this.m_ImageList.Images.SetKeyName(7, "symbol"); 133 | // 134 | // HeapTreeList 135 | // 136 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 137 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 138 | this.Controls.Add(this.m_TreeList); 139 | this.Name = "HeapTreeList"; 140 | this.Size = new System.Drawing.Size(1000, 500); 141 | ((System.ComponentModel.ISupportInitialize)(this.m_TreeList)).EndInit(); 142 | this.ResumeLayout(false); 143 | 144 | } 145 | 146 | #endregion 147 | 148 | private BrightIdeasSoftware.TreeListView m_TreeList; 149 | private BrightIdeasSoftware.OLVColumn m_KeyColumn; 150 | private BrightIdeasSoftware.OLVColumn m_FileNameColumn; 151 | private BrightIdeasSoftware.OLVColumn m_LineNumberColumn; 152 | private BrightIdeasSoftware.OLVColumn m_SizeColumn; 153 | private BrightIdeasSoftware.OLVColumn m_CountColumn; 154 | private System.Windows.Forms.ImageList m_ImageList; 155 | 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /runtime/vs2012/MemTraceDemo.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {635A9485-BB33-4886-BE78-797A2693B987} 23 | Win32Proj 24 | 25 | 26 | 27 | Application 28 | true 29 | v110 30 | 31 | 32 | Application 33 | true 34 | v110 35 | 36 | 37 | Application 38 | false 39 | v110 40 | 41 | 42 | Application 43 | false 44 | v110 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | true 64 | 65 | 66 | true 67 | 68 | 69 | true 70 | 71 | 72 | true 73 | 74 | 75 | 76 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 77 | MultiThreadedDebugDLL 78 | Level3 79 | ProgramDatabase 80 | Disabled 81 | 82 | 83 | MachineX86 84 | true 85 | Console 86 | 87 | 88 | 89 | 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | MultiThreadedDebugDLL 92 | Level3 93 | ProgramDatabase 94 | Disabled 95 | 96 | 97 | true 98 | Console 99 | 100 | 101 | 102 | 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | MultiThreadedDLL 105 | Level3 106 | ProgramDatabase 107 | 108 | 109 | MachineX86 110 | true 111 | Console 112 | true 113 | true 114 | 115 | 116 | 117 | 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | MultiThreadedDLL 120 | Level3 121 | ProgramDatabase 122 | 123 | 124 | true 125 | Console 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | {c9f9ca93-3a01-41e8-a601-66c45aa7fea6} 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /runtime/vs2012/MemTrace.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {C9F9CA93-3A01-41E8-A601-66C45AA7FEA6} 23 | Win32Proj 24 | 25 | 26 | 27 | StaticLibrary 28 | true 29 | v110 30 | 31 | 32 | StaticLibrary 33 | true 34 | v110 35 | 36 | 37 | StaticLibrary 38 | false 39 | v110 40 | 41 | 42 | StaticLibrary 43 | false 44 | v110 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | true 64 | 65 | 66 | true 67 | 68 | 69 | true 70 | 71 | 72 | true 73 | 74 | 75 | 76 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 77 | MultiThreadedDebugDLL 78 | Level3 79 | ProgramDatabase 80 | Disabled 81 | 82 | 83 | MachineX86 84 | true 85 | Windows 86 | 87 | 88 | 89 | 90 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 91 | MultiThreadedDebugDLL 92 | Level3 93 | ProgramDatabase 94 | Disabled 95 | $(SolutionDir)..\minhook\include 96 | 97 | 98 | true 99 | Console 100 | 101 | 102 | 103 | 104 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 105 | MultiThreadedDLL 106 | Level3 107 | ProgramDatabase 108 | 109 | 110 | MachineX86 111 | true 112 | Windows 113 | true 114 | true 115 | 116 | 117 | 118 | 119 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 120 | MultiThreadedDLL 121 | Level3 122 | ProgramDatabase 123 | $(SolutionDir)..\minhook\include 124 | 125 | 126 | true 127 | Console 128 | true 129 | true 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | --------------------------------------------------------------------------------