|
|
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
@@ -21,6 +21,7 @@ using System.Collections.Generic;
|
|
|
|
|
using System.Threading; |
|
|
|
|
using Mono.Cecil; |
|
|
|
|
using Mono.Cecil.Cil; |
|
|
|
|
using Mono.Collections.Generic; |
|
|
|
|
|
|
|
|
|
namespace ICSharpCode.Decompiler.Disassembler |
|
|
|
|
{ |
|
|
|
@ -30,15 +31,24 @@ namespace ICSharpCode.Decompiler.Disassembler
@@ -30,15 +31,24 @@ namespace ICSharpCode.Decompiler.Disassembler
|
|
|
|
|
public class MethodBodyDisassembler |
|
|
|
|
{ |
|
|
|
|
readonly ITextOutput output; |
|
|
|
|
readonly bool detectControlStructure; |
|
|
|
|
readonly CancellationToken cancellationToken; |
|
|
|
|
|
|
|
|
|
public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken) |
|
|
|
|
/// <summary>
|
|
|
|
|
/// Show .try/finally as blocks in IL code; indent loops.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool DetectControlStructure { get; set; } = true; |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Show sequence points if debug information is loaded in Cecil.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool ShowSequencePoints { get; set; } |
|
|
|
|
|
|
|
|
|
Collection<SequencePoint> sequencePoints; |
|
|
|
|
int nextSequencePointIndex; |
|
|
|
|
|
|
|
|
|
public MethodBodyDisassembler(ITextOutput output, CancellationToken cancellationToken) |
|
|
|
|
{ |
|
|
|
|
if (output == null) |
|
|
|
|
throw new ArgumentNullException(nameof(output)); |
|
|
|
|
this.output = output; |
|
|
|
|
this.detectControlStructure = detectControlStructure; |
|
|
|
|
this.output = output ?? throw new ArgumentNullException(nameof(output)); |
|
|
|
|
this.cancellationToken = cancellationToken; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -55,7 +65,9 @@ namespace ICSharpCode.Decompiler.Disassembler
@@ -55,7 +65,9 @@ namespace ICSharpCode.Decompiler.Disassembler
|
|
|
|
|
DisassembleLocalsBlock(body); |
|
|
|
|
output.WriteLine(); |
|
|
|
|
|
|
|
|
|
if (detectControlStructure && body.Instructions.Count > 0) { |
|
|
|
|
sequencePoints = method.DebugInformation?.SequencePoints; |
|
|
|
|
nextSequencePointIndex = 0; |
|
|
|
|
if (DetectControlStructure && body.Instructions.Count > 0) { |
|
|
|
|
Instruction inst = body.Instructions[0]; |
|
|
|
|
HashSet<int> branchTargets = GetBranchTargets(body.Instructions); |
|
|
|
|
WriteStructureBody(new ILStructure(body), branchTargets, ref inst, method.Body.CodeSize); |
|
|
|
@ -66,6 +78,7 @@ namespace ICSharpCode.Decompiler.Disassembler
@@ -66,6 +78,7 @@ namespace ICSharpCode.Decompiler.Disassembler
|
|
|
|
|
} |
|
|
|
|
WriteExceptionHandlers(body); |
|
|
|
|
} |
|
|
|
|
sequencePoints = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void DisassembleLocalsBlock(MethodBody body) |
|
|
|
@ -215,6 +228,21 @@ namespace ICSharpCode.Decompiler.Disassembler
@@ -215,6 +228,21 @@ namespace ICSharpCode.Decompiler.Disassembler
|
|
|
|
|
|
|
|
|
|
protected virtual void WriteInstruction(ITextOutput output, Instruction instruction) |
|
|
|
|
{ |
|
|
|
|
if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) { |
|
|
|
|
SequencePoint sp = sequencePoints[nextSequencePointIndex]; |
|
|
|
|
if (sp.Offset <= instruction.Offset) { |
|
|
|
|
output.Write("// sequence point: "); |
|
|
|
|
if (sp.Offset != instruction.Offset) { |
|
|
|
|
output.Write("!! at " + DisassemblerHelpers.OffsetToString(sp.Offset) + " !!"); |
|
|
|
|
} |
|
|
|
|
if (sp.IsHidden) { |
|
|
|
|
output.WriteLine("hidden"); |
|
|
|
|
} else { |
|
|
|
|
output.WriteLine($"(line {sp.StartLine}, col {sp.StartColumn}) to (line {sp.EndLine}, col {sp.EndColumn}) in {sp.Document?.Url}"); |
|
|
|
|
} |
|
|
|
|
nextSequencePointIndex++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
instruction.WriteTo(output); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|