From 116b377250363b5734cf5820dd36f201d9b4453f Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Sat, 20 Jun 2020 10:36:45 -0700 Subject: [PATCH] Improving the code --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 112 ++++++++++-------- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 25 ++-- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs | 14 +-- ILSpy.ReadyToRun/ReadyToRunOptions.cs | 8 +- 4 files changed, 86 insertions(+), 73 deletions(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 07ea593ea..b273cfba7 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -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,20 +103,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine("; " + comment); } - private Dictionary WriteUnwindInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) + private Dictionary WriteUnwindInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) { IReadOnlyList runTimeList = readyToRunMethod.RuntimeFunctions; - Dictionary unwindCodes = new Dictionary(); + Dictionary unwindCodes = new Dictionary(); foreach (RuntimeFunction i in runTimeList) { - if (i.UnwindInfo is ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo amd64UnwindInfo) { + if (i.UnwindInfo is UnwindInfo amd64UnwindInfo) { string parsedFlags = ""; - if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_EHANDLER) != 0) { + if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) { parsedFlags += " EHANDLER"; } - if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_UHANDLER) != 0) { + if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_UHANDLER) != 0) { parsedFlags += " UHANDLER"; } - if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_CHAININFO) != 0) { + if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_CHAININFO) != 0) { parsedFlags += " CHAININFO"; } if (parsedFlags.Length == 0) { @@ -128,7 +128,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun WriteCommentLine(output, $"FrameRegister: {((amd64UnwindInfo.FrameRegister == 0) ? "none" : amd64UnwindInfo.FrameRegister.ToString())}"); for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++) { unwindCodes.Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset, amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); - + } } } @@ -138,18 +138,17 @@ namespace ICSharpCode.ILSpy.ReadyToRun 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 unwindInfo = null; - if (ReadyToRunOptions.GetIsChecked(null)) { + Dictionary unwindInfo = null; + if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { unwindInfo = WriteUnwindInfo(readyToRunMethod, output); - WriteCommentLine(output, unwindInfo.ToString()); } - + 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; @@ -198,48 +197,59 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.Write(" "); output.Write(" "); output.Write(tempOutput.ToStringAndReset()); - int importCellAddress = (int)instr.IPRelativeMemoryAddress; - if (unwindInfo!= null && unwindInfo.ContainsKey(instr.IP - baseInstrIP)) { - ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode unwindCode = unwindInfo[instr.IP - baseInstrIP]; - output.Write($" ; UnwindCode: OpCode: {unwindCode.UnwindOp} Op: {unwindCode.OpInfoStr}"); - } - if (instr.IsCallNearIndirect && reader.ImportCellNames.ContainsKey(importCellAddress)) { - output.Write(" ; "); - ReadyToRunSignature signature = reader.ImportSignatures[(int)instr.IPRelativeMemoryAddress]; - switch(signature) { - case MethodDefEntrySignature methodDefSignature: - var methodDefToken = MetadataTokens.EntityHandle(unchecked((int)methodDefSignature.MethodDefToken)); - if (showMetadataTokens) { - if (showMetadataTokensInBase10) { - output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken)}) ", "metadata"); - } else { - output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken):X8}) ", "metadata"); - } + DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr); + DecorateCallSite(currentFile, output, reader, showMetadataTokens, showMetadataTokensInBase10, instr); + } + output.WriteLine(); + } + + private static void DecorateUnwindInfo(ITextOutput output, Dictionary unwindInfo, ulong baseInstrIP, Instruction instr) + { + ulong nextInstructionOffset = instr.IP + (ulong)instr.Length - 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) { + case MethodDefEntrySignature methodDefSignature: + var methodDefToken = MetadataTokens.EntityHandle(unchecked((int)methodDefSignature.MethodDefToken)); + if (showMetadataTokens) { + if (showMetadataTokensInBase10) { + output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken)}) ", "metadata"); + } else { + output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken):X8}) ", "metadata"); } - methodDefToken.WriteTo(currentFile, output, Decompiler.Metadata.GenericContext.Empty); - break; - case MethodRefEntrySignature methodRefSignature: - var methodRefToken = MetadataTokens.EntityHandle(unchecked((int)methodRefSignature.MethodRefToken)); - if (showMetadataTokens) { - if (showMetadataTokensInBase10) { - output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken)}) ", "metadata"); - } else { - output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken):X8}) ", "metadata"); - } + } + methodDefToken.WriteTo(currentFile, output, Decompiler.Metadata.GenericContext.Empty); + break; + case MethodRefEntrySignature methodRefSignature: + var methodRefToken = MetadataTokens.EntityHandle(unchecked((int)methodRefSignature.MethodRefToken)); + if (showMetadataTokens) { + if (showMetadataTokensInBase10) { + output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken)}) ", "metadata"); + } else { + output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken):X8}) ", "metadata"); } - methodRefToken.WriteTo(currentFile, output, Decompiler.Metadata.GenericContext.Empty); - break; - default: - output.WriteLine(reader.ImportCellNames[importCellAddress]); - break; - } - - output.WriteLine(); - } else { - output.WriteLine(); + } + methodRefToken.WriteTo(currentFile, output, Decompiler.Metadata.GenericContext.Empty); + break; + default: + output.WriteLine(reader.ImportCellNames[importCellAddress]); + break; } + + output.WriteLine(); + } else { + output.WriteLine(); } - output.WriteLine(); } public override RichText GetRichTextTooltip(IEntity entity) diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 1548792ee..42840bee7 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -2,16 +2,19 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - - - Disassembly Format - Show Unwind Info - - - - - - - + + + + + + + + + + Disassembly Format + + Show Unwind Info + + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs index 26e5821c7..218ddb054 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun { Options s = new Options(); s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings); - s.IsChecked = ReadyToRunOptions.GetIsChecked(settings); + s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings); this.DataContext = s; } @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun public void Save(XElement root) { Options s = (Options)this.DataContext; - ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsChecked); + ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo); } } @@ -60,14 +60,14 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } - private bool isChecked; - public bool IsChecked { + private bool isShowUnwindInfo; + public bool IsShowUnwindInfo { get { - return isChecked; + return isShowUnwindInfo; } set { - isChecked = value; - OnPropertyChanged(nameof(IsChecked)); + isShowUnwindInfo = value; + OnPropertyChanged(nameof(IsShowUnwindInfo)); } } diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs index d0f263288..2317112b0 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs @@ -42,13 +42,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } - public static bool GetIsChecked(ILSpySettings settings) + public static bool GetIsShowUnwindInfo(ILSpySettings settings) { if (settings == null) { settings = ILSpySettings.Load(); } XElement e = settings[ns + "ReadyToRunOptions"]; - XAttribute a = e.Attribute("IsChecked"); + XAttribute a = e.Attribute("IsShowUnwindInfo"); if (a == null) { return false; } else { @@ -56,11 +56,11 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } - public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isChecked) + public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool IsShowUnwindInfo) { XElement section = new XElement(ns + "ReadyToRunOptions"); section.SetAttributeValue("DisassemblyFormat", disassemblyFormat); - section.SetAttributeValue("IsChecked", isChecked); + section.SetAttributeValue("IsShowUnwindInfo", IsShowUnwindInfo); XElement existingElement = root.Element(ns + "ReadyToRunOptions"); if (existingElement != null) {