forked from jbevain/PmipMyCallStack
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from Unity-Technologies/line-numbers
Line number and multiple domain support
- Loading branch information
Showing
14 changed files
with
152,871 additions
and
104 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net472</TargetFramework> | ||
|
||
<IsPackable>false</IsPackable> | ||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> | ||
<PlatformTarget>x64</PlatformTarget> | ||
<Platforms>AnyCPU;x64</Platforms> | ||
<VSSdkPath Condition="'$(VisualStudioVersion.Contains(`17`))'">$(ProgramFiles)\Microsoft Visual Studio\2022\Professional\VSSDK\</VSSdkPath> | ||
<VSSdkPath Condition="'$(VisualStudioVersion.Contains(`16`))'">$(MSBuildProgramFiles32)\Microsoft Visual Studio\2019\Professional\VSSDK\</VSSdkPath> | ||
<ConcordSDKDir>$(VSSdkPath)VisualStudioIntegration\</ConcordSDKDir> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<None Remove="pmip_32260_3.txt" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.TestPlatform" Version="17.5.0" /> | ||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" /> | ||
<PackageReference Include="NUnit" Version="3.13.3" /> | ||
<PackageReference Include="NUnit3TestAdapter" Version="4.4.0" /> | ||
</ItemGroup> | ||
|
||
<Import Project="$(ConcordSDKDir)Tools\bin\Microsoft.VSSDK.Debugger.VSDConfigTool.targets" /> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\UnityMixedCallStack.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Update="TestData\line-numbers\pmip_23672_1_0.txt"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Update="TestData\line-numbers\pmip_23672_4_1.txt"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Update="TestData\pmip_31964_3.txt"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Update="TestData\pmip_32260_3.txt"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Update="TestData\pmip_44920_4.txt"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
|
||
</Project> |
208 changes: 208 additions & 0 deletions
208
CallstackTestProj/TestData/line-numbers/pmip_23672_1_0.txt
Large diffs are not rendered by default.
Oops, something went wrong.
95,270 changes: 95,270 additions & 0 deletions
95,270
CallstackTestProj/TestData/line-numbers/pmip_23672_4_1.txt
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
using NUnit.Framework; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.IO; | ||
using UnityMixedCallStack; | ||
|
||
namespace CallstackTestProj | ||
{ | ||
[TestFixture] | ||
public class Tests | ||
{ | ||
private Tuple<string, string>[] m_legacyData = | ||
{ | ||
Tuple.Create("000001C44A1C81D7", "[UnityEditor.CoreModule.dll] (wrapper managed-to-native) UnityEditor.EditorGUIUtility:RenderPlayModeViewCamerasInternal_Injected (UnityEngine.RenderTexture,int,UnityEngine.Vector2&,bool,bool)"), | ||
Tuple.Create("000001C44A1C8083", "[UnityEditor.CoreModule.dll] UnityEditor.EditorGUIUtility:RenderPlayModeViewCamerasInternal (UnityEngine.RenderTexture,int,UnityEngine.Vector2,bool,bool)"), | ||
Tuple.Create("000001C44A1C52EB", "[UnityEditor.CoreModule.dll] UnityEditor.PlayModeView:RenderView (UnityEngine.Vector2,bool)"), | ||
Tuple.Create("000001C449F19A23", "[UnityEditor.CoreModule.dll] UnityEditor.GameView:OnGUI ()"), | ||
Tuple.Create("000001C449F12BF8", "[UnityEditor.CoreModule.dll] UnityEditor.HostView:InvokeOnGUI (UnityEngine.Rect)"), | ||
Tuple.Create("000001C449F12793", "[UnityEditor.CoreModule.dll] UnityEditor.DockArea:DrawView (UnityEngine.Rect)"), | ||
Tuple.Create("000001C449EF1353", "[UnityEditor.CoreModule.dll] UnityEditor.DockArea:OldOnGUI ()"), | ||
Tuple.Create("000001C449EBCCE9", "[UnityEngine.UIElementsModule.dll] UnityEngine.UIElements.IMGUIContainer:DoOnGUI (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,bool,UnityEngine.Rect,System.Action,bool)"), | ||
Tuple.Create("000001C449EBAC13", "[UnityEngine.UIElementsModule.dll] UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,System.Action,bool)") | ||
}; | ||
|
||
[Test] | ||
public void LegacyDataTest() | ||
{ | ||
Assert.IsTrue(PmipReader.ReadPmipFile(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "pmip_32260_3.txt"))); | ||
PmipReader.Sort(); | ||
|
||
foreach (Tuple<string, string> t in m_legacyData) | ||
{ | ||
if (PmipReader.TryGetDescriptionForIp(ulong.Parse(t.Item1, NumberStyles.HexNumber), out string retVal)) | ||
{ | ||
Assert.AreEqual(t.Item2, retVal); | ||
} | ||
else | ||
Assert.Fail(); | ||
} | ||
PmipReader.DisposeStreams(); | ||
} | ||
|
||
private Tuple<string, string>[] m_legacyModeData = | ||
{ | ||
Tuple.Create("000001C4F5DC03FF", "[Assembly-CSharp.dll] SpinMe:FooBar ()"), | ||
Tuple.Create("000001C4F5DC02D3", "[Assembly-CSharp.dll] SpinMe:Foo ()"), | ||
Tuple.Create("000001C4F5DBF6F3", "[Assembly-CSharp.dll] SpinMe:Update ()"), | ||
Tuple.Create("000001C3FF868578", "[mscorlib.dll] (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)") | ||
}; | ||
|
||
[Test] | ||
public void LegacyModeDataTest() | ||
{ | ||
Assert.IsTrue(PmipReader.ReadPmipFile(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "pmip_31964_3.txt"))); | ||
PmipReader.Sort(); | ||
|
||
foreach (Tuple<string, string> t in m_legacyModeData) | ||
{ | ||
if (PmipReader.TryGetDescriptionForIp(ulong.Parse(t.Item1, NumberStyles.HexNumber), out string retVal)) | ||
{ | ||
Assert.AreEqual(t.Item2, retVal); | ||
} | ||
else | ||
Assert.Fail(); | ||
}; | ||
PmipReader.DisposeStreams(); | ||
} | ||
|
||
private Tuple<string, string>[] m_lineNumbersData = | ||
{ | ||
Tuple.Create("00000244C7A990BF", "[Assembly-CSharp.dll] SpinMe:FooBar ()"), | ||
Tuple.Create("00000244C7A98F93", "[Assembly-CSharp.dll] SpinMe:Foo () : 32"), | ||
Tuple.Create("00000244C7A98153", "[Assembly-CSharp.dll] SpinMe:Update () : 26"), | ||
Tuple.Create("00000244EC9DF6B8", "[mscorlib.dll] (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)") | ||
}; | ||
|
||
[Test] | ||
public void LineNumbersDataTest() | ||
{ | ||
Assert.IsTrue(PmipReader.ReadPmipFile(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "line-numbers", "pmip_23672_1_0.txt"))); | ||
Assert.IsTrue(PmipReader.ReadPmipFile(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "line-numbers", "pmip_23672_4_1.txt"))); | ||
PmipReader.Sort(); | ||
|
||
foreach (Tuple<string, string> t in m_lineNumbersData) | ||
{ | ||
if (PmipReader.TryGetDescriptionForIp(ulong.Parse(t.Item1, NumberStyles.HexNumber), out string retVal)) | ||
{ | ||
Assert.AreEqual(t.Item2, retVal); | ||
} | ||
else | ||
Assert.Fail($"Couldn't find address: {t.Item1}"); | ||
}; | ||
|
||
PmipReader.DisposeStreams(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.IO; | ||
using UnityMixedCallstack; | ||
|
||
namespace UnityMixedCallStack | ||
{ | ||
public class PmipReader | ||
{ | ||
private static List<Range> _rangesSortedByIp = new List<Range>(); | ||
private static List<Range> _legacyRanges = new List<Range>(); | ||
private static FuzzyRangeComparer _comparer = new FuzzyRangeComparer(); | ||
|
||
private struct PmipStreams | ||
{ | ||
public FileStream fileStream; | ||
public StreamReader fileStreamReader; | ||
|
||
public void Dispose() | ||
{ | ||
fileStreamReader.Dispose(); | ||
fileStreamReader = null; | ||
fileStream.Dispose(); | ||
fileStream = null; | ||
} | ||
} | ||
|
||
private static Dictionary<string, PmipStreams> _currentFiles = new Dictionary<string, PmipStreams>(); | ||
|
||
public static void Sort() | ||
{ | ||
_legacyRanges.Sort((r1, r2) => r1.Start.CompareTo(r2.Start)); | ||
_rangesSortedByIp.Sort((r1, r2) => r1.Start.CompareTo(r2.Start)); | ||
} | ||
|
||
public static void DisposeStreams() | ||
{ | ||
foreach (PmipStreams streams in _currentFiles.Values) | ||
streams.Dispose(); | ||
_currentFiles.Clear(); | ||
|
||
_rangesSortedByIp.Clear(); | ||
_legacyRanges.Clear(); | ||
} | ||
public static bool ReadPmipFile(string filePath) | ||
{ | ||
var _debugPane = UnityMixedCallstackFilter._debugPane; | ||
#if DEBUG | ||
_debugPane?.OutputString("MIXEDCALLSTACK :: Reading pmip file: " + filePath + "\n"); | ||
#endif | ||
//DisposeStreams(); | ||
|
||
if (!_currentFiles.TryGetValue(filePath, out PmipStreams pmipStreams)) | ||
{ | ||
pmipStreams = new PmipStreams(); | ||
try | ||
{ | ||
pmipStreams.fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); | ||
pmipStreams.fileStreamReader = new StreamReader(pmipStreams.fileStream); | ||
var versionStr = pmipStreams.fileStreamReader.ReadLine(); | ||
const char delimiter = ':'; | ||
var tokens = versionStr.Split(delimiter); | ||
|
||
if (tokens.Length != 2) | ||
throw new Exception("Failed reading input file " + filePath + ": Incorrect format"); | ||
|
||
if (!double.TryParse(tokens[1], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var version)) | ||
throw new Exception("Failed reading input file " + filePath + ": Incorrect version format"); | ||
|
||
if (version > 2.0) | ||
throw new Exception("Failed reading input file " + filePath + ": A newer version of UnityMixedCallstacks plugin is required to read this file"); | ||
} | ||
catch (Exception ex) | ||
{ | ||
_debugPane?.OutputString("MIXEDCALLSTACK :: Unable to read dumped pmip file: " + ex.Message + "\n"); | ||
DisposeStreams(); | ||
return false; | ||
} | ||
_currentFiles.Add(filePath, pmipStreams); | ||
} | ||
|
||
try | ||
{ | ||
string line; | ||
int count = 0; | ||
int legacyCount = 0; | ||
while ((line = pmipStreams.fileStreamReader.ReadLine()) != null) | ||
{ | ||
const char delemiter = ';'; | ||
var tokens = line.Split(delemiter); | ||
|
||
//should never happen, but lets be safe and not get array out of bounds if it does | ||
if (tokens.Length == 3 || tokens.Length == 4) | ||
{ | ||
string startip = tokens[0]; | ||
string endip = tokens[1]; | ||
string description = tokens[2]; | ||
string file = ""; | ||
if (tokens.Length == 4) | ||
file = tokens[3]; | ||
|
||
if (startip.StartsWith("---")) | ||
{ | ||
startip = startip.Remove(0, 3); | ||
} | ||
|
||
var startiplong = ulong.Parse(startip, NumberStyles.HexNumber); | ||
var endipint = ulong.Parse(endip, NumberStyles.HexNumber); | ||
if (tokens[0].StartsWith("---")) | ||
{ | ||
// legacy stored in new pmip file | ||
_legacyRanges.Add(new Range() { Name = description, File = file, Start = startiplong, End = endipint }); | ||
legacyCount++; | ||
} | ||
else | ||
{ | ||
Range range = new Range() { Name = description, File = file, Start = startiplong, End = endipint }; | ||
#if DEBUG | ||
_debugPane?.OutputString($"MIXEDCALLSTACK :: adding range: {range}\n"); | ||
#endif | ||
_rangesSortedByIp.Add(range); | ||
count++; | ||
} | ||
} | ||
} | ||
#if DEBUG | ||
if (count > 0 || legacyCount > 0) | ||
_debugPane?.OutputString($"MIXEDCALLSTACK :: added {count} to map for a total of {_rangesSortedByIp.Count} entries! Added {legacyCount} to legacy map for a total of {_legacyRanges.Count} \n"); | ||
#endif | ||
} | ||
catch (Exception ex) | ||
{ | ||
_debugPane?.OutputString("MIXEDCALLSTACK :: Unable to read dumped pmip file: " + ex.Message + "\n"); | ||
DisposeStreams(); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
public static bool TryGetDescriptionForIp(ulong ip, out string name) | ||
{ | ||
name = string.Empty; | ||
|
||
//_debugPane?.OutputString("MIXEDCALLSTACK :: Looking for ip: " + String.Format("{0:X}", ip) + "\n"); | ||
var rangeToFindIp = new Range() { Start = ip }; | ||
var index = _rangesSortedByIp.BinarySearch(rangeToFindIp, _comparer); | ||
|
||
if (index >= 0) | ||
{ | ||
//_debugPane?.OutputString("MIXEDCALLSTACK :: SUCCESS!!\n"); | ||
name = _rangesSortedByIp[index].Name; | ||
return true; | ||
} | ||
|
||
index = _legacyRanges.BinarySearch(rangeToFindIp, _comparer); | ||
if (index >= 0) | ||
{ | ||
//_debugPane?.OutputString("MIXEDCALLSTACK :: LEGACY SUCCESS!! "+ String.Format("{0:X}", _legacyRanges[index].Start) +" -- "+ String.Format("{0:X}", _legacyRanges[index].End) + "\n"); | ||
name = _legacyRanges[index].Name; | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.