From a2312f594d8f69186767e1eadba98fe4740fa554 Mon Sep 17 00:00:00 2001 From: plupiman Date: Fri, 17 Jul 2020 15:30:20 -0700 Subject: [PATCH 1/6] Decorate ReadyToRun dissassembly with NativeVarInfo --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 4 +- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 180 +++++++++++++++++++-- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 2 - ILSpy/ILSpy.csproj | 4 +- 4 files changed, 172 insertions(+), 18 deletions(-) diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index dddbbb74c2..a31d531845 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -37,6 +37,9 @@ False + + ..\..\..\Desktop\r2r\ILCompiler.Reflection.ReadyToRun\bin\Debug\netstandard2.0\ILCompiler.Reflection.ReadyToRun.dll + @@ -57,7 +60,6 @@ - diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index f29c5ce73d..1437df6045 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -86,6 +86,8 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi .GroupBy(m => m.MethodHandle) .ToDictionary(g => g.Key, g => g.ToArray()); } + + bool showMetadataTokens = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens; bool showMetadataTokensInBase10 = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10; if (cacheEntry.methodMap.TryGetValue(method.MetadataToken, out var methods)) { @@ -103,12 +105,92 @@ public override void WriteCommentLine(ITextOutput output, string comment) output.WriteLine("; " + comment); } + private Dictionary>> WriteDebugInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) + { + Dictionary>> debugInfoDict = new Dictionary>>(); + IReadOnlyList runTimeList = readyToRunMethod.RuntimeFunctions; + foreach (RuntimeFunction runtimeFunction in runTimeList) { + DebugInfo debugInfo = runtimeFunction.DebugInfo; + if (debugInfo != null && debugInfo.BoundsList.Count > 0) { + for (int i = 0; i < debugInfo.VariablesList.Count; ++i) { + var varLoc = debugInfo.VariablesList[i]; + try { + HashSet > typeSet = new HashSet>(); + bool found = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet); + if (found) { + typeSet.Add(new Tuple(debugInfo, varLoc)); + } else { + typeSet = new HashSet>(); + debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet); + typeSet.Add(new Tuple(debugInfo, varLoc)); + } + + } catch (ArgumentNullException) { + output.WriteLine("Failed to find hash set of Debug info type"); + } + + if (varLoc.VariableLocation.VarLocType != VarLocType.VLT_REG && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK + && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK_BYREF) { + //debugInfoDict.Add(varLoc.VariableLocation.VarLocType, ) + output.WriteLine($" Variable Number: {varLoc.VariableNumber}"); + output.WriteLine($" Start Offset: 0x{varLoc.StartOffset:X}"); + output.WriteLine($" End Offset: 0x{varLoc.EndOffset:X}"); + output.WriteLine($" Loc Type: {varLoc.VariableLocation.VarLocType}"); + switch (varLoc.VariableLocation.VarLocType) { + case VarLocType.VLT_REG: + case VarLocType.VLT_REG_FP: + case VarLocType.VLT_REG_BYREF: + output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + break; + + case VarLocType.VLT_STK: + case VarLocType.VLT_STK_BYREF: + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data2}"); + break; + case VarLocType.VLT_REG_REG: + output.WriteLine($" Register 1: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Register 2: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}"); + break; + case VarLocType.VLT_REG_STK: + output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}"); + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data3}"); + break; + case VarLocType.VLT_STK_REG: + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data1}"); + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}"); + output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data3)}"); + break; + case VarLocType.VLT_STK2: + output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + output.WriteLine($" Stack Offset: {varLoc.VariableLocation.Data2}"); + break; + case VarLocType.VLT_FPSTK: + output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + break; + case VarLocType.VLT_FIXED_VA: + output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); + break; + + default: + throw new BadImageFormatException("Unexpected var loc type"); + } + + output.WriteLine(""); + } + } + } + } + return debugInfoDict; + } - private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) + + private Dictionary> WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) { - Dictionary unwindCodes = new Dictionary(); + Dictionary> unwindCodes = new Dictionary>(); if (runtimeFunction.UnwindInfo is UnwindInfo amd64UnwindInfo) { string parsedFlags = ""; if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) { @@ -128,8 +210,13 @@ private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFun 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]); - + if (unwindCodes.ContainsKey((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset))) { + unwindCodes[(ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset)].Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); + } else { + HashSet codeSet = new HashSet(); + codeSet.Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); + unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), codeSet); + } } } return unwindCodes; @@ -137,19 +224,19 @@ private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFun 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; + Dictionary> unwindInfo = null; if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { unwindInfo = WriteUnwindInfo(runtimeFunction, output); } - - + Dictionary>> debugInfo = WriteDebugInfo(readyToRunMethod, 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 GC and debug info + // TODO: Decorate the disassembly with GC var codeReader = new ByteArrayCodeReader(codeBytes); var decoder = Decoder.Create(bitness, codeReader); decoder.IP = address; @@ -172,7 +259,10 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade formatter.Options.FirstOperandCharIndex = 10; var tempOutput = new StringOutput(); ulong baseInstrIP = instructions[0].IP; + int counter = -1; foreach (var instr in instructions) { + counter++; + int byteBaseIndex = (int)(instr.IP - address); if (runtimeFunction.DebugInfo != null) { foreach (var bound in runtimeFunction.DebugInfo.BoundsList) { @@ -187,32 +277,98 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade } } } + formatter.Format(instr, tempOutput); output.Write(instr.IP.ToString("X16")); output.Write(" "); int instrLen = instr.Length; - for (int i = 0; i < instrLen; i++) + for (int i = 0; i < instrLen; i++) { output.Write(codeBytes[byteBaseIndex + i].ToString("X2")); + } int missingBytes = 10 - instrLen; for (int i = 0; i < missingBytes; i++) output.Write(" "); output.Write(" "); output.Write(tempOutput.ToStringAndReset()); DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr); + DecorateDebugInfo(output, instr, debugInfo, baseInstrIP); DecorateCallSite(currentFile, output, reader, showMetadataTokens, showMetadataTokensInBase10, instr); } output.WriteLine(); } - private static void DecorateUnwindInfo(ITextOutput output, Dictionary unwindInfo, ulong baseInstrIP, Instruction instr) + private static void DecorateUnwindInfo(ITextOutput output, Dictionary> 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})"); + foreach (var unwindCode in unwindInfo[nextInstructionOffset]) { + output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); + } } } + private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dictionary>> debugInfoDict, ulong baseInstrIP) + { + if (debugInfoDict != null) { + InstructionInfoFactory factory = new InstructionInfoFactory(); + InstructionInfo info = factory.GetInfo(instr); + HashSet> stkSet = new HashSet>(); + if (debugInfoDict.ContainsKey(VarLocType.VLT_STK)) { + stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK]); + } + if (debugInfoDict.ContainsKey(VarLocType.VLT_STK_BYREF)) { + stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK_BYREF]); + } + if (stkSet != null) { + foreach (UsedMemory usedMemInfo in info.GetUsedMemory()) { //for each time a [register +- value] is used + foreach (Tuple tuple in stkSet) { //for each VLT_STK variable + var debugInfo = tuple.Item1; + var varInfo = tuple.Item2; + int stackOffset = varInfo.VariableLocation.Data2; + ulong adjOffset; + bool negativeOffset; + if (stackOffset < 0) { + int absValue = -1 * stackOffset; + adjOffset = ulong.MaxValue - (ulong)absValue + 1; + negativeOffset = true; + } else { + adjOffset = (ulong)stackOffset; + negativeOffset = false; + } + if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && + DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Base.ToString() && + adjOffset == usedMemInfo.Displacement) { + + output.Write($"; [{usedMemInfo.Base.ToString()}{(negativeOffset ? '-' : '+')}{Math.Abs(stackOffset)}] = {varInfo.Variable.Type} {varInfo.Variable.Index}"); + } + } + } + } + HashSet> regSet = new HashSet>(); + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG)) { + regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG]); + } + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_BYREF)) { + regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG_BYREF]); + } + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_FP)) { + regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG_FP]); + } + if (regSet != null) { + foreach (UsedRegister usedMemInfo in info.GetUsedRegisters()) { + foreach (Tuple tuple in regSet) { + var debugInfo = tuple.Item1; + var varInfo = tuple.Item2; + if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && + DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) { + + output.Write($"; {usedMemInfo.Register.ToString()} = {varInfo.Variable.Type} {varInfo.Variable.Index}"); + } + } + } + } + } + } private static void DecorateCallSite(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, bool showMetadataTokens, bool showMetadataTokensInBase10, Instruction instr) { int importCellAddress = (int)instr.IPRelativeMemoryAddress; diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 188f52994f..55fcf2fb63 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -15,7 +15,5 @@ Show Unwind Info - Show Debug Info - \ No newline at end of file diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 71414747bc..4d4ee4e3a8 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -128,9 +128,7 @@ - - Form - + From 28a1382a52dbba8f7891b86806524724ed7932a9 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Sun, 2 Aug 2020 12:11:47 -0700 Subject: [PATCH 2/6] Some changes I wanted --- ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj | 4 +- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 57 +++++++------------ ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml | 2 + ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs | 14 ++++- ILSpy.ReadyToRun/ReadyToRunOptions.cs | 24 ++++++-- ILSpy/ILSpy.csproj | 4 +- 6 files changed, 57 insertions(+), 48 deletions(-) diff --git a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj index a31d531845..aacd891977 100644 --- a/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj +++ b/ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj @@ -37,9 +37,6 @@ False - - ..\..\..\Desktop\r2r\ILCompiler.Reflection.ReadyToRun\bin\Debug\netstandard2.0\ILCompiler.Reflection.ReadyToRun.dll - @@ -60,6 +57,7 @@ + diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 1437df6045..18355d9859 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -86,8 +86,6 @@ public override void DecompileMethod(IMethod method, ITextOutput output, Decompi .GroupBy(m => m.MethodHandle) .ToDictionary(g => g.Key, g => g.ToArray()); } - - bool showMetadataTokens = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens; bool showMetadataTokensInBase10 = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10; if (cacheEntry.methodMap.TryGetValue(method.MetadataToken, out var methods)) { @@ -115,7 +113,7 @@ private Dictionary>> WriteDe for (int i = 0; i < debugInfo.VariablesList.Count; ++i) { var varLoc = debugInfo.VariablesList[i]; try { - HashSet > typeSet = new HashSet>(); + HashSet> typeSet = new HashSet>(); bool found = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet); if (found) { typeSet.Add(new Tuple(debugInfo, varLoc)); @@ -124,14 +122,12 @@ private Dictionary>> WriteDe debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet); typeSet.Add(new Tuple(debugInfo, varLoc)); } - } catch (ArgumentNullException) { output.WriteLine("Failed to find hash set of Debug info type"); } if (varLoc.VariableLocation.VarLocType != VarLocType.VLT_REG && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK_BYREF) { - //debugInfoDict.Add(varLoc.VariableLocation.VarLocType, ) output.WriteLine($" Variable Number: {varLoc.VariableNumber}"); output.WriteLine($" Start Offset: 0x{varLoc.StartOffset:X}"); output.WriteLine($" End Offset: 0x{varLoc.EndOffset:X}"); @@ -142,7 +138,6 @@ private Dictionary>> WriteDe case VarLocType.VLT_REG_BYREF: output.WriteLine($" Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; - case VarLocType.VLT_STK: case VarLocType.VLT_STK_BYREF: output.WriteLine($" Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); @@ -172,25 +167,20 @@ private Dictionary>> WriteDe case VarLocType.VLT_FIXED_VA: output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; - default: throw new BadImageFormatException("Unexpected var loc type"); } - output.WriteLine(""); } } - } } return debugInfoDict; } - - private Dictionary> WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) - + private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) { - Dictionary> unwindCodes = new Dictionary>(); + Dictionary unwindCodes = new Dictionary(); if (runtimeFunction.UnwindInfo is UnwindInfo amd64UnwindInfo) { string parsedFlags = ""; if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) { @@ -210,13 +200,7 @@ private Dictionary> WriteUnwindInfo(RuntimeFunction r 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++) { - if (unwindCodes.ContainsKey((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset))) { - unwindCodes[(ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset)].Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); - } else { - HashSet codeSet = new HashSet(); - codeSet.Add(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); - unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), codeSet); - } + unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex].CodeOffset), amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex]); } } return unwindCodes; @@ -224,19 +208,25 @@ private Dictionary> WriteUnwindInfo(RuntimeFunction r 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; + + Dictionary unwindInfo = null; if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { unwindInfo = WriteUnwindInfo(runtimeFunction, output); } - Dictionary>> debugInfo = WriteDebugInfo(readyToRunMethod, output); + + bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null); + Dictionary>> debugInfo = null; + if (isShowDebugInfo) { + debugInfo = WriteDebugInfo(readyToRunMethod, 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 GC + // TODO: Decorate the disassembly with GCInfo var codeReader = new ByteArrayCodeReader(codeBytes); var decoder = Decoder.Create(bitness, codeReader); decoder.IP = address; @@ -259,12 +249,9 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade formatter.Options.FirstOperandCharIndex = 10; var tempOutput = new StringOutput(); ulong baseInstrIP = instructions[0].IP; - int counter = -1; foreach (var instr in instructions) { - counter++; - int byteBaseIndex = (int)(instr.IP - address); - if (runtimeFunction.DebugInfo != null) { + if (isShowDebugInfo && runtimeFunction.DebugInfo != null) { foreach (var bound in runtimeFunction.DebugInfo.BoundsList) { if (bound.NativeOffset == byteBaseIndex) { if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog) { @@ -277,7 +264,6 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade } } } - formatter.Format(instr, tempOutput); output.Write(instr.IP.ToString("X16")); output.Write(" "); @@ -286,8 +272,9 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade output.Write(codeBytes[byteBaseIndex + i].ToString("X2")); } int missingBytes = 10 - instrLen; - for (int i = 0; i < missingBytes; i++) + for (int i = 0; i < missingBytes; i++) { output.Write(" "); + } output.Write(" "); output.Write(tempOutput.ToStringAndReset()); DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr); @@ -297,13 +284,12 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade output.WriteLine(); } - private static void DecorateUnwindInfo(ITextOutput output, Dictionary> unwindInfo, ulong baseInstrIP, Instruction instr) + private static void DecorateUnwindInfo(ITextOutput output, Dictionary unwindInfo, ulong baseInstrIP, Instruction instr) { ulong nextInstructionOffset = instr.NextIP - baseInstrIP; if (unwindInfo != null && unwindInfo.ContainsKey(nextInstructionOffset)) { - foreach (var unwindCode in unwindInfo[nextInstructionOffset]) { - output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); - } + UnwindCode unwindCode = unwindInfo[nextInstructionOffset]; + output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); } } @@ -338,7 +324,6 @@ private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dic if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Base.ToString() && adjOffset == usedMemInfo.Displacement) { - output.Write($"; [{usedMemInfo.Base.ToString()}{(negativeOffset ? '-' : '+')}{Math.Abs(stackOffset)}] = {varInfo.Variable.Type} {varInfo.Variable.Index}"); } } @@ -361,7 +346,6 @@ private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dic var varInfo = tuple.Item2; if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) { - output.Write($"; {usedMemInfo.Register.ToString()} = {varInfo.Variable.Type} {varInfo.Variable.Index}"); } } @@ -402,7 +386,6 @@ private static void DecorateCallSite(PEFile currentFile, ITextOutput output, Rea output.WriteLine(reader.ImportCellNames[importCellAddress]); break; } - output.WriteLine(); } else { output.WriteLine(); diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml index 55fcf2fb63..7fb149cbe1 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml @@ -15,5 +15,7 @@ Show Unwind Info + Show Debug Info + \ No newline at end of file diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs index 3e81b1c7c0..3bf810d851 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -36,6 +36,7 @@ public void Load(ILSpySettings settings) Options s = new Options(); s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings); s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings); + s.IsShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(settings); this.DataContext = s; } @@ -48,7 +49,7 @@ public void LoadDefaults() public void Save(XElement root) { Options s = (Options)this.DataContext; - ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo); + ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo, s.IsShowDebugInfo); } } @@ -71,6 +72,17 @@ public bool IsShowUnwindInfo { } } + private bool isShowDebugInfo; + + public bool IsShowDebugInfo { + get { + return isShowDebugInfo; + } + set { + isShowDebugInfo = value; + OnPropertyChanged(nameof(IsShowDebugInfo)); + } + } private string disassemblyFormat; diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs index 5eddd67891..f82535e630 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs @@ -43,7 +43,6 @@ public static string GetDisassemblyFormat(ILSpySettings settings) } public static bool GetIsShowUnwindInfo(ILSpySettings settings) - { if (settings == null) { settings = ILSpySettings.Load(); @@ -58,11 +57,27 @@ public static bool GetIsShowUnwindInfo(ILSpySettings settings) } } - public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool IsShowUnwindInfo) + public static bool GetIsShowDebugInfo(ILSpySettings settings) + { + if (settings == null) { + settings = ILSpySettings.Load(); + } + XElement e = settings[ns + "ReadyToRunOptions"]; + XAttribute a = e.Attribute("IsShowDebugInfo"); + + if (a == null) { + return true; + } else { + return (bool)a; + } + } + + public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isShowUnwindInfo, bool isShowDebugInfo) { XElement section = new XElement(ns + "ReadyToRunOptions"); section.SetAttributeValue("DisassemblyFormat", disassemblyFormat); - section.SetAttributeValue("IsShowUnwindInfo", IsShowUnwindInfo); + section.SetAttributeValue("IsShowUnwindInfo", isShowUnwindInfo); + section.SetAttributeValue("IsShowDebugInfo", isShowDebugInfo); XElement existingElement = root.Element(ns + "ReadyToRunOptions"); if (existingElement != null) { existingElement.ReplaceWith(section); @@ -70,8 +85,5 @@ public static void SetDisassemblyOptions(XElement root, string disassemblyFormat root.Add(section); } } - - } - } diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 4d4ee4e3a8..71414747bc 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -128,7 +128,9 @@ - + + Form + From 8b49cc0f5451c599805839536fee760b7583d1cb Mon Sep 17 00:00:00 2001 From: Edward Carlson Date: Wed, 5 Aug 2020 12:37:23 -0700 Subject: [PATCH 3/6] backup --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 36 ++++++++++++++------------ 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 18355d9859..7b8b62a8b9 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -103,9 +103,9 @@ public override void WriteCommentLine(ITextOutput output, string comment) output.WriteLine("; " + comment); } - private Dictionary>> WriteDebugInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) + private Dictionary> WriteDebugInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) { - Dictionary>> debugInfoDict = new Dictionary>>(); + Dictionary> debugInfoDict = new Dictionary>(); IReadOnlyList runTimeList = readyToRunMethod.RuntimeFunctions; foreach (RuntimeFunction runtimeFunction in runTimeList) { DebugInfo debugInfo = runtimeFunction.DebugInfo; @@ -113,14 +113,16 @@ private Dictionary>> WriteDe for (int i = 0; i < debugInfo.VariablesList.Count; ++i) { var varLoc = debugInfo.VariablesList[i]; try { - HashSet> typeSet = new HashSet>(); + var typeSet = new HashSet>(); bool found = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet); if (found) { - typeSet.Add(new Tuple(debugInfo, varLoc)); + (DebugInfo debugInfo, NativeVarInfo varLoc) newTuple = (debugInfo, varLoc); + typeSet.Add(newTuple); } else { - typeSet = new HashSet>(); + typeSet = new HashSet>(); debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet); - typeSet.Add(new Tuple(debugInfo, varLoc)); + (DebugInfo debugInfo, NativeVarInfo varLoc) newTuple = (debugInfo, varLoc); + typeSet.Add(newTuple); } } catch (ArgumentNullException) { output.WriteLine("Failed to find hash set of Debug info type"); @@ -168,7 +170,7 @@ private Dictionary>> WriteDe output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; default: - throw new BadImageFormatException("Unexpected var loc type"); + throw new BadImageFormatException("Unexpected variable type"); } output.WriteLine(""); } @@ -216,7 +218,7 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade } bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null); - Dictionary>> debugInfo = null; + Dictionary>> debugInfo = null; if (isShowDebugInfo) { debugInfo = WriteDebugInfo(readyToRunMethod, output); } @@ -293,12 +295,12 @@ private static void DecorateUnwindInfo(ITextOutput output, Dictionary>> debugInfoDict, ulong baseInstrIP) + private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dictionary> debugInfoDict, ulong baseInstrIP) { if (debugInfoDict != null) { InstructionInfoFactory factory = new InstructionInfoFactory(); InstructionInfo info = factory.GetInfo(instr); - HashSet> stkSet = new HashSet>(); + HashSet> stkSet = new HashSet>(); if (debugInfoDict.ContainsKey(VarLocType.VLT_STK)) { stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK]); } @@ -307,9 +309,9 @@ private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dic } if (stkSet != null) { foreach (UsedMemory usedMemInfo in info.GetUsedMemory()) { //for each time a [register +- value] is used - foreach (Tuple tuple in stkSet) { //for each VLT_STK variable - var debugInfo = tuple.Item1; - var varInfo = tuple.Item2; + foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in stkSet) { //for each VLT_STK variable + var debugInfo = tuple.debugInfo; + var varInfo = tuple.varLoc; int stackOffset = varInfo.VariableLocation.Data2; ulong adjOffset; bool negativeOffset; @@ -329,7 +331,7 @@ private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dic } } } - HashSet> regSet = new HashSet>(); + HashSet> regSet = new HashSet>(); if (debugInfoDict.ContainsKey(VarLocType.VLT_REG)) { regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG]); } @@ -341,9 +343,9 @@ private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dic } if (regSet != null) { foreach (UsedRegister usedMemInfo in info.GetUsedRegisters()) { - foreach (Tuple tuple in regSet) { - var debugInfo = tuple.Item1; - var varInfo = tuple.Item2; + foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in regSet) { + var debugInfo = tuple.debugInfo; + var varInfo = tuple.varLoc; if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) { output.Write($"; {usedMemInfo.Register.ToString()} = {varInfo.Variable.Type} {varInfo.Variable.Index}"); From ef96d178bfffee40276f38247a7254a660c3cfec Mon Sep 17 00:00:00 2001 From: Edward Carlson Date: Thu, 6 Aug 2020 10:26:14 -0700 Subject: [PATCH 4/6] change from tuple to valuetuple --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 7b8b62a8b9..f10c40941d 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -210,6 +210,7 @@ private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFun private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10) { + // TODO: Decorate the disassembly with GCInfo WriteCommentLine(output, readyToRunMethod.SignatureString); Dictionary unwindInfo = null; @@ -228,7 +229,6 @@ private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReade codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i]; } - // TODO: Decorate the disassembly with GCInfo var codeReader = new ByteArrayCodeReader(codeBytes); var decoder = Decoder.Create(bitness, codeReader); decoder.IP = address; From eabe8f96357c6439b533da88afcd81984230ddbf Mon Sep 17 00:00:00 2001 From: Edward Kazuya Carlson Date: Sat, 8 Aug 2020 10:41:05 -0700 Subject: [PATCH 5/6] Update ILSpy.ReadyToRun/ReadyToRunLanguage.cs Change how it handle's unexpected var loc types. Co-authored-by: Siegfried Pammer --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index f10c40941d..602771a2f1 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -170,7 +170,7 @@ public override void WriteCommentLine(ITextOutput output, string comment) output.WriteLine($" Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}"); break; default: - throw new BadImageFormatException("Unexpected variable type"); + output.WriteLine("WRN: Unexpected variable location type"); } output.WriteLine(""); } From f9562d67019e93b1ffa2240138b128401ea30775 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 8 Aug 2020 20:19:58 +0200 Subject: [PATCH 6/6] Fix build. --- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 602771a2f1..bcf8308316 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -171,6 +171,7 @@ public override void WriteCommentLine(ITextOutput output, string comment) break; default: output.WriteLine("WRN: Unexpected variable location type"); + break; } output.WriteLine(""); }