private void WriteParameters(Collection <ParameterDefinition> parameters) { for (var i = 0; i < parameters.Count; i++) { var p = parameters[i]; if (p.IsIn) { _o.Write("[in] "); } if (p.IsOut) { _o.Write("[out] "); } if (p.IsOptional) { _o.Write("[opt] "); } p.ParameterType.WriteTo(_o); _o.Write(' '); if (p.HasMarshalInfo) { WriteMarshalInfo(p.MarshalInfo); } _o.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p); if (i < parameters.Count - 1) { _o.Write(','); } _o.WriteLine(); } }
public void DisassembleField(FieldDefinition field) { _o.WriteDefinition(".field ", field); if (field.HasLayoutInfo) { _o.Write("[" + field.Offset + "] "); } WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, _fieldVisibility); const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA; WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), _fieldAttributes); if (field.HasMarshalInfo) { WriteMarshalInfo(field.MarshalInfo); } field.FieldType.WriteTo(_o); _o.Write(' '); _o.Write(DisassemblerHelpers.Escape(field.Name)); if ((field.Attributes & FieldAttributes.HasFieldRVA) == FieldAttributes.HasFieldRVA) { _o.Write(" at I_{0:x8}", field.RVA); } if (field.HasConstant) { _o.Write(" = "); WriteConstant(field.Constant); } _o.WriteLine(); if (field.HasCustomAttributes) { WriteAttributes(field.CustomAttributes); } }
public void WriteAssemblyHeader(AssemblyDefinition asm) { output.Write(".assembly " + DisassemblerHelpers.Escape(asm.Name.Name)); OpenBlock(false); WriteAttributes(asm.CustomAttributes); WriteSecurityDeclarations(asm); if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) { output.Write(".publickey = "); WriteBlob(asm.Name.PublicKey); output.WriteLine(); } if (asm.Name.HashAlgorithm != AssemblyHashAlgorithm.None) { output.Write(".hash algorithm 0x{0:x8}", (int)asm.Name.HashAlgorithm); if (asm.Name.HashAlgorithm == AssemblyHashAlgorithm.SHA1) { output.Write(" // SHA1"); } output.WriteLine(); } Version v = asm.Name.Version; if (v != null) { output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision); } CloseBlock(); }
public void DisassembleProperty(PropertyDefinition property) { _o.WriteDefinition(".property ", property); WriteFlags(property.Attributes, _propertyAttributes); if (property.HasThis) { _o.Write("instance "); } property.PropertyType.WriteTo(_o); _o.Write(' '); _o.Write(DisassemblerHelpers.Escape(property.Name)); _o.Write("("); if (property.HasParameters) { _o.WriteLine(); _o.Indent(); WriteParameters(property.Parameters); _o.Unindent(); } _o.Write(")"); OpenBlock(); WriteAttributes(property.CustomAttributes); WriteNestedMethod(".get", property.GetMethod); WriteNestedMethod(".set", property.SetMethod); foreach (var method in property.OtherMethods) { WriteNestedMethod(".other", method); } CloseBlock(); }
public void Disassemble(MethodBody body) { // start writing IL code var method = body.Method; var codesize = body.ComputeCodeSize(); var maxstacksize = body.ComputeMaxStackSize(); body.ComputeOffsets(); _o.WriteLine("// Code size {0} (0x{0:x})", codesize); _o.WriteLine(".maxstack {0}", maxstacksize); if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.Assembly.EntryPoint == method) { _o.WriteLine(".entrypoint"); } if (method.Body.HasVariables) { _o.Write(".locals "); if (body.InitLocals) { _o.Write("init "); } _o.WriteLine("("); _o.Indent(); foreach (var v in body.Variables) { _o.Write("[" + v.Index + "] "); v.VariableType.WriteTo(_o); if (!string.IsNullOrEmpty(v.Name)) { _o.Write(' '); _o.Write(DisassemblerHelpers.Escape(v.Name)); } if (v.Index + 1 < body.Variables.Count) { _o.Write(','); } _o.WriteLine(); } _o.Unindent(); _o.WriteLine(")"); } _o.WriteLine(); if (body.Instructions.Count > 0) { var inst = body.Instructions[0]; var branchTargets = GetBranchTargets(body.Instructions); WriteStructureBody(new IlStructure(body, codesize), branchTargets, ref inst); } else { // we ignore method without instructions (but it can have exception handlers) _o.WriteLine(); } }
void DisassembleMethodInternal(MethodDefinition method) { // .method public hidebysig specialname // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed // //emit flags WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility); WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags); output.WriteLine(); output.Indent(); if (method.HasThis) output.Write("instance "); //call convention WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention); //return type method.ReturnType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(method.Name)); //( params ) output.Write(" ("); if (method.HasParameters) { output.WriteLine(); output.Indent(); WriteParameters(method.Parameters); output.Unindent(); } output.Write(") "); //cil managed WriteEnum(method.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType); if ((method.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed) output.Write("managed "); else output.Write("unmanaged "); WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl); output.Unindent(); if (method.HasBody || method.HasCustomAttributes) { OpenBlock(defaultCollapsed: isInType); WriteAttributes(method.CustomAttributes); if (method.HasBody) methodBodyDisassembler.Disassemble(method.Body); CloseBlock("End of method " + method.DeclaringType.Name + "." + method.Name); } else { output.WriteLine(); } }
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(")"); }
public void Disassemble(MethodBody body) { MethodDefinition method = body.Method; output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize); output.WriteLine(".maxstack {0}", body.MaxStackSize); if (method.DeclaringType.Module.Assembly.EntryPoint == method) { output.WriteLine(".entrypoint"); } if (method.Body.HasVariables) { output.Write(".locals "); if (method.Body.InitLocals) { output.Write("init "); } output.WriteLine("("); output.Indent(); foreach (var v in method.Body.Variables) { output.WriteDefinition("[" + v.Index + "] ", v); v.VariableType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(v.Name)); output.WriteLine(); } output.Unindent(); output.WriteLine(")"); } output.WriteLine(); if (detectControlStructure && body.Instructions.Count > 0) { Instruction inst = body.Instructions[0]; WriteStructureBody(new ILStructure(body), ref inst); } else { foreach (var inst in method.Body.Instructions) { inst.WriteTo(output); output.WriteLine(); } output.WriteLine(); foreach (var eh in method.Body.ExceptionHandlers) { eh.WriteTo(output); output.WriteLine(); } } }
void WriteParameters(Collection<ParameterDefinition> parameters) { for (int i = 0; i < parameters.Count; i++) { var p = parameters[i]; p.ParameterType.WriteTo(output); output.Write(' '); output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p); if (i < parameters.Count - 1) output.Write(','); output.WriteLine(); } }
private static void WriteTypeParameters(PlainTextOutput output, IGenericParameterProvider p) { if (!p.HasGenericParameters) { return; } output.Write('<'); for (var i = 0; i < p.GenericParameters.Count; i++) { if (i > 0) { output.Write(", "); } var gp = p.GenericParameters[i]; if (gp.HasReferenceTypeConstraint) { output.Write("class "); } else if (gp.HasNotNullableValueTypeConstraint) { output.Write("valuetype "); } if (gp.HasDefaultConstructorConstraint) { output.Write(".ctor "); } if (gp.HasConstraints) { output.Write('('); for (var j = 0; j < gp.Constraints.Count; j++) { if (j > 0) { output.Write(", "); } gp.Constraints[j].WriteTo(output, IlNameSyntax.TypeName); } output.Write(") "); } if (gp.IsContravariant) { output.Write('-'); } else if (gp.IsCovariant) { output.Write('+'); } output.Write(DisassemblerHelpers.Escape(gp.Name)); } output.Write('>'); }
public void DisassembleProperty(PropertyDefinition property) { output.WriteDefinition(".property ", property); WriteFlags(property.Attributes, propertyAttributes); property.PropertyType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(property.Name)); OpenBlock(false); WriteAttributes(property.CustomAttributes); WriteNestedMethod(".get", property.GetMethod); WriteNestedMethod(".set", property.SetMethod); foreach (var method in property.OtherMethods) { WriteNestedMethod(".method", method); } CloseBlock(); }
public void DisassembleEvent(EventDefinition ev) { output.WriteDefinition(".event ", ev); WriteFlags(ev.Attributes, eventAttributes); ev.EventType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(ev.Name)); OpenBlock(false); WriteAttributes(ev.CustomAttributes); WriteNestedMethod(".add", ev.AddMethod); WriteNestedMethod(".remove", ev.RemoveMethod); WriteNestedMethod(".invoke", ev.InvokeMethod); foreach (var method in ev.OtherMethods) { WriteNestedMethod(".method", method); } CloseBlock(); }
public void DisassembleNamespace(string nameSpace, IEnumerable<TypeDefinition> types) { if (!string.IsNullOrEmpty(nameSpace)) { output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace)); OpenBlock(false); } bool oldIsInType = isInType; isInType = true; foreach (TypeDefinition td in types) { cancellationToken.ThrowIfCancellationRequested(); DisassembleType(td); output.WriteLine(); } if (!string.IsNullOrEmpty(nameSpace)) { CloseBlock(); isInType = oldIsInType; } }
public void DisassembleEvent(EventDefinition ev) { _o.WriteDefinition(".event ", ev); WriteFlags(ev.Attributes, _eventAttributes); ev.EventType.WriteTo(_o, IlNameSyntax.TypeName); _o.Write(' '); _o.Write(DisassemblerHelpers.Escape(ev.Name)); OpenBlock(); WriteAttributes(ev.CustomAttributes); WriteNestedMethod(".addon", ev.AddMethod); WriteNestedMethod(".removeon", ev.RemoveMethod); WriteNestedMethod(".fire", ev.InvokeMethod); foreach (var method in ev.OtherMethods) { WriteNestedMethod(".other", method); } CloseBlock(); }
void WriteTypeParameter(GenericParameterHandle paramRef, int index, ILNameSyntax syntax) { if (paramRef.IsNil || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) { output.Write(index.ToString()); } else { var param = metadata.GetGenericParameter(paramRef); if (param.Name.IsNil) { output.Write(param.Index.ToString()); } else { output.Write(DisassemblerHelpers.Escape(metadata.GetString(param.Name))); } } }
public void DisassembleField(FieldDefinition field) { output.WriteDefinition(".field ", field); WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility); WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | FieldAttributes.HasDefault), fieldAttributes); field.FieldType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(field.Name)); if (field.HasConstant) { output.Write(" = "); DisassemblerHelpers.WriteOperand(output, field.Constant); } if (field.HasCustomAttributes) { OpenBlock(false); WriteAttributes(field.CustomAttributes); CloseBlock(); } else { output.WriteLine(); } }
private void WriteSecurityDeclarationArgument(CustomAttributeNamedArgument na) { var type = na.Argument.Type; if (type.MetadataType == MetadataType.Class || type.MetadataType == MetadataType.ValueType) { _o.Write("enum "); if (type.Scope != type.Module) { _o.Write("class "); _o.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(type))); } else { type.WriteTo(_o, IlNameSyntax.TypeName); } } else { type.WriteTo(_o); } _o.Write(' '); _o.Write(DisassemblerHelpers.Escape(na.Name)); _o.Write(" = "); var s = na.Argument.Value as string; if (s != null) { // secdecls use special syntax for strings _o.Write("string('{0}')", DisassemblerHelpers.ConvertString(s).Replace("'", "\'")); } else { WriteConstant(na.Argument.Value); } }
public void WriteAssemblyReferences(ModuleDefinition module) { foreach (var mref in module.ModuleReferences) { output.WriteLine(".module extern {0}", DisassemblerHelpers.Escape(mref.Name)); } foreach (var aref in module.AssemblyReferences) { output.Write(".assembly extern {0}", DisassemblerHelpers.Escape(aref.Name)); OpenBlock(false); if (aref.PublicKeyToken != null) { output.Write(".publickeytoken = "); WriteBlob(aref.PublicKeyToken); output.WriteLine(); } if (aref.Version != null) { output.WriteLine(".ver {0}:{1}:{2}:{3}", aref.Version.Major, aref.Version.Minor, aref.Version.Build, aref.Version.Revision); } CloseBlock(); } }
public void DisassembleType(TypeDefinition type) { // create IL code mappings - used for debugger if (this.CodeMappings == null) { this.CodeMappings = new Tuple <string, List <MemberMapping> >(type.FullName, new List <MemberMapping>()); } // start writing IL output.WriteDefinition(".class ", type); if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface) { output.Write("interface "); } WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, typeVisibility); WriteEnum(type.Attributes & TypeAttributes.LayoutMask, typeLayout); WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, typeStringFormat); const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask; WriteFlags(type.Attributes & ~masks, typeAttributes); output.Write(DisassemblerHelpers.Escape(type.Name)); WriteTypeParameters(output, type); output.MarkFoldStart(defaultCollapsed: isInType); output.WriteLine(); if (type.BaseType != null) { output.Indent(); output.Write("extends "); type.BaseType.WriteTo(output, true); output.WriteLine(); output.Unindent(); } if (type.HasInterfaces) { output.Indent(); for (int index = 0; index < type.Interfaces.Count; index++) { if (index > 0) { output.WriteLine(","); } if (index == 0) { output.Write("implements "); } else { output.Write(" "); } if (type.Interfaces[index].Namespace != null) { output.Write("{0}.", type.Interfaces[index].Namespace); } output.Write(type.Interfaces[index].Name); } output.WriteLine(); output.Unindent(); } output.WriteLine("{"); output.Indent(); bool oldIsInType = isInType; isInType = true; WriteAttributes(type.CustomAttributes); if (type.HasLayoutInfo) { output.WriteLine(".pack {0}", type.PackingSize); output.WriteLine(".size {0}", type.ClassSize); output.WriteLine(); } if (type.HasNestedTypes) { output.WriteLine("// Nested Types"); foreach (var nestedType in type.NestedTypes) { cancellationToken.ThrowIfCancellationRequested(); DisassembleType(nestedType); output.WriteLine(); } output.WriteLine(); } if (type.HasFields) { output.WriteLine("// Fields"); foreach (var field in type.Fields) { cancellationToken.ThrowIfCancellationRequested(); DisassembleField(field); } output.WriteLine(); } if (type.HasProperties) { output.WriteLine("// Properties"); foreach (var prop in type.Properties) { cancellationToken.ThrowIfCancellationRequested(); DisassembleProperty(prop); } output.WriteLine(); } if (type.HasEvents) { output.WriteLine("// Events"); foreach (var ev in type.Events) { cancellationToken.ThrowIfCancellationRequested(); DisassembleEvent(ev); output.WriteLine(); } output.WriteLine(); } if (type.HasMethods) { output.WriteLine("// Methods"); var accessorMethods = type.GetAccessorMethods(); foreach (var m in type.Methods) { cancellationToken.ThrowIfCancellationRequested(); if (!(detectControlStructure && accessorMethods.Contains(m))) { DisassembleMethod(m); output.WriteLine(); } } } CloseBlock("End of class " + type.FullName); isInType = oldIsInType; }
public void Disassemble(MethodDef method, MemberMapping debugSymbols) { // start writing IL code CilBody body = method.Body; uint codeSize = (uint)body.GetCodeSize(); output.WriteLine(string.Format("// RVA 0x{0:x8} - 0x{1:x8} ({2} (0x{2:x}) bytes)", (uint)method.RVA, (uint)method.RVA + codeSize, codeSize), TextTokenType.Comment); output.WriteLine(string.Format("// Metadata token 0x{0:x8} (RID {1})", method.MDToken.ToInt32(), method.Rid), TextTokenType.Comment); if (body.LocalVarSigTok != 0) { output.WriteLine(string.Format("// LocalVarSig token 0x{0:x8} (RID {1})", body.LocalVarSigTok, body.LocalVarSigTok & 0xFFFFFF), TextTokenType.Comment); } output.Write(".maxstack", TextTokenType.ILDirective); output.WriteSpace(); output.WriteLine(string.Format("{0}", body.MaxStack), TextTokenType.Number); if (method.DeclaringType.Module.EntryPoint == method) { output.WriteLine(".entrypoint", TextTokenType.ILDirective); } if (method.Body.HasVariables) { output.Write(".locals", TextTokenType.ILDirective); output.WriteSpace(); if (method.Body.InitLocals) { output.Write("init", TextTokenType.Keyword); output.WriteSpace(); } output.WriteLine("(", TextTokenType.Operator); output.Indent(); foreach (var v in method.Body.Variables) { output.Write('[', TextTokenType.Operator); output.WriteDefinition(v.Index.ToString(), v, TextTokenType.Number); output.Write(']', TextTokenType.Operator); output.WriteSpace(); v.Type.WriteTo(output); if (!string.IsNullOrEmpty(v.Name)) { output.WriteSpace(); output.Write(DisassemblerHelpers.Escape(v.Name), TextTokenType.Local); } if (v.Index + 1 < method.Body.Variables.Count) { output.Write(',', TextTokenType.Operator); } output.WriteLine(); } output.Unindent(); output.WriteLine(")", TextTokenType.Operator); } output.WriteLine(); if (detectControlStructure && body.Instructions.Count > 0) { int index = 0; HashSet <uint> branchTargets = GetBranchTargets(body.Instructions); WriteStructureBody(body, new ILStructure(body), branchTargets, ref index, debugSymbols, method.Body.GetCodeSize()); } else { var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var inst = instructions[i]; var startLocation = output.Location; inst.WriteTo(output, options.GetOpCodeDocumentation); if (debugSymbols != null) { // add IL code mappings - used in debugger var next = i + 1 < instructions.Count ? instructions[i + 1] : null; debugSymbols.MemberCodeMappings.Add( new SourceCodeMapping() { StartLocation = output.Location, EndLocation = output.Location, ILInstructionOffset = new ILRange(inst.Offset, next == null ? (uint)method.Body.GetCodeSize() : next.Offset), MemberMapping = debugSymbols }); } output.WriteLine(); } if (method.Body.HasExceptionHandlers) { output.WriteLine(); foreach (var eh in method.Body.ExceptionHandlers) { eh.WriteTo(output); output.WriteLine(); } } } }
public void Disassemble(MethodBody body, MethodDebugSymbols debugSymbols) { // start writing IL code MethodDefinition method = body.Method; output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize); output.WriteLine(".maxstack {0}", body.MaxStackSize); if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.Assembly.EntryPoint == method) { output.WriteLine(".entrypoint"); } if (method.Body.HasVariables) { output.Write(".locals "); if (method.Body.InitLocals) { output.Write("init "); } output.WriteLine("("); output.Indent(); foreach (var v in method.Body.Variables) { output.WriteDefinition("[" + v.Index + "] ", v); v.VariableType.WriteTo(output); string name; if (body.Method.DebugInformation.TryGetName(v, out name)) { output.Write(' '); output.Write(DisassemblerHelpers.Escape(name)); } if (v.Index + 1 < method.Body.Variables.Count) { output.Write(','); } output.WriteLine(); } output.Unindent(); output.WriteLine(")"); } output.WriteLine(); if (detectControlStructure && body.Instructions.Count > 0) { Instruction inst = body.Instructions[0]; HashSet <int> branchTargets = GetBranchTargets(body.Instructions); WriteStructureBody(new ILStructure(body), branchTargets, ref inst, debugSymbols, method.Body.CodeSize); } else { foreach (var inst in method.Body.Instructions) { var startLocation = output.Location; inst.WriteTo(output); if (debugSymbols != null) { // add IL code mappings - used in debugger debugSymbols.SequencePoints.Add( new SequencePoint() { StartLocation = output.Location, EndLocation = output.Location, ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? method.Body.CodeSize : inst.Next.Offset) } }); } output.WriteLine(); } if (method.Body.HasExceptionHandlers) { output.WriteLine(); foreach (var eh in method.Body.ExceptionHandlers) { eh.WriteTo(output); output.WriteLine(); } } } }
public void Disassemble(MethodDef method, CilBody body, MemberMapping methodMapping) { // start writing IL code output.WriteLineComment("// Method Token is 0x{0:x8}", method.MDToken.Raw); output.WriteLineComment("// Method begins at RVA 0x{0:x}", method.RVA); output.WriteLineComment("// Code size {0} (0x{0:x})", body.GetCodeSize()); output.WriteKeyword(".maxstack "); output.WriteLiteral(body.MaxStack.ToString()); output.WriteLine(); if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.EntryPoint == method) { output.WriteKeyword(".entrypoint"); output.WriteLine(); } if (method.Body.HasVariables) { output.WriteKeyword(".locals "); if (method.Body.InitLocals) { output.WriteKeyword("init "); } output.WriteLine("("); output.Indent(); foreach (var v in method.Body.Variables) { output.WriteDefinition("[" + v.Index + "]", v, true); output.Write(" "); v.Type.WriteTo(output); if (!string.IsNullOrEmpty(v.Name)) { output.Write(' '); output.Write(DisassemblerHelpers.Escape(v.Name)); } if (v.Index + 1 < method.Body.Variables.Count) { output.Write(','); } output.WriteLine(); } output.Unindent(); output.WriteLine(")"); } output.WriteLine(); if (detectControlStructure && body.Instructions.Count > 0) { Instruction inst = body.Instructions[0]; var branchTargets = GetBranchTargets(body.Instructions); WriteStructureBody(method, body, new ILStructure(body), branchTargets, ref inst, methodMapping, method.Body.GetCodeSize()); } else { foreach (var inst in method.Body.Instructions) { var startLocation = output.Location; inst.WriteTo(method, body, output); if (methodMapping != null) { var next = inst.GetNext(body); // add IL code mappings - used in debugger methodMapping.MemberCodeMappings.Add( new SourceCodeMapping() { StartLocation = output.Location, EndLocation = output.Location, ILInstructionOffset = new ILRange { From = inst.Offset, To = next == null ? method.Body.GetCodeSize() : next.Offset }, MemberMapping = methodMapping }); } output.WriteLine(); } if (method.Body.HasExceptionHandlers) { output.WriteLine(); foreach (var eh in method.Body.ExceptionHandlers) { eh.WriteTo(output); output.WriteLine(); } } } }
public void DisassembleType(TypeDefinition type) { output.WriteDefinition(".class ", type); if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface) output.Write("interface "); WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, typeVisibility); WriteEnum(type.Attributes & TypeAttributes.LayoutMask, typeLayout); WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, typeStringFormat); const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask; WriteFlags(type.Attributes & ~masks, typeAttributes); output.Write(DisassemblerHelpers.Escape(type.Name)); output.MarkFoldStart(defaultCollapsed: isInType); output.WriteLine(); if (type.BaseType != null) { output.Indent(); output.Write("extends "); type.BaseType.WriteTo(output, true); output.WriteLine(); output.Unindent(); } output.WriteLine("{"); output.Indent(); bool oldIsInType = isInType; isInType = true; WriteAttributes(type.CustomAttributes); if (type.HasLayoutInfo) { output.WriteLine(".pack {0}", type.PackingSize); output.WriteLine(".size {0}", type.ClassSize); output.WriteLine(); } if (type.HasNestedTypes) { output.WriteLine("// Nested Types"); foreach (var nestedType in type.NestedTypes) { cancellationToken.ThrowIfCancellationRequested(); DisassembleType(nestedType); output.WriteLine(); } output.WriteLine(); } if (type.HasFields) { output.WriteLine("// Fields"); foreach (var field in type.Fields) { cancellationToken.ThrowIfCancellationRequested(); DisassembleField(field); } output.WriteLine(); } if (type.HasProperties) { output.WriteLine("// Properties"); foreach (var prop in type.Properties) { cancellationToken.ThrowIfCancellationRequested(); DisassembleProperty(prop); } output.WriteLine(); } if (type.HasEvents) { output.WriteLine("// Events"); foreach (var ev in type.Events) { cancellationToken.ThrowIfCancellationRequested(); DisassembleEvent(ev); output.WriteLine(); } output.WriteLine(); } if (type.HasMethods) { output.WriteLine("// Methods"); var accessorMethods = type.GetAccessorMethods(); foreach (var m in type.Methods) { cancellationToken.ThrowIfCancellationRequested(); if (!(detectControlStructure && accessorMethods.Contains(m))) { DisassembleMethod(m); output.WriteLine(); } } } CloseBlock("End of class " + type.FullName); isInType = oldIsInType; }
void WriteSecurityDeclarations(ISecurityDeclarationProvider secDeclProvider) { if (!secDeclProvider.HasSecurityDeclarations) { return; } foreach (var secdecl in secDeclProvider.SecurityDeclarations) { output.Write(".permissionset "); switch (secdecl.Action) { case SecurityAction.Request: output.Write("request"); break; case SecurityAction.Demand: output.Write("demand"); break; case SecurityAction.Assert: output.Write("assert"); break; case SecurityAction.Deny: output.Write("deny"); break; case SecurityAction.PermitOnly: output.Write("permitonly"); break; case SecurityAction.LinkDemand: output.Write("linkcheck"); break; case SecurityAction.InheritDemand: output.Write("inheritcheck"); break; case SecurityAction.RequestMinimum: output.Write("reqmin"); break; case SecurityAction.RequestOptional: output.Write("reqopt"); break; case SecurityAction.RequestRefuse: output.Write("reqrefuse"); break; case SecurityAction.PreJitGrant: output.Write("prejitgrant"); break; case SecurityAction.PreJitDeny: output.Write("prejitdeny"); break; case SecurityAction.NonCasDemand: output.Write("noncasdemand"); break; case SecurityAction.NonCasLinkDemand: output.Write("noncaslinkdemand"); break; case SecurityAction.NonCasInheritance: output.Write("noncasinheritance"); break; default: output.Write(secdecl.Action.ToString()); break; } output.WriteLine(" = {"); output.Indent(); for (int i = 0; i < secdecl.SecurityAttributes.Count; i++) { SecurityAttribute sa = secdecl.SecurityAttributes[i]; if (sa.AttributeType.Scope == sa.AttributeType.Module) { output.Write("class "); output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(sa.AttributeType))); } else { sa.AttributeType.WriteTo(output, ILNameSyntax.TypeName); } output.Write(" = {"); if (sa.HasFields || sa.HasProperties) { output.WriteLine(); output.Indent(); foreach (CustomAttributeNamedArgument na in sa.Fields) { output.Write("field "); WriteSecurityDeclarationArgument(na); output.WriteLine(); } foreach (CustomAttributeNamedArgument na in sa.Properties) { output.Write("property "); WriteSecurityDeclarationArgument(na); output.WriteLine(); } output.Unindent(); } output.Write('}'); if (i + 1 < secdecl.SecurityAttributes.Count) { output.Write(','); } output.WriteLine(); } output.Unindent(); output.WriteLine("}"); } }
private void DisassembleMethodInternal(MethodDefinition method) { // .method public hidebysig specialname // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed // //emit flags WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, _methodVisibility); WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, _methodAttributeFlags); if (method.IsCompilerControlled) { _o.Write("privatescope "); } if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) { _o.Write("pinvokeimpl"); if (method.HasPInvokeInfo && method.PInvokeInfo != null) { var info = method.PInvokeInfo; _o.Write("(\"" + DisassemblerHelpers.ConvertString(info.Module.Name) + "\""); if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name) { _o.Write(" as \"" + DisassemblerHelpers.ConvertString(info.EntryPoint) + "\""); } if (info.IsNoMangle) { _o.Write(" nomangle"); } if (info.IsCharSetAnsi) { _o.Write(" ansi"); } else if (info.IsCharSetAuto) { _o.Write(" autochar"); } else if (info.IsCharSetUnicode) { _o.Write(" unicode"); } if (info.SupportsLastError) { _o.Write(" lasterr"); } if (info.IsCallConvCdecl) { _o.Write(" cdecl"); } else if (info.IsCallConvFastcall) { _o.Write(" fastcall"); } else if (info.IsCallConvStdCall) { _o.Write(" stdcall"); } else if (info.IsCallConvThiscall) { _o.Write(" thiscall"); } else if (info.IsCallConvWinapi) { _o.Write(" winapi"); } _o.Write(')'); } _o.Write(' '); } _o.WriteLine(); _o.Indent(); if (method.ExplicitThis) { _o.Write("instance explicit "); } else if (method.HasThis) { _o.Write("instance "); } //call convention // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, _callingConvention); //return type method.ReturnType.WriteTo(_o); _o.Write(' '); if (method.MethodReturnType.HasMarshalInfo) { WriteMarshalInfo(method.MethodReturnType.MarshalInfo); } _o.Write(method.IsCompilerControlled ? DisassemblerHelpers.Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")) : DisassemblerHelpers.Escape(method.Name)); WriteTypeParameters(_o, method); //( params ) _o.Write(" ("); if (method.HasParameters) { _o.WriteLine(); _o.Indent(); WriteParameters(method.Parameters); _o.Unindent(); } _o.Write(") "); //cil managed WriteEnum(method.ImplAttributes & MethodImplAttributes.CodeTypeMask, _methodCodeType); _o.Write((method.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed ? "managed " : "unmanaged "); WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), _methodImpl); _o.Unindent(); OpenBlock(); WriteAttributes(method.CustomAttributes); if (method.HasOverrides) { foreach (var methodOverride in method.Overrides) { _o.Write(".override method "); methodOverride.WriteTo(_o); _o.WriteLine(); } } WriteParameterAttributes(0, method.MethodReturnType, method.MethodReturnType); foreach (var p in method.Parameters) { WriteParameterAttributes(p.Index + 1, p, p); } WriteSecurityDeclarations(method); if (method.HasBody) { new MethodBodyDisassembler(_o) .Disassemble(method.Body); } CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name)); }
void DisassembleMethodInternal(MethodDefinition method) { // .method public hidebysig specialname // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed // //emit flags WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility); WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags); if (method.IsCompilerControlled) { output.Write("privatescope "); } if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) { output.Write("pinvokeimpl"); if (method.HasPInvokeInfo && method.PInvokeInfo != null) { PInvokeInfo info = method.PInvokeInfo; output.Write("(\"" + NRefactory.CSharp.CSharpOutputVisitor.ConvertString(info.Module.Name) + "\""); if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name) { output.Write(" as \"" + NRefactory.CSharp.CSharpOutputVisitor.ConvertString(info.EntryPoint) + "\""); } if (info.IsNoMangle) { output.Write(" nomangle"); } if (info.IsCharSetAnsi) { output.Write(" ansi"); } else if (info.IsCharSetAuto) { output.Write(" autochar"); } else if (info.IsCharSetUnicode) { output.Write(" unicode"); } if (info.SupportsLastError) { output.Write(" lasterr"); } if (info.IsCallConvCdecl) { output.Write(" cdecl"); } else if (info.IsCallConvFastcall) { output.Write(" fastcall"); } else if (info.IsCallConvStdCall) { output.Write(" stdcall"); } else if (info.IsCallConvThiscall) { output.Write(" thiscall"); } else if (info.IsCallConvWinapi) { output.Write(" winapi"); } output.Write(')'); } output.Write(' '); } output.WriteLine(); output.Indent(); if (method.ExplicitThis) { output.Write("instance explicit "); } else if (method.HasThis) { output.Write("instance "); } //call convention WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention); //return type method.ReturnType.WriteTo(output); output.Write(' '); if (method.MethodReturnType.HasMarshalInfo) { WriteMarshalInfo(method.MethodReturnType.MarshalInfo); } if (method.IsCompilerControlled) { output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8"))); } else { output.Write(DisassemblerHelpers.Escape(method.Name)); } WriteTypeParameters(output, method); //( params ) output.Write(" ("); if (method.HasParameters) { output.WriteLine(); output.Indent(); WriteParameters(method.Parameters); output.Unindent(); } output.Write(") "); //cil managed WriteEnum(method.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType); if ((method.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed) { output.Write("managed "); } else { output.Write("unmanaged "); } WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl); output.Unindent(); OpenBlock(defaultCollapsed: isInType); WriteAttributes(method.CustomAttributes); if (method.HasOverrides) { foreach (var methodOverride in method.Overrides) { output.Write(".override method "); methodOverride.WriteTo(output); output.WriteLine(); } } foreach (var p in method.Parameters) { WriteParameterAttributes(p); } WriteSecurityDeclarations(method); if (method.HasBody) { // create IL code mappings - used in debugger MemberMapping methodMapping = new MemberMapping(method); methodBodyDisassembler.Disassemble(method.Body, methodMapping); output.AddDebuggerMemberMapping(methodMapping); } CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name)); }
public void DisassembleType(TypeDefinition type) { // start writing IL output.WriteDefinition(".class ", type); if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface) { output.Write("interface "); } WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, typeVisibility); WriteEnum(type.Attributes & TypeAttributes.LayoutMask, typeLayout); WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, typeStringFormat); const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask; WriteFlags(type.Attributes & ~masks, typeAttributes); output.Write(DisassemblerHelpers.Escape(type.DeclaringType != null ? type.Name : type.FullName)); WriteTypeParameters(output, type); output.MarkFoldStart(defaultCollapsed: isInType); output.WriteLine(); if (type.BaseType != null) { output.Indent(); output.Write("extends "); type.BaseType.WriteTo(output, ILNameSyntax.TypeName); output.WriteLine(); output.Unindent(); } if (type.HasInterfaces) { output.Indent(); for (int index = 0; index < type.Interfaces.Count; index++) { if (index > 0) { output.WriteLine(","); } if (index == 0) { output.Write("implements "); } else { output.Write(" "); } type.Interfaces[index].WriteTo(output, ILNameSyntax.TypeName); } output.WriteLine(); output.Unindent(); } output.WriteLine("{"); output.Indent(); bool oldIsInType = isInType; isInType = true; WriteAttributes(type.CustomAttributes); WriteSecurityDeclarations(type); if (type.HasLayoutInfo) { output.WriteLine(".pack {0}", type.PackingSize); output.WriteLine(".size {0}", type.ClassSize); output.WriteLine(); } if (type.HasNestedTypes) { output.WriteLine("// Nested Types"); foreach (var nestedType in type.NestedTypes) { cancellationToken.ThrowIfCancellationRequested(); DisassembleType(nestedType); output.WriteLine(); } output.WriteLine(); } if (type.HasFields) { output.WriteLine("// Fields"); foreach (var field in type.Fields) { cancellationToken.ThrowIfCancellationRequested(); DisassembleField(field); } output.WriteLine(); } if (type.HasMethods) { output.WriteLine("// Methods"); foreach (var m in type.Methods) { cancellationToken.ThrowIfCancellationRequested(); DisassembleMethod(m); output.WriteLine(); } } if (type.HasEvents) { output.WriteLine("// Events"); foreach (var ev in type.Events) { cancellationToken.ThrowIfCancellationRequested(); DisassembleEvent(ev); output.WriteLine(); } output.WriteLine(); } if (type.HasProperties) { output.WriteLine("// Properties"); foreach (var prop in type.Properties) { cancellationToken.ThrowIfCancellationRequested(); DisassembleProperty(prop); } output.WriteLine(); } CloseBlock("end of class " + (type.DeclaringType != null ? type.Name : type.FullName)); isInType = oldIsInType; }
public void Disassemble(MethodDef method, MemberMapping debugSymbols) { // start writing IL code CilBody body = method.Body; uint codeSize = (uint)body.GetCodeSize(); uint rva = (uint)method.RVA; long offset = method.Module.ToFileOffset(rva); if (options.ShowTokenAndRvaComments) { output.WriteLine(string.Format("// Header Size: {0} {1}", method.Body.HeaderSize, method.Body.HeaderSize == 1 ? "byte" : "bytes"), TextTokenType.Comment); output.WriteLine(string.Format("// Code Size: {0} (0x{0:X}) {1}", codeSize, codeSize == 1 ? "byte" : "bytes"), TextTokenType.Comment); if (body.LocalVarSigTok != 0) { output.WriteLine(string.Format("// LocalVarSig Token: 0x{0:X8} RID: {1}", body.LocalVarSigTok, body.LocalVarSigTok & 0xFFFFFF), TextTokenType.Comment); } } output.Write(".maxstack", TextTokenType.ILDirective); output.WriteSpace(); output.WriteLine(string.Format("{0}", body.MaxStack), TextTokenType.Number); if (method.DeclaringType.Module.EntryPoint == method) { output.WriteLine(".entrypoint", TextTokenType.ILDirective); } if (method.Body.HasVariables) { output.Write(".locals", TextTokenType.ILDirective); output.WriteSpace(); if (method.Body.InitLocals) { output.Write("init", TextTokenType.Keyword); output.WriteSpace(); } output.WriteLine("(", TextTokenType.Operator); output.Indent(); foreach (var v in method.Body.Variables) { output.Write('[', TextTokenType.Operator); output.WriteDefinition(v.Index.ToString(), v, TextTokenType.Number); output.Write(']', TextTokenType.Operator); output.WriteSpace(); v.Type.WriteTo(output); if (!string.IsNullOrEmpty(v.Name)) { output.WriteSpace(); output.Write(DisassemblerHelpers.Escape(v.Name), TextTokenType.Local); } if (v.Index + 1 < method.Body.Variables.Count) { output.Write(',', TextTokenType.Operator); } output.WriteLine(); } output.Unindent(); output.WriteLine(")", TextTokenType.Operator); } output.WriteLine(); uint baseRva = rva == 0 ? 0 : rva + method.Body.HeaderSize; long baseOffs = baseRva == 0 ? 0 : method.Module.ToFileOffset(baseRva); using (var byteReader = !options.ShowILBytes || options.CreateInstructionBytesReader == null ? null : options.CreateInstructionBytesReader(method)) { if (detectControlStructure && body.Instructions.Count > 0) { int index = 0; HashSet <uint> branchTargets = GetBranchTargets(body.Instructions); WriteStructureBody(body, new ILStructure(body), branchTargets, ref index, debugSymbols, method.Body.GetCodeSize(), baseRva, baseOffs, byteReader, method); } else { var instructions = method.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { var inst = instructions[i]; var startLocation = output.Location; inst.WriteTo(output, options, baseRva, baseOffs, byteReader, method); if (debugSymbols != null) { // add IL code mappings - used in debugger var next = i + 1 < instructions.Count ? instructions[i + 1] : null; debugSymbols.MemberCodeMappings.Add( new SourceCodeMapping() { StartLocation = output.Location, EndLocation = output.Location, ILInstructionOffset = new ILRange(inst.Offset, next == null ? (uint)method.Body.GetCodeSize() : next.Offset), MemberMapping = debugSymbols }); } output.WriteLine(); } if (method.Body.HasExceptionHandlers) { output.WriteLine(); foreach (var eh in method.Body.ExceptionHandlers) { eh.WriteTo(output, method); output.WriteLine(); } } } } }
public void Disassemble(MethodBody body, MemberMapping methodMapping) { // start writing IL code MethodDefinition method = body.Method; output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize); output.WriteLine(".maxstack {0}", body.MaxStackSize); if (method.DeclaringType.Module.Assembly.EntryPoint == method) { output.WriteLine(".entrypoint"); } if (method.Body.HasVariables) { output.Write(".locals "); if (method.Body.InitLocals) { output.Write("init "); } output.WriteLine("("); output.Indent(); foreach (var v in method.Body.Variables) { output.WriteDefinition("[" + v.Index + "] ", v); v.VariableType.WriteTo(output); if (!string.IsNullOrEmpty(v.Name)) { output.Write(' '); output.Write(DisassemblerHelpers.Escape(v.Name)); } if (v.Index + 1 < method.Body.Variables.Count) { output.Write(','); } output.WriteLine(); } output.Unindent(); output.WriteLine(")"); } output.WriteLine(); if (detectControlStructure && body.Instructions.Count > 0) { Instruction inst = body.Instructions[0]; HashSet <int> branchTargets = GetBranchTargets(body.Instructions); WriteStructureBody(new ILStructure(body), branchTargets, ref inst, methodMapping, method.Body.CodeSize); } else { foreach (var inst in method.Body.Instructions) { inst.WriteTo(output); if (methodMapping != null) { // add IL code mappings - used in debugger methodMapping.MemberCodeMappings.Add( new SourceCodeMapping() { SourceCodeLine = output.CurrentLine, ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? method.Body.CodeSize : inst.Next.Offset }, MemberMapping = methodMapping }); } output.WriteLine(); } if (method.Body.HasExceptionHandlers) { output.WriteLine(); foreach (var eh in method.Body.ExceptionHandlers) { eh.WriteTo(output); output.WriteLine(); } } } }
public void DisassembleType(TypeDefinition type) { // start writing IL _o.WriteDefinition(".class ", type); if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface) { _o.Write("interface "); } WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, _typeVisibility); WriteEnum(type.Attributes & TypeAttributes.LayoutMask, _typeLayout); WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, _typeStringFormat); const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask; WriteFlags(type.Attributes & ~masks, _typeAttributes); _o.Write(DisassemblerHelpers.Escape(type.DeclaringType != null ? type.Name : type.FullName)); WriteTypeParameters(_o, type); _o.WriteLine(); if (type.BaseType != null) { _o.Indent(); _o.Write("extends "); type.BaseType.WriteTo(_o, IlNameSyntax.TypeName); _o.WriteLine(); _o.Unindent(); } if (type.HasInterfaces) { _o.Indent(); for (var index = 0; index < type.Interfaces.Count; index++) { if (index > 0) { _o.WriteLine(","); } _o.Write(index == 0 ? "implements " : " "); type.Interfaces[index].WriteTo(_o, IlNameSyntax.TypeName); } _o.WriteLine(); _o.Unindent(); } _o.WriteLine("{"); _o.Indent(); var oldIsInType = _isInType; _isInType = true; WriteAttributes(type.CustomAttributes); WriteSecurityDeclarations(type); if (type.HasLayoutInfo) { _o.WriteLine(".pack {0}", type.PackingSize); _o.WriteLine(".size {0}", type.ClassSize); _o.WriteLine(); } if (type.HasNestedTypes) { _o.WriteLine("// Nested Types"); foreach (var nestedType in type.NestedTypes) { DisassembleType(nestedType); _o.WriteLine(); } _o.WriteLine(); } if (type.HasFields) { _o.WriteLine("// Fields"); foreach (var field in type.Fields) { DisassembleField(field); } _o.WriteLine(); } if (type.HasMethods) { _o.WriteLine("// Methods"); foreach (var m in type.Methods) { // write method header _o.WriteDefinition(".method ", m); DisassembleMethodInternal(m); _o.WriteLine(); } } if (type.HasEvents) { _o.WriteLine("// Events"); foreach (var ev in type.Events) { DisassembleEvent(ev); _o.WriteLine(); } _o.WriteLine(); } if (type.HasProperties) { _o.WriteLine("// Properties"); foreach (var prop in type.Properties) { DisassembleProperty(prop); } _o.WriteLine(); } CloseBlock("end of class " + (type.DeclaringType != null ? type.Name : type.FullName)); _isInType = oldIsInType; }