Browse Source

Merge pull request #2043 from edkazcarlson/master

Added UnwindInfo as an optional printout
pull/2046/head
Siegfried Pammer 5 years ago committed by GitHub
parent
commit
c0ce62e2d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 65
      ILSpy.ReadyToRun/ReadyToRunLanguage.cs
  2. 23
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml
  3. 16
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
  4. 23
      ILSpy.ReadyToRun/ReadyToRunOptions.cs

65
ILSpy.ReadyToRun/ReadyToRunLanguage.cs

@ -33,8 +33,8 @@ using ICSharpCode.Decompiler.IL; @@ -33,8 +33,8 @@ using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TextView;
using ILCompiler.Reflection.ReadyToRun;
using ILCompiler.Reflection.ReadyToRun.Amd64;
namespace ICSharpCode.ILSpy.ReadyToRun
{
@ -103,15 +103,53 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -103,15 +103,53 @@ namespace ICSharpCode.ILSpy.ReadyToRun
output.WriteLine("; " + comment);
}
private Dictionary<ulong, UnwindCode> WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output)
{
Dictionary<ulong, UnwindCode> unwindCodes = new Dictionary<ulong, UnwindCode>();
if (runtimeFunction.UnwindInfo is UnwindInfo amd64UnwindInfo) {
string parsedFlags = "";
if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) {
parsedFlags += " EHANDLER";
}
if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_UHANDLER) != 0) {
parsedFlags += " UHANDLER";
}
if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_CHAININFO) != 0) {
parsedFlags += " CHAININFO";
}
if (parsedFlags.Length == 0) {
parsedFlags = " NHANDLER";
}
WriteCommentLine(output, $"UnwindInfo:");
WriteCommentLine(output, $"Version: {amd64UnwindInfo.Version}");
WriteCommentLine(output, $"Flags: 0x{amd64UnwindInfo.Flags:X2}{parsedFlags}");
WriteCommentLine(output, $"FrameRegister: {((amd64UnwindInfo.FrameRegister == 0) ? "none" : amd64UnwindInfo.FrameRegister.ToString())}");
for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++) {
unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]);
}
}
return unwindCodes;
}
private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10)
{
WriteCommentLine(output, readyToRunMethod.SignatureString);
Dictionary<ulong, UnwindCode> unwindInfo = null;
if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) {
unwindInfo = WriteUnwindInfo(runtimeFunction, output);
}
byte[] codeBytes = new byte[runtimeFunction.Size];
for (int i = 0; i < runtimeFunction.Size; i++) {
codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
}
// TODO: Decorate the disassembly with Unwind, GC and debug info
// TODO: Decorate the disassembly with GC and debug info
var codeReader = new ByteArrayCodeReader(codeBytes);
var decoder = Decoder.Create(bitness, codeReader);
decoder.IP = address;
@ -133,6 +171,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -133,6 +171,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
formatter.Options.DigitSeparator = "`";
formatter.Options.FirstOperandCharIndex = 10;
var tempOutput = new StringOutput();
ulong baseInstrIP = instructions[0].IP;
foreach (var instr in instructions) {
int byteBaseIndex = (int)(instr.IP - address);
if (runtimeFunction.DebugInfo != null) {
@ -159,11 +198,28 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -159,11 +198,28 @@ namespace ICSharpCode.ILSpy.ReadyToRun
output.Write(" ");
output.Write(" ");
output.Write(tempOutput.ToStringAndReset());
DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr);
DecorateCallSite(currentFile, output, reader, showMetadataTokens, showMetadataTokensInBase10, instr);
}
output.WriteLine();
}
private static void DecorateUnwindInfo(ITextOutput output, Dictionary<ulong, UnwindCode> unwindInfo, ulong baseInstrIP, Instruction instr)
{
ulong nextInstructionOffset = instr.NextIP - baseInstrIP;
if (unwindInfo != null && unwindInfo.ContainsKey(nextInstructionOffset)) {
UnwindCode unwindCode = unwindInfo[nextInstructionOffset];
output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})");
}
}
private static void DecorateCallSite(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, bool showMetadataTokens, bool showMetadataTokensInBase10, Instruction instr)
{
int importCellAddress = (int)instr.IPRelativeMemoryAddress;
if (instr.IsCallNearIndirect && reader.ImportCellNames.ContainsKey(importCellAddress)) {
output.Write(" ; ");
ReadyToRunSignature signature = reader.ImportSignatures[(int)instr.IPRelativeMemoryAddress];
switch(signature) {
switch (signature) {
case MethodDefEntrySignature methodDefSignature:
var methodDefToken = MetadataTokens.EntityHandle(unchecked((int)methodDefSignature.MethodDefToken));
if (showMetadataTokens) {
@ -190,13 +246,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -190,13 +246,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun
output.WriteLine(reader.ImportCellNames[importCellAddress]);
break;
}
output.WriteLine();
} else {
output.WriteLine();
}
}
output.WriteLine();
}
public override RichText GetRichTextTooltip(IEntity entity)
{

23
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml

@ -1,10 +1,21 @@ @@ -1,10 +1,21 @@
<UserControl x:Class="ICSharpCode.ILSpy.ReadyToRun.ReadyToRunOptionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock>Disassembly Format</TextBlock>
<ComboBox ItemsSource="{Binding DisassemblyFormats}" SelectedItem="{Binding DisassemblyFormat}"/>
</StackPanel>
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Margin="3">Disassembly Format</TextBlock>
<ComboBox Grid.Column="1" Margin="3" ItemsSource="{Binding DisassemblyFormats}" SelectedItem="{Binding DisassemblyFormat}" />
<TextBlock Grid.Row="1" Margin="3">Show Unwind Info</TextBlock>
<CheckBox Grid.Row="1" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowUnwindInfo}" />
<TextBlock Grid.Row="2" Margin="3">Show Debug Info</TextBlock>
<CheckBox Grid.Row="2" Grid.Column="1" Margin="3" IsChecked="{Binding DebugIsChecked}" />
</Grid>
</UserControl>

16
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs

@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun
{
Options s = new Options();
s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings);
s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings);
this.DataContext = s;
}
@ -46,7 +48,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -46,7 +48,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
public void Save(XElement root)
{
Options s = (Options)this.DataContext;
ReadyToRunOptions.SetDisassemblyFormat(root, s.DisassemblyFormat);
ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo);
}
}
@ -58,6 +60,18 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -58,6 +60,18 @@ namespace ICSharpCode.ILSpy.ReadyToRun
}
}
private bool isShowUnwindInfo;
public bool IsShowUnwindInfo {
get {
return isShowUnwindInfo;
}
set {
isShowUnwindInfo = value;
OnPropertyChanged(nameof(IsShowUnwindInfo));
}
}
private string disassemblyFormat;
public string DisassemblyFormat {

23
ILSpy.ReadyToRun/ReadyToRunOptions.cs

@ -42,11 +42,27 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -42,11 +42,27 @@ namespace ICSharpCode.ILSpy.ReadyToRun
}
}
public static void SetDisassemblyFormat(XElement root, string disassemblyFormat)
public static bool GetIsShowUnwindInfo(ILSpySettings settings)
{
if (settings == null) {
settings = ILSpySettings.Load();
}
XElement e = settings[ns + "ReadyToRunOptions"];
XAttribute a = e.Attribute("IsShowUnwindInfo");
if (a == null) {
return false;
} else {
return (bool)a;
}
}
public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool IsShowUnwindInfo)
{
XElement section = new XElement(ns + "ReadyToRunOptions");
section.SetAttributeValue("DisassemblyFormat", disassemblyFormat);
section.SetAttributeValue("IsShowUnwindInfo", IsShowUnwindInfo);
XElement existingElement = root.Element(ns + "ReadyToRunOptions");
if (existingElement != null) {
existingElement.ReplaceWith(section);
@ -54,5 +70,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -54,5 +70,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun
root.Add(section);
}
}
}
}

Loading…
Cancel
Save