void WriteStructureFooter(ILStructure s) { output.Unindent(); switch (s.Type) { case ILStructureType.Loop: output.WriteLine("// end loop"); break; case ILStructureType.Try: output.WriteLine("} // end .try"); break; case ILStructureType.Handler: output.WriteLine("} // end handler"); break; case ILStructureType.Filter: output.WriteLine("} // end filter"); break; default: throw new NotSupportedException(); } }
void WriteStructureFooter(ILStructure s) { output.Unindent(); switch (s.Type) { case ILStructureType.Loop: output.WriteLine("// end loop", TextTokenType.Comment); break; case ILStructureType.Try: output.WriteRightBrace(); output.WriteSpace(); output.WriteLine("// end .try", TextTokenType.Comment); break; case ILStructureType.Handler: output.WriteRightBrace(); output.WriteSpace(); output.WriteLine("// end handler", TextTokenType.Comment); break; case ILStructureType.Filter: output.WriteRightBrace(); output.WriteSpace(); output.WriteLine("// end filter", TextTokenType.Comment); break; default: throw new NotSupportedException(); } }
void WriteStructureBody(ILStructure s, HashSet <int> branchTargets, ref BlobReader body) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (body.RemainingBytes > 0 && body.Offset < s.EndOffset) { int offset = body.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref body); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var currentOpCode = ILParser.DecodeOpCode(ref body); body.Offset = offset; // reset IL stream WriteInstruction(output, metadata, s.MethodHandle, ref body); prevInstructionWasBranch = currentOpCode.IsBranch() || currentOpCode.IsReturn() || currentOpCode == ILOpCode.Throw || currentOpCode == ILOpCode.Rethrow || currentOpCode == ILOpCode.Switch; } isFirstInstructionInStructure = false; } }
void WriteStructureBody(ILStructure s, HashSet <int> branchTargets, ref Instruction inst, int codeSize) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref inst, codeSize); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } WriteInstruction(output, inst); output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; inst = inst.Next; } isFirstInstructionInStructure = false; } }
void WriteStructureHeader(ILStructure s) { switch (s.Type) { case ILStructureType.Loop: output.Write("// loop start", TextTokenType.Comment); if (s.LoopEntryPoint != null) { output.Write(" (head: ", TextTokenType.Comment); DisassemblerHelpers.WriteOffsetReference(output, s.LoopEntryPoint, null, TextTokenType.Comment); output.Write(')', TextTokenType.Comment); } output.WriteLine(); break; case ILStructureType.Try: output.WriteLine(".try", TextTokenType.ILDirective); output.WriteLineLeftBrace(); break; case ILStructureType.Handler: switch (s.ExceptionHandler.HandlerType) { case ExceptionHandlerType.Catch: case ExceptionHandlerType.Filter: output.Write("catch", TextTokenType.Keyword); if (s.ExceptionHandler.CatchType != null) { output.WriteSpace(); s.ExceptionHandler.CatchType.WriteTo(output, ILNameSyntax.TypeName); } output.WriteLine(); break; case ExceptionHandlerType.Finally: output.WriteLine("finally", TextTokenType.Keyword); break; case ExceptionHandlerType.Fault: output.WriteLine("fault", TextTokenType.Keyword); break; default: output.WriteLine(s.ExceptionHandler.HandlerType.ToString(), TextTokenType.Keyword); break; } output.WriteLineLeftBrace(); break; case ILStructureType.Filter: output.WriteLine("filter", TextTokenType.Keyword); output.WriteLineLeftBrace(); break; default: throw new NotSupportedException(); } output.Indent(); }
void WriteStructureHeader(ILStructure s) { switch (s.Type) { case ILStructureType.Loop: output.Write("// loop start"); if (s.LoopEntryPointOffset >= 0) { output.Write(" (head: "); DisassemblerHelpers.WriteOffsetReference(output, s.LoopEntryPointOffset); output.Write(')'); } output.WriteLine(); break; case ILStructureType.Try: output.WriteLine(".try"); output.WriteLine("{"); break; case ILStructureType.Handler: switch (s.ExceptionHandler.Kind) { case ExceptionRegionKind.Catch: case ExceptionRegionKind.Filter: output.Write("catch"); if (!s.ExceptionHandler.CatchType.IsNil) { output.Write(' '); s.ExceptionHandler.CatchType.WriteTo(s.Module, output, s.GenericContext, ILNameSyntax.TypeName); } output.WriteLine(); break; case ExceptionRegionKind.Finally: output.WriteLine("finally"); break; case ExceptionRegionKind.Fault: output.WriteLine("fault"); break; default: throw new ArgumentOutOfRangeException(); } output.WriteLine("{"); break; case ILStructureType.Filter: output.WriteLine("filter"); output.WriteLine("{"); break; default: throw new ArgumentOutOfRangeException(); } output.Indent(); }
void WriteStructureHeader(ILStructure s) { switch (s.Type) { case ILStructureType.Loop: output.Write("// loop start"); if (s.LoopEntryPoint != null) { output.Write(" (head: "); DisassemblerHelpers.WriteOffsetReference(output, s.LoopEntryPoint); output.Write(')'); } output.WriteLine(); break; case ILStructureType.Try: output.WriteLine(".try"); output.WriteLine("{"); break; case ILStructureType.Handler: switch (s.ExceptionHandler.HandlerType) { case Mono.Cecil.Cil.ExceptionHandlerType.Catch: case Mono.Cecil.Cil.ExceptionHandlerType.Filter: output.Write("catch"); if (s.ExceptionHandler.CatchType != null) { output.Write(' '); s.ExceptionHandler.CatchType.WriteTo(output, ILNameSyntax.TypeName); } output.WriteLine(); break; case Mono.Cecil.Cil.ExceptionHandlerType.Finally: output.WriteLine("finally"); break; case Mono.Cecil.Cil.ExceptionHandlerType.Fault: output.WriteLine("fault"); break; default: throw new NotSupportedException(); } output.WriteLine("{"); break; case ILStructureType.Filter: output.WriteLine("filter"); output.WriteLine("{"); break; default: throw new NotSupportedException(); } output.Indent(); }
void WriteStructureBody(CilBody body, ILStructure s, HashSet <uint> branchTargets, ref int index, MemberMapping debugSymbols, int codeSize, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; var instructions = body.Instructions; while (index < instructions.Count) { Instruction inst = instructions[index]; if (inst.Offset >= s.EndOffset) { break; } uint offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(body, child, branchTargets, ref index, debugSymbols, codeSize, baseRva, baseOffs, byteReader, method); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var startLocation = output.Location; inst.WriteTo(output, options, baseRva, baseOffs, byteReader, method); // add IL code mappings - used in debugger if (debugSymbols != null) { var next = index + 1 < instructions.Count ? instructions[index + 1] : null; debugSymbols.MemberCodeMappings.Add( new SourceCodeMapping() { StartLocation = startLocation, EndLocation = output.Location, ILInstructionOffset = new ILRange(inst.Offset, next == null ? (uint)codeSize : next.Offset), MemberMapping = debugSymbols }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; index++; } isFirstInstructionInStructure = false; } }
void WriteStructureBody(MethodDef method, CilBody body, ILStructure s, HashSet <uint> branchTargets, ref int index, MemberMapping currentMethodMapping, int codeSize) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (index < body.Instructions.Count) { Instruction inst = body.Instructions[index]; uint offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(method, body, child, branchTargets, ref index, currentMethodMapping, codeSize); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var startLocation = output.Location; inst.WriteTo(method, output); // add IL code mappings - used in debugger if (currentMethodMapping != null) { var next = body.GetNext(inst); currentMethodMapping.MemberCodeMappings.Add( new SourceCodeMapping() { StartLocation = startLocation, EndLocation = output.Location, ILInstructionOffset = new ILRange { From = inst.Offset, To = next == null ? (uint)codeSize : next.Offset }, MemberMapping = currentMethodMapping }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; index++; } isFirstInstructionInStructure = false; } }
void WriteStructureBody(ILStructure s, HashSet <int> branchTargets, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref inst, currentMethodMapping, codeSize); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } inst.WriteTo(output); // add IL code mappings - used in debugger if (currentMethodMapping != null) { currentMethodMapping.MemberCodeMappings.Add( new SourceCodeMapping() { SourceCodeLine = output.CurrentLine, ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? codeSize : inst.Next.Offset }, MemberMapping = currentMethodMapping }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; inst = inst.Next; } isFirstInstructionInStructure = false; } }
private void WriteStructureBody(ILStructure s, HashSet <int> branchTargets, ref Instruction inst, MethodDebugSymbols debugSymbols, int codeSize) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref inst, debugSymbols, codeSize); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var startLocation = output.Location; inst.WriteTo(output); // add IL code mappings - used in debugger if (debugSymbols != null) { debugSymbols.SequencePoints.Add( new SequencePoint() { StartLocation = startLocation, EndLocation = output.Location, ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? codeSize : inst.Next.Offset) } }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; inst = inst.Next; } isFirstInstructionInStructure = false; } }
bool AddNestedStructure(ILStructure newStructure) { // special case: don't consider the loop-like structure of "continue;" statements to be nested loops if (this.Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == this.StartOffset) { return(false); } // use <= for end-offset comparisons because both end and EndOffset are exclusive Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset); foreach (ILStructure child in this.Children) { if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) { return(child.AddNestedStructure(newStructure)); } else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) { // child and newStructure overlap if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) { // Invalid nesting, can't build a tree. -> Don't add the new structure. return(false); } } } // Move existing structures into the new structure: for (int i = 0; i < this.Children.Count; i++) { ILStructure child = this.Children[i]; if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) { this.Children.RemoveAt(i--); newStructure.Children.Add(child); } } // Add the structure here: this.Children.Add(newStructure); return(true); }
void WriteStructureBody(ILStructure s, ref Instruction inst) { int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, ref inst); WriteStructureFooter(child); } else { inst.WriteTo(output); output.WriteLine(); inst = inst.Next; } } }
void WriteStructureBody(ILStructure s, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) { int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, ref inst, currentMethodMapping, codeSize); WriteStructureFooter(child); } else { inst.WriteTo(output); // add IL code mappings - used in debugger if (currentMethodMapping != null) { currentMethodMapping.MemberCodeMappings.Add( new SourceCodeMapping() { SourceCodeLine = output.CurrentLine, ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? codeSize : inst.Next.Offset }, MemberMapping = currentMethodMapping }); } output.WriteLine(); inst = inst.Next; } } }
void WriteStructureBody(CilBody body, ILStructure s, HashSet<uint> branchTargets, ref int index, MemberMapping debugSymbols, int codeSize, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; var instructions = body.Instructions; while (index < instructions.Count) { Instruction inst = instructions[index]; if (inst.Offset >= s.EndOffset) break; uint offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(body, child, branchTargets, ref index, debugSymbols, codeSize, baseRva, baseOffs, byteReader, method); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var startLocation = output.Location; inst.WriteTo(output, options, baseRva, baseOffs, byteReader, method); // add IL code mappings - used in debugger if (debugSymbols != null) { var next = index + 1 < instructions.Count ? instructions[index + 1] : null; debugSymbols.MemberCodeMappings.Add( new SourceCodeMapping() { StartLocation = startLocation, EndLocation = output.Location, ILInstructionOffset = new ILRange(inst.Offset, next == null ? (uint)codeSize : next.Offset), MemberMapping = debugSymbols }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; index++; } isFirstInstructionInStructure = false; } }
bool AddNestedStructure(ILStructure newStructure) { // special case: don't consider the loop-like structure of "continue;" statements to be nested loops if (this.Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == this.StartOffset) return false; // use <= for end-offset comparisons because both end and EndOffset are exclusive Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset); foreach (ILStructure child in this.Children) { if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) { return child.AddNestedStructure(newStructure); } else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) { // child and newStructure overlap if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) { // Invalid nesting, can't build a tree. -> Don't add the new structure. return false; } } } // Move existing structures into the new structure: for (int i = 0; i < this.Children.Count; i++) { ILStructure child = this.Children[i]; if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) { this.Children.RemoveAt(i--); newStructure.Children.Add(child); } } // Add the structure here: this.Children.Add(newStructure); return true; }
void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref inst, currentMethodMapping, codeSize); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } inst.WriteTo(output); // add IL code mappings - used in debugger if (currentMethodMapping != null) { currentMethodMapping.MemberCodeMappings.Add( new SourceCodeMapping() { SourceCodeLine = output.CurrentLine, ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? codeSize : inst.Next.Offset }, MemberMapping = currentMethodMapping }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; inst = inst.Next; } isFirstInstructionInStructure = false; } }
void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref Instruction inst, MethodDebugSymbols debugSymbols, int codeSize) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref inst, debugSymbols, codeSize); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var startLocation = output.Location; inst.WriteTo(output); // add IL code mappings - used in debugger if (debugSymbols != null) { debugSymbols.SequencePoints.Add( new SequencePoint() { StartLocation = startLocation, EndLocation = output.Location, ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? codeSize : inst.Next.Offset) } }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; inst = inst.Next; } isFirstInstructionInStructure = false; } }