From 20201d3598467b09cd2c1a21d89b5d1ce9dc71cb Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2023 15:15:44 -0700 Subject: [PATCH 1/6] Add GC Info --- ILSpy.ReadyToRun/ReadyToRunDisassembler.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs index 6996f211d..b99a706a8 100644 --- a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs +++ b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs @@ -47,10 +47,19 @@ namespace ICSharpCode.ILSpy.ReadyToRun public void Disassemble(PEFile currentFile, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10) { - // TODO: Decorate the disassembly with GCInfo ReadyToRunMethod readyToRunMethod = runtimeFunction.Method; WriteCommentLine(readyToRunMethod.SignatureString); + if (readyToRunMethod.GcInfo != null) + { + string[] lines = readyToRunMethod.GcInfo.ToString().Split(Environment.NewLine); + WriteCommentLine("GC info:"); + foreach (string line in lines) + { + WriteCommentLine(line); + } + } + Dictionary unwindInfo = null; if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { From 99a1e427ea2227fc5b4be02a083643cabcead64e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2023 16:08:39 -0700 Subject: [PATCH 2/6] Adding GC transitions --- ILSpy.ReadyToRun/ReadyToRunDisassembler.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs index b99a706a8..90e5cda29 100644 --- a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs +++ b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs @@ -129,6 +129,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } } + DecorateGCInfo(instr, baseInstrIP, readyToRunMethod.GcInfo); formatter.Format(instr, tempOutput); output.Write(instr.IP.ToString("X16")); output.Write(" "); @@ -152,6 +153,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine(); } + private void DecorateGCInfo(Instruction instr, ulong baseInstrIP, BaseGcInfo gcInfo) + { + ulong codeOffset = instr.IP - baseInstrIP; + if (gcInfo != null && gcInfo.Transitions != null && gcInfo.Transitions.TryGetValue((int)codeOffset, out List transitionsForOffset)) + { + // this value comes from a manual count of the spaces used for each instruction in Disassemble() + string indent = new string(' ', 36); + foreach (var transition in transitionsForOffset) + { + WriteCommentLine(indent + transition.ToString()); + } + } + } + private void WriteCommentLine(string comment) { output.WriteLine("; " + comment); From 232582b81de6f34e659caca28676da4f2bce94da Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2023 17:07:40 -0700 Subject: [PATCH 3/6] Stop iterating through all of runtimeFunction.DebugInfo.BoundsList for each instruction --- ILSpy.ReadyToRun/ReadyToRunDisassembler.cs | 33 +++++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs index 90e5cda29..cfbf5a07d 100644 --- a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs +++ b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs @@ -105,27 +105,32 @@ namespace ICSharpCode.ILSpy.ReadyToRun formatter.Options.FirstOperandCharIndex = 10; var tempOutput = new StringOutput(); ulong baseInstrIP = instructions[0].IP; + + var boundsMap = new Dictionary(); + foreach (var bound in runtimeFunction.DebugInfo.BoundsList) + { + // ignoring the return value assuming the same key is always mapped to the same value in runtimeFunction.DebugInfo.BoundsList + boundsMap.TryAdd(bound.NativeOffset, bound.ILOffset); + } + foreach (var instr in instructions) { int byteBaseIndex = (int)(instr.IP - address); if (isShowDebugInfo && runtimeFunction.DebugInfo != null) { - foreach (var bound in runtimeFunction.DebugInfo.BoundsList) + if (byteBaseIndex >= 0 && boundsMap.TryGetValue((uint)byteBaseIndex, out uint boundILOffset)) { - if (bound.NativeOffset == byteBaseIndex) + if (boundILOffset == (uint)DebugInfoBoundsType.Prolog) { - if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog) - { - WriteCommentLine("Prolog"); - } - else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog) - { - WriteCommentLine("Epilog"); - } - else - { - WriteCommentLine($"IL_{bound.ILOffset:x4}"); - } + WriteCommentLine("Prolog"); + } + else if (boundILOffset == (uint)DebugInfoBoundsType.Epilog) + { + WriteCommentLine("Epilog"); + } + else + { + WriteCommentLine($"IL_{boundILOffset:x4}"); } } } From c39a1f7fcc1ca3e1e2178d4f5938bf6099188524 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Sep 2023 13:43:01 -0700 Subject: [PATCH 4/6] Add Show GC Info checkbox --- .../Properties/Resources.Designer.cs | 11 +++++++++- ILSpy.ReadyToRun/Properties/Resources.resx | 3 +++ .../Properties/Resources.zh-Hans.resx | 3 +++ ILSpy.ReadyToRun/ReadyToRunDisassembler.cs | 2 +- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 3 +++ ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs | 15 ++++++++++++- ILSpy.ReadyToRun/ReadyToRunOptions.cs | 22 ++++++++++++++++++- 7 files changed, 55 insertions(+), 4 deletions(-) diff --git a/ILSpy.ReadyToRun/Properties/Resources.Designer.cs b/ILSpy.ReadyToRun/Properties/Resources.Designer.cs index f28df710f..5d4bb0f36 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.Designer.cs +++ b/ILSpy.ReadyToRun/Properties/Resources.Designer.cs @@ -95,5 +95,14 @@ namespace ILSpy.ReadyToRun.Properties { return ResourceManager.GetString("ShowUnwindInfo", resourceCulture); } } - } + + /// + /// Looks up a localized string similar to Show GC Info. + /// + public static string ShowGCInfo { + get { + return ResourceManager.GetString("ShowGCInfo", resourceCulture); + } + } + } } diff --git a/ILSpy.ReadyToRun/Properties/Resources.resx b/ILSpy.ReadyToRun/Properties/Resources.resx index 8c6d1ce8c..499c47add 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.resx +++ b/ILSpy.ReadyToRun/Properties/Resources.resx @@ -129,4 +129,7 @@ Show Unwind Info + + Show GC Info + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx index 9430c8a3d..9e59d7bc2 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx +++ b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx @@ -129,4 +129,7 @@ 显示展开信息 + + ? + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs index cfbf5a07d..aa6eb5211 100644 --- a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs +++ b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun ReadyToRunMethod readyToRunMethod = runtimeFunction.Method; WriteCommentLine(readyToRunMethod.SignatureString); - if (readyToRunMethod.GcInfo != null) + if (ReadyToRunOptions.GetIsShowGCInfo(null) && readyToRunMethod.GcInfo != null) { string[] lines = readyToRunMethod.GcInfo.ToString().Split(Environment.NewLine); WriteCommentLine("GC info:"); diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index c11450ef7..609000137 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -11,6 +11,7 @@ + @@ -18,5 +19,7 @@ + + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs index a1a9cf689..53da7a71f 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -39,6 +39,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings); s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings); s.IsShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(settings); + s.IsShowGCInfo = ReadyToRunOptions.GetIsShowGCInfo(settings); this.DataContext = s; } @@ -51,7 +52,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun public void Save(XElement root) { Options s = (Options)this.DataContext; - ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo, s.IsShowDebugInfo); + ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo, s.IsShowDebugInfo, s.IsShowGCInfo); } } @@ -86,6 +87,18 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } + private bool isShowGCInfo; + + public bool IsShowGCInfo { + get { + return isShowGCInfo; + } + set { + isShowGCInfo = value; + OnPropertyChanged(nameof(IsShowGCInfo)); + } + } + private string disassemblyFormat; public string DisassemblyFormat { diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs index 22fc68639..365d1dd9a 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs @@ -87,12 +87,32 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } - public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isShowUnwindInfo, bool isShowDebugInfo) + public static bool GetIsShowGCInfo(ILSpySettings settings) + { + if (settings == null) + { + settings = ILSpySettings.Load(); + } + XElement e = settings[ns + "ReadyToRunOptions"]; + XAttribute a = e.Attribute("IsShowGCInfo"); + + if (a == null) + { + return false; + } + else + { + return (bool)a; + } + } + + public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isShowUnwindInfo, bool isShowDebugInfo, bool isShowGCInfo) { XElement section = new XElement(ns + "ReadyToRunOptions"); section.SetAttributeValue("DisassemblyFormat", disassemblyFormat); section.SetAttributeValue("IsShowUnwindInfo", isShowUnwindInfo); section.SetAttributeValue("IsShowDebugInfo", isShowDebugInfo); + section.SetAttributeValue("IsShowGCInfo", isShowGCInfo); XElement existingElement = root.Element(ns + "ReadyToRunOptions"); if (existingElement != null) { From 290be277c6df429539bc1e1c314e0a607c9e4d21 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Tue, 5 Sep 2023 15:50:15 -0700 Subject: [PATCH 5/6] Chinese translation --- ILSpy.ReadyToRun/Properties/Resources.Designer.cs | 4 ++-- ILSpy.ReadyToRun/Properties/Resources.resx | 6 +++--- ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx | 8 ++++---- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ILSpy.ReadyToRun/Properties/Resources.Designer.cs b/ILSpy.ReadyToRun/Properties/Resources.Designer.cs index 5d4bb0f36..2b8162693 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.Designer.cs +++ b/ILSpy.ReadyToRun/Properties/Resources.Designer.cs @@ -90,9 +90,9 @@ namespace ILSpy.ReadyToRun.Properties { /// /// Looks up a localized string similar to Show Unwind Info. /// - public static string ShowUnwindInfo { + public static string ShowStackUnwindInfo { get { - return ResourceManager.GetString("ShowUnwindInfo", resourceCulture); + return ResourceManager.GetString("ShowStackUnwindInfo", resourceCulture); } } diff --git a/ILSpy.ReadyToRun/Properties/Resources.resx b/ILSpy.ReadyToRun/Properties/Resources.resx index 499c47add..bd77f2bf6 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.resx +++ b/ILSpy.ReadyToRun/Properties/Resources.resx @@ -126,10 +126,10 @@ Show Debug Info - - Show Unwind Info - Show GC Info + + Show Stack Unwind Info + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx index 9e59d7bc2..57523b138 100644 --- a/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx +++ b/ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx @@ -126,10 +126,10 @@ 显示调试信息 - - 显示展开信息 - - ? + 显示垃圾回收信息 + + + 显示堆栈展开信息 \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 609000137..137e0a6a1 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -15,7 +15,7 @@ - + From 2b8bf8143d5f7adee7fe78a51e16d9e94271adda Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Sep 2023 17:28:01 -0700 Subject: [PATCH 6/6] Show alternative message if no GC Info is found --- ILSpy.ReadyToRun/ReadyToRunDisassembler.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs index aa6eb5211..a5780db4e 100644 --- a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs +++ b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs @@ -50,13 +50,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun ReadyToRunMethod readyToRunMethod = runtimeFunction.Method; WriteCommentLine(readyToRunMethod.SignatureString); - if (ReadyToRunOptions.GetIsShowGCInfo(null) && readyToRunMethod.GcInfo != null) + if (ReadyToRunOptions.GetIsShowGCInfo(null)) { - string[] lines = readyToRunMethod.GcInfo.ToString().Split(Environment.NewLine); - WriteCommentLine("GC info:"); - foreach (string line in lines) + if (readyToRunMethod.GcInfo != null) { - WriteCommentLine(line); + string[] lines = readyToRunMethod.GcInfo.ToString().Split(Environment.NewLine); + WriteCommentLine("GC info:"); + foreach (string line in lines) + { + WriteCommentLine(line); + } + } + else + { + WriteCommentLine("GC Info is not available for this method"); } }