|
|
@ -33,8 +33,8 @@ using ICSharpCode.Decompiler.IL; |
|
|
|
using ICSharpCode.Decompiler.Metadata; |
|
|
|
using ICSharpCode.Decompiler.Metadata; |
|
|
|
using ICSharpCode.Decompiler.Solution; |
|
|
|
using ICSharpCode.Decompiler.Solution; |
|
|
|
using ICSharpCode.Decompiler.TypeSystem; |
|
|
|
using ICSharpCode.Decompiler.TypeSystem; |
|
|
|
using ICSharpCode.ILSpy.TextView; |
|
|
|
|
|
|
|
using ILCompiler.Reflection.ReadyToRun; |
|
|
|
using ILCompiler.Reflection.ReadyToRun; |
|
|
|
|
|
|
|
using ILCompiler.Reflection.ReadyToRun.Amd64; |
|
|
|
|
|
|
|
|
|
|
|
namespace ICSharpCode.ILSpy.ReadyToRun |
|
|
|
namespace ICSharpCode.ILSpy.ReadyToRun |
|
|
|
{ |
|
|
|
{ |
|
|
@ -103,20 +103,20 @@ namespace ICSharpCode.ILSpy.ReadyToRun |
|
|
|
output.WriteLine("; " + comment); |
|
|
|
output.WriteLine("; " + comment); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode> WriteUnwindInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) |
|
|
|
private Dictionary<ulong, UnwindCode> WriteUnwindInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output) |
|
|
|
{ |
|
|
|
{ |
|
|
|
IReadOnlyList<RuntimeFunction> runTimeList = readyToRunMethod.RuntimeFunctions; |
|
|
|
IReadOnlyList<RuntimeFunction> runTimeList = readyToRunMethod.RuntimeFunctions; |
|
|
|
Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode> unwindCodes = new Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode>(); |
|
|
|
Dictionary<ulong, UnwindCode> unwindCodes = new Dictionary<ulong, UnwindCode>(); |
|
|
|
foreach (RuntimeFunction i in runTimeList) { |
|
|
|
foreach (RuntimeFunction i in runTimeList) { |
|
|
|
if (i.UnwindInfo is ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo amd64UnwindInfo) { |
|
|
|
if (i.UnwindInfo is UnwindInfo amd64UnwindInfo) { |
|
|
|
string parsedFlags = ""; |
|
|
|
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"; |
|
|
|
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"; |
|
|
|
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"; |
|
|
|
parsedFlags += " CHAININFO"; |
|
|
|
} |
|
|
|
} |
|
|
|
if (parsedFlags.Length == 0) { |
|
|
|
if (parsedFlags.Length == 0) { |
|
|
@ -138,10 +138,9 @@ 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) |
|
|
|
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); |
|
|
|
WriteCommentLine(output, readyToRunMethod.SignatureString); |
|
|
|
Dictionary<ulong, ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode> unwindInfo = null; |
|
|
|
Dictionary<ulong, UnwindCode> unwindInfo = null; |
|
|
|
if (ReadyToRunOptions.GetIsChecked(null)) { |
|
|
|
if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { |
|
|
|
unwindInfo = WriteUnwindInfo(readyToRunMethod, output); |
|
|
|
unwindInfo = WriteUnwindInfo(readyToRunMethod, output); |
|
|
|
WriteCommentLine(output, unwindInfo.ToString()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
byte[] codeBytes = new byte[runtimeFunction.Size]; |
|
|
|
byte[] codeBytes = new byte[runtimeFunction.Size]; |
|
|
@ -149,7 +148,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun |
|
|
|
codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + 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 codeReader = new ByteArrayCodeReader(codeBytes); |
|
|
|
var decoder = Decoder.Create(bitness, codeReader); |
|
|
|
var decoder = Decoder.Create(bitness, codeReader); |
|
|
|
decoder.IP = address; |
|
|
|
decoder.IP = address; |
|
|
@ -198,15 +197,28 @@ namespace ICSharpCode.ILSpy.ReadyToRun |
|
|
|
output.Write(" "); |
|
|
|
output.Write(" "); |
|
|
|
output.Write(" "); |
|
|
|
output.Write(" "); |
|
|
|
output.Write(tempOutput.ToStringAndReset()); |
|
|
|
output.Write(tempOutput.ToStringAndReset()); |
|
|
|
int importCellAddress = (int)instr.IPRelativeMemoryAddress; |
|
|
|
DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr); |
|
|
|
if (unwindInfo!= null && unwindInfo.ContainsKey(instr.IP - baseInstrIP)) { |
|
|
|
DecorateCallSite(currentFile, output, reader, showMetadataTokens, showMetadataTokensInBase10, instr); |
|
|
|
ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode unwindCode = unwindInfo[instr.IP - baseInstrIP]; |
|
|
|
} |
|
|
|
output.Write($" ; UnwindCode: OpCode: {unwindCode.UnwindOp} Op: {unwindCode.OpInfoStr}"); |
|
|
|
output.WriteLine(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void DecorateUnwindInfo(ITextOutput output, Dictionary<ulong, UnwindCode> 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)) { |
|
|
|
if (instr.IsCallNearIndirect && reader.ImportCellNames.ContainsKey(importCellAddress)) { |
|
|
|
output.Write(" ; "); |
|
|
|
output.Write(" ; "); |
|
|
|
ReadyToRunSignature signature = reader.ImportSignatures[(int)instr.IPRelativeMemoryAddress]; |
|
|
|
ReadyToRunSignature signature = reader.ImportSignatures[(int)instr.IPRelativeMemoryAddress]; |
|
|
|
switch(signature) { |
|
|
|
switch (signature) { |
|
|
|
case MethodDefEntrySignature methodDefSignature: |
|
|
|
case MethodDefEntrySignature methodDefSignature: |
|
|
|
var methodDefToken = MetadataTokens.EntityHandle(unchecked((int)methodDefSignature.MethodDefToken)); |
|
|
|
var methodDefToken = MetadataTokens.EntityHandle(unchecked((int)methodDefSignature.MethodDefToken)); |
|
|
|
if (showMetadataTokens) { |
|
|
|
if (showMetadataTokens) { |
|
|
@ -239,8 +251,6 @@ namespace ICSharpCode.ILSpy.ReadyToRun |
|
|
|
output.WriteLine(); |
|
|
|
output.WriteLine(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
output.WriteLine(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override RichText GetRichTextTooltip(IEntity entity) |
|
|
|
public override RichText GetRichTextTooltip(IEntity entity) |
|
|
|
{ |
|
|
|
{ |
|
|
|