diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 3bb34ee04..07ea593ea 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -103,9 +103,47 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine("; " + comment); } + private Dictionary WriteUnwindInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) + { + IReadOnlyList runTimeList = readyToRunMethod.RuntimeFunctions; + Dictionary unwindCodes = new Dictionary(); + foreach (RuntimeFunction i in runTimeList) { + if (i.UnwindInfo is ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo amd64UnwindInfo) { + string parsedFlags = ""; + if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_EHANDLER) != 0) { + parsedFlags += " EHANDLER"; + } + if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_UHANDLER) != 0) { + parsedFlags += " UHANDLER"; + } + if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.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(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 unwindInfo = null; + if (ReadyToRunOptions.GetIsChecked(null)) { + 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]; @@ -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) { @@ -160,6 +199,10 @@ namespace ICSharpCode.ILSpy.ReadyToRun 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]; @@ -190,6 +233,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.WriteLine(reader.ImportCellNames[importCellAddress]); break; } + output.WriteLine(); } else { output.WriteLine(); diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 9920b8344..1548792ee 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -3,8 +3,15 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - Disassembly Format - + + 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 ddbd6aed4..26e5821c7 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun { Options s = new Options(); s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings); + s.IsChecked = ReadyToRunOptions.GetIsChecked(settings); + this.DataContext = s; } @@ -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.IsChecked); } } @@ -58,6 +60,17 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } + private bool isChecked; + public bool IsChecked { + get { + return isChecked; + } + set { + isChecked = value; + OnPropertyChanged(nameof(IsChecked)); + } + } + private string disassemblyFormat; public string DisassemblyFormat { diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs index 6ee672880..d0f263288 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs @@ -42,10 +42,25 @@ namespace ICSharpCode.ILSpy.ReadyToRun } } - public static void SetDisassemblyFormat(XElement root, string disassemblyFormat) + public static bool GetIsChecked(ILSpySettings settings) + { + if (settings == null) { + settings = ILSpySettings.Load(); + } + XElement e = settings[ns + "ReadyToRunOptions"]; + XAttribute a = e.Attribute("IsChecked"); + if (a == null) { + return false; + } else { + return (bool)a; + } + } + + public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isChecked) { XElement section = new XElement(ns + "ReadyToRunOptions"); section.SetAttributeValue("DisassemblyFormat", disassemblyFormat); + section.SetAttributeValue("IsChecked", isChecked); XElement existingElement = root.Element(ns + "ReadyToRunOptions"); if (existingElement != null) { @@ -54,5 +69,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun root.Add(section); } } + } }