Browse Source

Merge pull request #3076 from eduardo-vp/add/gc-info

pull/3081/head
Siegfried Pammer 2 years ago committed by GitHub
parent
commit
0c2e4b145b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      ILSpy.ReadyToRun/Properties/Resources.Designer.cs
  2. 7
      ILSpy.ReadyToRun/Properties/Resources.resx
  3. 7
      ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx
  4. 52
      ILSpy.ReadyToRun/ReadyToRunDisassembler.cs
  5. 5
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml
  6. 15
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
  7. 22
      ILSpy.ReadyToRun/ReadyToRunOptions.cs

13
ILSpy.ReadyToRun/Properties/Resources.Designer.cs generated

@ -90,9 +90,18 @@ namespace ILSpy.ReadyToRun.Properties {
/// <summary> /// <summary>
/// Looks up a localized string similar to Show Unwind Info. /// Looks up a localized string similar to Show Unwind Info.
/// </summary> /// </summary>
public static string ShowUnwindInfo { public static string ShowStackUnwindInfo {
get { get {
return ResourceManager.GetString("ShowUnwindInfo", resourceCulture); return ResourceManager.GetString("ShowStackUnwindInfo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show GC Info.
/// </summary>
public static string ShowGCInfo {
get {
return ResourceManager.GetString("ShowGCInfo", resourceCulture);
} }
} }
} }

7
ILSpy.ReadyToRun/Properties/Resources.resx

@ -126,7 +126,10 @@
<data name="ShowDebugInfo" xml:space="preserve"> <data name="ShowDebugInfo" xml:space="preserve">
<value>Show Debug Info</value> <value>Show Debug Info</value>
</data> </data>
<data name="ShowUnwindInfo" xml:space="preserve"> <data name="ShowGCInfo" xml:space="preserve">
<value>Show Unwind Info</value> <value>Show GC Info</value>
</data>
<data name="ShowStackUnwindInfo" xml:space="preserve">
<value>Show Stack Unwind Info</value>
</data> </data>
</root> </root>

7
ILSpy.ReadyToRun/Properties/Resources.zh-Hans.resx

@ -126,7 +126,10 @@
<data name="ShowDebugInfo" xml:space="preserve"> <data name="ShowDebugInfo" xml:space="preserve">
<value>显示调试信息</value> <value>显示调试信息</value>
</data> </data>
<data name="ShowUnwindInfo" xml:space="preserve"> <data name="ShowGCInfo" xml:space="preserve">
<value>显示展开信息</value> <value>显示垃圾回收信息</value>
</data>
<data name="ShowStackUnwindInfo" xml:space="preserve">
<value>显示堆栈展开信息</value>
</data> </data>
</root> </root>

52
ILSpy.ReadyToRun/ReadyToRunDisassembler.cs

@ -47,10 +47,26 @@ namespace ICSharpCode.ILSpy.ReadyToRun
public void Disassemble(PEFile currentFile, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10) public void Disassemble(PEFile currentFile, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10)
{ {
// TODO: Decorate the disassembly with GCInfo
ReadyToRunMethod readyToRunMethod = runtimeFunction.Method; ReadyToRunMethod readyToRunMethod = runtimeFunction.Method;
WriteCommentLine(readyToRunMethod.SignatureString); WriteCommentLine(readyToRunMethod.SignatureString);
if (ReadyToRunOptions.GetIsShowGCInfo(null))
{
if (readyToRunMethod.GcInfo != null)
{
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");
}
}
Dictionary<ulong, UnwindCode> unwindInfo = null; Dictionary<ulong, UnwindCode> unwindInfo = null;
if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64)
{ {
@ -96,30 +112,36 @@ namespace ICSharpCode.ILSpy.ReadyToRun
formatter.Options.FirstOperandCharIndex = 10; formatter.Options.FirstOperandCharIndex = 10;
var tempOutput = new StringOutput(); var tempOutput = new StringOutput();
ulong baseInstrIP = instructions[0].IP; ulong baseInstrIP = instructions[0].IP;
var boundsMap = new Dictionary<uint, uint>();
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) foreach (var instr in instructions)
{ {
int byteBaseIndex = (int)(instr.IP - address); int byteBaseIndex = (int)(instr.IP - address);
if (isShowDebugInfo && runtimeFunction.DebugInfo != null) 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 (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog) if (boundILOffset == (uint)DebugInfoBoundsType.Prolog)
{ {
WriteCommentLine("Prolog"); WriteCommentLine("Prolog");
} }
else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog) else if (boundILOffset == (uint)DebugInfoBoundsType.Epilog)
{ {
WriteCommentLine("Epilog"); WriteCommentLine("Epilog");
} }
else else
{ {
WriteCommentLine($"IL_{bound.ILOffset:x4}"); WriteCommentLine($"IL_{boundILOffset:x4}");
}
} }
} }
} }
DecorateGCInfo(instr, baseInstrIP, readyToRunMethod.GcInfo);
formatter.Format(instr, tempOutput); formatter.Format(instr, tempOutput);
output.Write(instr.IP.ToString("X16")); output.Write(instr.IP.ToString("X16"));
output.Write(" "); output.Write(" ");
@ -143,6 +165,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun
output.WriteLine(); 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<BaseGcTransition> 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) private void WriteCommentLine(string comment)
{ {
output.WriteLine("; " + comment); output.WriteLine("; " + comment);

5
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml

@ -11,12 +11,15 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Margin="3" Text="{x:Static properties:Resources.DisassemblyFormat}" /> <TextBlock Margin="3" Text="{x:Static properties:Resources.DisassemblyFormat}" />
<ComboBox Grid.Column="1" Margin="3" ItemsSource="{Binding DisassemblyFormats}" SelectedItem="{Binding DisassemblyFormat}" /> <ComboBox Grid.Column="1" Margin="3" ItemsSource="{Binding DisassemblyFormats}" SelectedItem="{Binding DisassemblyFormat}" />
<TextBlock Grid.Row="1" Margin="3" Text="{x:Static properties:Resources.ShowUnwindInfo}"/> <TextBlock Grid.Row="1" Margin="3" Text="{x:Static properties:Resources.ShowStackUnwindInfo}"/>
<CheckBox Grid.Row="1" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowUnwindInfo}" /> <CheckBox Grid.Row="1" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowUnwindInfo}" />
<TextBlock Grid.Row="2" Margin="3" Text="{x:Static properties:Resources.ShowDebugInfo}"/> <TextBlock Grid.Row="2" Margin="3" Text="{x:Static properties:Resources.ShowDebugInfo}"/>
<CheckBox Grid.Row="2" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowDebugInfo}" /> <CheckBox Grid.Row="2" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowDebugInfo}" />
<TextBlock Grid.Row="3" Margin="3" Text="{x:Static properties:Resources.ShowGCInfo}"/>
<CheckBox Grid.Row="3" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowGCInfo}" />
</Grid> </Grid>
</UserControl> </UserControl>

