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 DisassembleLocalsBlock(MethodDefinitionHandle method, MethodBodyBlock body) { if (body.LocalSignature.IsNil) { return; } output.Write(".locals"); WriteMetadataToken(body.LocalSignature, spaceBefore: true); if (body.LocalVariablesInitialized) { output.Write(" init"); } var blob = metadata.GetStandaloneSignature(body.LocalSignature); var signature = ImmutableArray <Action <ILNameSyntax> > .Empty; try { if (blob.GetKind() == StandaloneSignatureKind.LocalVariables) { signature = blob.DecodeLocalSignature(signatureDecoder, genericContext); } else { output.Write(" /* wrong signature kind */"); } } catch (BadImageFormatException ex) { output.Write($" /* {ex.Message} */"); } output.Write(' '); output.WriteLine("("); output.Indent(); int index = 0; foreach (var v in signature) { output.WriteLocalReference("[" + index + "]", "loc_" + index, isDefinition: true); output.Write(' '); v(ILNameSyntax.TypeName); if (DebugInfo != null && DebugInfo.TryGetName(method, index, out var name)) { output.Write(" " + DisassemblerHelpers.Escape(name)); } if (index + 1 < signature.Length) { output.Write(','); } output.WriteLine(); index++; } output.Unindent(); output.WriteLine(")"); }
protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodDefinition, ref BlobReader blob) { int offset = blob.Offset; if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) { var sp = sequencePoints[nextSequencePointIndex]; if (sp.Offset <= offset) { output.Write("// sequence point: "); if (sp.Offset != 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.DocumentUrl}"); } nextSequencePointIndex++; } } ILOpCode opCode = ILParser.DecodeOpCode(ref blob); output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true); output.Write(": "); if (opCode.IsDefined()) { WriteOpCode(opCode); switch (opCode.GetOperandType()) { case OperandType.BrTarget: case OperandType.ShortBrTarget: output.Write(' '); int targetOffset = ILParser.DecodeBranchTarget(ref blob, opCode); output.WriteLocalReference($"IL_{targetOffset:x4}", targetOffset); break; case OperandType.Field: case OperandType.Method: case OperandType.Sig: case OperandType.Type: output.Write(' '); int metadataToken = blob.ReadInt32(); EntityHandle?handle = MetadataTokenHelpers.TryAsEntityHandle(metadataToken); try { handle?.WriteTo(module, output, genericContext); } catch (BadImageFormatException) { handle = null; } WriteMetadataToken(handle, metadataToken, spaceBefore: true); break; case OperandType.Tok: output.Write(' '); metadataToken = blob.ReadInt32(); handle = MetadataTokenHelpers.TryAsEntityHandle(metadataToken); switch (handle?.Kind) { case HandleKind.MemberReference: switch (metadata.GetMemberReference((MemberReferenceHandle)handle).GetKind()) { case MemberReferenceKind.Method: output.Write("method "); break; case MemberReferenceKind.Field: output.Write("field "); break; } break; case HandleKind.FieldDefinition: output.Write("field "); break; case HandleKind.MethodDefinition: output.Write("method "); break; } try { handle?.WriteTo(module, output, genericContext); } catch (BadImageFormatException) { handle = null; } WriteMetadataToken(handle, metadataToken, spaceBefore: true); break; case OperandType.ShortI: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadSByte()); break; case OperandType.I: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadInt32()); break; case OperandType.I8: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadInt64()); break; case OperandType.ShortR: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadSingle()); break; case OperandType.R: output.Write(' '); DisassemblerHelpers.WriteOperand(output, blob.ReadDouble()); break; case OperandType.String: metadataToken = blob.ReadInt32(); output.Write(' '); UserStringHandle?userString; string text; try { userString = MetadataTokens.UserStringHandle(metadataToken); text = metadata.GetUserString(userString.Value); } catch (BadImageFormatException) { userString = null; text = null; } if (userString != null) { DisassemblerHelpers.WriteOperand(output, text); } WriteMetadataToken(userString, metadataToken, spaceBefore: true); break; case OperandType.Switch: int[] targets = ILParser.DecodeSwitchTargets(ref blob); output.Write(" ("); for (int i = 0; i < targets.Length; i++) { if (i > 0) { output.Write(", "); } output.WriteLocalReference($"IL_{targets[i]:x4}", targets[i]); } output.Write(")"); break; case OperandType.Variable: output.Write(' '); int index = blob.ReadUInt16(); if (opCode == ILOpCode.Ldloc || opCode == ILOpCode.Ldloca || opCode == ILOpCode.Stloc) { DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index); } else { DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index); } break; case OperandType.ShortVariable: output.Write(' '); index = blob.ReadByte(); if (opCode == ILOpCode.Ldloc_s || opCode == ILOpCode.Ldloca_s || opCode == ILOpCode.Stloc_s) { DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index); } else { DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index); } break; } } else { ushort opCodeValue = (ushort)opCode; if (opCodeValue > 0xFF) { // split 16-bit value into two emitbyte directives output.WriteLine($".emitbyte 0x{(byte)(opCodeValue >> 8):x}"); // add label output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1, isDefinition: true); output.Write(": "); output.Write($".emitbyte 0x{(byte)(opCodeValue & 0xFF):x}"); } else { output.Write($".emitbyte 0x{(byte)opCodeValue:x}"); } } output.WriteLine(); }