15
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs

@ -39,6 +39,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings); s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings);
s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings); s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings);
s.IsShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(settings); s.IsShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(settings);
s.IsShowGCInfo = ReadyToRunOptions.GetIsShowGCInfo(settings);
this.DataContext = s; this.DataContext = s;
} }
@ -51,7 +52,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
public void Save(XElement root) public void Save(XElement root)
{ {
Options s = (Options)this.DataContext; 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; private string disassemblyFormat;
public string DisassemblyFormat { public string DisassemblyFormat {

22
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"); XElement section = new XElement(ns + "ReadyToRunOptions");
section.SetAttributeValue("DisassemblyFormat", disassemblyFormat); section.SetAttributeValue("DisassemblyFormat", disassemblyFormat);
section.SetAttributeValue("IsShowUnwindInfo", isShowUnwindInfo); section.SetAttributeValue("IsShowUnwindInfo", isShowUnwindInfo);
section.SetAttributeValue("IsShowDebugInfo", isShowDebugInfo); section.SetAttributeValue("IsShowDebugInfo", isShowDebugInfo);
section.SetAttributeValue("IsShowGCInfo", isShowGCInfo);
XElement existingElement = root.Element(ns + "ReadyToRunOptions"); XElement existingElement = root.Element(ns + "ReadyToRunOptions");
if (existingElement != null) if (existingElement != null)
{ {

Loading…
Cancel
Save