summaryrefslogtreecommitdiff
path: root/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs')
-rw-r--r--ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs1168
1 files changed, 0 insertions, 1168 deletions
diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
deleted file mode 100644
index 2a374c3a..00000000
--- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
+++ /dev/null
@@ -1,1168 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using ICSharpCode.NRefactory;
-using Mono.Cecil;
-using Mono.Collections.Generic;
-
-namespace ICSharpCode.Decompiler.Disassembler
-{
- /// <summary>
- /// Disassembles type and member definitions.
- /// </summary>
- public sealed class ReflectionDisassembler
- {
- ITextOutput output;
- CancellationToken cancellationToken;
- bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
- MethodBodyDisassembler methodBodyDisassembler;
- MemberReference currentMember;
-
- public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
- {
- if (output == null)
- throw new ArgumentNullException("output");
- this.output = output;
- this.cancellationToken = cancellationToken;
- methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);
- }
-
- #region Disassemble Method
- EnumNameCollection<MethodAttributes> methodAttributeFlags = new EnumNameCollection<MethodAttributes>() {
- { MethodAttributes.Final, "final" },
- { MethodAttributes.HideBySig, "hidebysig" },
- { MethodAttributes.SpecialName, "specialname" },
- { MethodAttributes.PInvokeImpl, null }, // handled separately
- { MethodAttributes.UnmanagedExport, "export" },
- { MethodAttributes.RTSpecialName, "rtspecialname" },
- { MethodAttributes.RequireSecObject, "reqsecobj" },
- { MethodAttributes.NewSlot, "newslot" },
- { MethodAttributes.CheckAccessOnOverride, "strict" },
- { MethodAttributes.Abstract, "abstract" },
- { MethodAttributes.Virtual, "virtual" },
- { MethodAttributes.Static, "static" },
- { MethodAttributes.HasSecurity, null }, // ?? also invisible in ILDasm
- };
-
- EnumNameCollection<MethodAttributes> methodVisibility = new EnumNameCollection<MethodAttributes>() {
- { MethodAttributes.Private, "private" },
- { MethodAttributes.FamANDAssem, "famandassem" },
- { MethodAttributes.Assembly, "assembly" },
- { MethodAttributes.Family, "family" },
- { MethodAttributes.FamORAssem, "famorassem" },
- { MethodAttributes.Public, "public" },
- };
-
- EnumNameCollection<MethodCallingConvention> callingConvention = new EnumNameCollection<MethodCallingConvention>() {
- { MethodCallingConvention.C, "unmanaged cdecl" },
- { MethodCallingConvention.StdCall, "unmanaged stdcall" },
- { MethodCallingConvention.ThisCall, "unmanaged thiscall" },
- { MethodCallingConvention.FastCall, "unmanaged fastcall" },
- { MethodCallingConvention.VarArg, "vararg" },
- { MethodCallingConvention.Generic, null },
- };
-
- EnumNameCollection<MethodImplAttributes> methodCodeType = new EnumNameCollection<MethodImplAttributes>() {
- { MethodImplAttributes.IL, "cil" },
- { MethodImplAttributes.Native, "native" },
- { MethodImplAttributes.OPTIL, "optil" },
- { MethodImplAttributes.Runtime, "runtime" },
- };
-
- EnumNameCollection<MethodImplAttributes> methodImpl = new EnumNameCollection<MethodImplAttributes>() {
- { MethodImplAttributes.Synchronized, "synchronized" },
- { MethodImplAttributes.NoInlining, "noinlining" },
- { MethodImplAttributes.NoOptimization, "nooptimization" },
- { MethodImplAttributes.PreserveSig, "preservesig" },
- { MethodImplAttributes.InternalCall, "internalcall" },
- { MethodImplAttributes.ForwardRef, "forwardref" },
- };
-
- public void DisassembleMethod(MethodDefinition method)
- {
- // set current member
- currentMember = method;
-
- // write method header
- output.WriteDefinition(".method ", method);
- DisassembleMethodInternal(method);
- }
-
- void DisassembleMethodInternal(MethodDefinition method)
- {
- // .method public hidebysig specialname
- // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
- //
-
- TextLocation startLocation = output.Location;
-
- //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.TextWriterTokenWriter.ConvertString(info.Module.Name) + "\"");
-
- if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name)
- output.Write(" as \"" + NRefactory.CSharp.TextWriterTokenWriter.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
- MethodDebugSymbols debugSymbols = new MethodDebugSymbols(method);
- debugSymbols.StartLocation = startLocation;
- methodBodyDisassembler.Disassemble(method.Body, debugSymbols);
- debugSymbols.EndLocation = output.Location;
- output.AddDebugSymbols(debugSymbols);
- }
-
- CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name));
- }
-
- #region Write Security Declarations
- 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("}");
- }
- }
-
- void WriteSecurityDeclarationArgument(CustomAttributeNamedArgument na)
- {
- TypeReference type = na.Argument.Type;
- if (type.MetadataType == MetadataType.Class || type.MetadataType == MetadataType.ValueType) {
- output.Write("enum ");
- if (type.Scope != type.Module) {
- output.Write("class ");
- output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(type)));
- } else {
- type.WriteTo(output, ILNameSyntax.TypeName);
- }
- } else {
- type.WriteTo(output);
- }
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(na.Name));
- output.Write(" = ");
- if (na.Argument.Value is string) {
- // secdecls use special syntax for strings
- output.Write("string('{0}')", NRefactory.CSharp.TextWriterTokenWriter.ConvertString((string)na.Argument.Value).Replace("'", "\'"));
- } else {
- WriteConstant(na.Argument.Value);
- }
- }
-
- string GetAssemblyQualifiedName(TypeReference type)
- {
- AssemblyNameReference anr = type.Scope as AssemblyNameReference;
- if (anr == null) {
- ModuleDefinition md = type.Scope as ModuleDefinition;
- if (md != null) {
- anr = md.Assembly.Name;
- }
- }
- if (anr != null) {
- return type.FullName + ", " + anr.FullName;
- } else {
- return type.FullName;
- }
- }
- #endregion
-
- #region WriteMarshalInfo
- void WriteMarshalInfo(MarshalInfo marshalInfo)
- {
- output.Write("marshal(");
- WriteNativeType(marshalInfo.NativeType, marshalInfo);
- output.Write(") ");
- }
-
- void WriteNativeType(NativeType nativeType, MarshalInfo marshalInfo = null)
- {
- switch (nativeType) {
- case NativeType.None:
- break;
- case NativeType.Boolean:
- output.Write("bool");
- break;
- case NativeType.I1:
- output.Write("int8");
- break;
- case NativeType.U1:
- output.Write("unsigned int8");
- break;
- case NativeType.I2:
- output.Write("int16");
- break;
- case NativeType.U2:
- output.Write("unsigned int16");
- break;
- case NativeType.I4:
- output.Write("int32");
- break;
- case NativeType.U4:
- output.Write("unsigned int32");
- break;
- case NativeType.I8:
- output.Write("int64");
- break;
- case NativeType.U8:
- output.Write("unsigned int64");
- break;
- case NativeType.R4:
- output.Write("float32");
- break;
- case NativeType.R8:
- output.Write("float64");
- break;
- case NativeType.LPStr:
- output.Write("lpstr");
- break;
- case NativeType.Int:
- output.Write("int");
- break;
- case NativeType.UInt:
- output.Write("unsigned int");
- break;
- case NativeType.Func:
- goto default; // ??
- case NativeType.Array:
- ArrayMarshalInfo ami = (ArrayMarshalInfo)marshalInfo;
- if (ami == null)
- goto default;
- if (ami.ElementType != NativeType.Max)
- WriteNativeType(ami.ElementType);
- output.Write('[');
- if (ami.SizeParameterMultiplier == 0) {
- output.Write(ami.Size.ToString());
- } else {
- if (ami.Size >= 0)
- output.Write(ami.Size.ToString());
- output.Write(" + ");
- output.Write(ami.SizeParameterIndex.ToString());
- }
- output.Write(']');
- break;
- case NativeType.Currency:
- output.Write("currency");
- break;
- case NativeType.BStr:
- output.Write("bstr");
- break;
- case NativeType.LPWStr:
- output.Write("lpwstr");
- break;
- case NativeType.LPTStr:
- output.Write("lptstr");
- break;
- case NativeType.FixedSysString:
- output.Write("fixed sysstring[{0}]", ((FixedSysStringMarshalInfo)marshalInfo).Size);
- break;
- case NativeType.IUnknown:
- output.Write("iunknown");
- break;
- case NativeType.IDispatch:
- output.Write("idispatch");
- break;
- case NativeType.Struct:
- output.Write("struct");
- break;
- case NativeType.IntF:
- output.Write("interface");
- break;
- case NativeType.SafeArray:
- output.Write("safearray ");
- SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
- if (sami != null) {
- switch (sami.ElementType) {
- case VariantType.None:
- break;
- case VariantType.I2:
- output.Write("int16");
- break;
- case VariantType.I4:
- output.Write("int32");
- break;
- case VariantType.R4:
- output.Write("float32");
- break;
- case VariantType.R8:
- output.Write("float64");
- break;
- case VariantType.CY:
- output.Write("currency");
- break;
- case VariantType.Date:
- output.Write("date");
- break;
- case VariantType.BStr:
- output.Write("bstr");
- break;
- case VariantType.Dispatch:
- output.Write("idispatch");
- break;
- case VariantType.Error:
- output.Write("error");
- break;
- case VariantType.Bool:
- output.Write("bool");
- break;
- case VariantType.Variant:
- output.Write("variant");
- break;
- case VariantType.Unknown:
- output.Write("iunknown");
- break;
- case VariantType.Decimal:
- output.Write("decimal");
- break;
- case VariantType.I1:
- output.Write("int8");
- break;
- case VariantType.UI1:
- output.Write("unsigned int8");
- break;
- case VariantType.UI2:
- output.Write("unsigned int16");
- break;
- case VariantType.UI4:
- output.Write("unsigned int32");
- break;
- case VariantType.Int:
- output.Write("int");
- break;
- case VariantType.UInt:
- output.Write("unsigned int");
- break;
- default:
- output.Write(sami.ElementType.ToString());
- break;
- }
- }
- break;
- case NativeType.FixedArray:
- output.Write("fixed array");
- FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
- if (fami != null) {
- output.Write("[{0}]", fami.Size);
- if (fami.ElementType != NativeType.None) {
- output.Write(' ');
- WriteNativeType(fami.ElementType);
- }
- }
- break;
- case NativeType.ByValStr:
- output.Write("byvalstr");
- break;
- case NativeType.ANSIBStr:
- output.Write("ansi bstr");
- break;
- case NativeType.TBStr:
- output.Write("tbstr");
- break;
- case NativeType.VariantBool:
- output.Write("variant bool");
- break;
- case NativeType.ASAny:
- output.Write("as any");
- break;
- case NativeType.LPStruct:
- output.Write("lpstruct");
- break;
- case NativeType.CustomMarshaler:
- CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
- if (cmi == null)
- goto default;
- output.Write("custom(\"{0}\", \"{1}\"",
- NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.ManagedType.FullName),
- NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.Cookie));
- if (cmi.Guid != Guid.Empty || !string.IsNullOrEmpty(cmi.UnmanagedType)) {
- output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.UnmanagedType));
- }
- output.Write(')');
- break;
- case NativeType.Error:
- output.Write("error");
- break;
- default:
- output.Write(nativeType.ToString());
- break;
- }
- }
- #endregion
-
- void WriteParameters(Collection<ParameterDefinition> parameters)
- {
- for (int i = 0; i < parameters.Count; i++) {
- var p = parameters[i];
- if (p.IsIn)
- output.Write("[in] ");
- if (p.IsOut)
- output.Write("[out] ");
- if (p.IsOptional)
- output.Write("[opt] ");
- p.ParameterType.WriteTo(output);
- output.Write(' ');
- if (p.HasMarshalInfo) {
- WriteMarshalInfo(p.MarshalInfo);
- }
- output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p);
- if (i < parameters.Count - 1)
- output.Write(',');
- output.WriteLine();
- }
- }
-
- bool HasParameterAttributes(ParameterDefinition p)
- {
- return p.HasConstant || p.HasCustomAttributes;
- }
-
- void WriteParameterAttributes(ParameterDefinition p)
- {
- if (!HasParameterAttributes(p))
- return;
- output.Write(".param [{0}]", p.Index + 1);
- if (p.HasConstant) {
- output.Write(" = ");
- WriteConstant(p.Constant);
- }
- output.WriteLine();
- WriteAttributes(p.CustomAttributes);
- }
-
- void WriteConstant(object constant)
- {
- if (constant == null) {
- output.Write("nullref");
- } else {
- string typeName = DisassemblerHelpers.PrimitiveTypeName(constant.GetType().FullName);
- if (typeName != null && typeName != "string") {
- output.Write(typeName);
- output.Write('(');
- float? cf = constant as float?;
- double? cd = constant as double?;
- if (cf.HasValue && (float.IsNaN(cf.Value) || float.IsInfinity(cf.Value))) {
- output.Write("0x{0:x8}", BitConverter.ToInt32(BitConverter.GetBytes(cf.Value), 0));
- } else if (cd.HasValue && (double.IsNaN(cd.Value) || double.IsInfinity(cd.Value))) {
- output.Write("0x{0:x16}", BitConverter.DoubleToInt64Bits(cd.Value));
- } else {
- DisassemblerHelpers.WriteOperand(output, constant);
- }
- output.Write(')');
- } else {
- DisassemblerHelpers.WriteOperand(output, constant);
- }
- }
- }
- #endregion
-
- #region Disassemble Field
- EnumNameCollection<FieldAttributes> fieldVisibility = new EnumNameCollection<FieldAttributes>() {
- { FieldAttributes.Private, "private" },
- { FieldAttributes.FamANDAssem, "famandassem" },
- { FieldAttributes.Assembly, "assembly" },
- { FieldAttributes.Family, "family" },
- { FieldAttributes.FamORAssem, "famorassem" },
- { FieldAttributes.Public, "public" },
- };
-
- EnumNameCollection<FieldAttributes> fieldAttributes = new EnumNameCollection<FieldAttributes>() {
- { FieldAttributes.Static, "static" },
- { FieldAttributes.Literal, "literal" },
- { FieldAttributes.InitOnly, "initonly" },
- { FieldAttributes.SpecialName, "specialname" },
- { FieldAttributes.RTSpecialName, "rtspecialname" },
- { FieldAttributes.NotSerialized, "notserialized" },
- };
-
- public void DisassembleField(FieldDefinition field)
- {
- output.WriteDefinition(".field ", field);
- if (field.HasLayoutInfo) {
- output.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(output);
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(field.Name));
- if ((field.Attributes & FieldAttributes.HasFieldRVA) == FieldAttributes.HasFieldRVA) {
- output.Write(" at I_{0:x8}", field.RVA);
- }
- if (field.HasConstant) {
- output.Write(" = ");
- WriteConstant(field.Constant);
- }
- output.WriteLine();
- if (field.HasCustomAttributes) {
- output.MarkFoldStart();
- WriteAttributes(field.CustomAttributes);
- output.MarkFoldEnd();
- }
- }
- #endregion
-
- #region Disassemble Property
- EnumNameCollection<PropertyAttributes> propertyAttributes = new EnumNameCollection<PropertyAttributes>() {
- { PropertyAttributes.SpecialName, "specialname" },
- { PropertyAttributes.RTSpecialName, "rtspecialname" },
- { PropertyAttributes.HasDefault, "hasdefault" },
- };
-
- public void DisassembleProperty(PropertyDefinition property)
- {
- // set current member
- currentMember = property;
-
- output.WriteDefinition(".property ", property);
- WriteFlags(property.Attributes, propertyAttributes);
- if (property.HasThis)
- output.Write("instance ");
- property.PropertyType.WriteTo(output);
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(property.Name));
-
- output.Write("(");
- if (property.HasParameters) {
- output.WriteLine();
- output.Indent();
- WriteParameters(property.Parameters);
- output.Unindent();
- }
- output.Write(")");
-
- OpenBlock(false);
- WriteAttributes(property.CustomAttributes);
- WriteNestedMethod(".get", property.GetMethod);
- WriteNestedMethod(".set", property.SetMethod);
-
- foreach (var method in property.OtherMethods) {
- WriteNestedMethod(".other", method);
- }
- CloseBlock();
- }
-
- void WriteNestedMethod(string keyword, MethodDefinition method)
- {
- if (method == null)
- return;
-
- output.Write(keyword);
- output.Write(' ');
- method.WriteTo(output);
- output.WriteLine();
- }
- #endregion
-
- #region Disassemble Event
- EnumNameCollection<EventAttributes> eventAttributes = new EnumNameCollection<EventAttributes>() {
- { EventAttributes.SpecialName, "specialname" },
- { EventAttributes.RTSpecialName, "rtspecialname" },
- };
-
- public void DisassembleEvent(EventDefinition ev)
- {
- // set current member
- currentMember = ev;
-
- output.WriteDefinition(".event ", ev);
- WriteFlags(ev.Attributes, eventAttributes);
- ev.EventType.WriteTo(output, ILNameSyntax.TypeName);
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(ev.Name));
- OpenBlock(false);
- 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();
- }
- #endregion
-
- #region Disassemble Type
- EnumNameCollection<TypeAttributes> typeVisibility = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.Public, "public" },
- { TypeAttributes.NotPublic, "private" },
- { TypeAttributes.NestedPublic, "nested public" },
- { TypeAttributes.NestedPrivate, "nested private" },
- { TypeAttributes.NestedAssembly, "nested assembly" },
- { TypeAttributes.NestedFamily, "nested family" },
- { TypeAttributes.NestedFamANDAssem, "nested famandassem" },
- { TypeAttributes.NestedFamORAssem, "nested famorassem" },
- };
-
- EnumNameCollection<TypeAttributes> typeLayout = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.AutoLayout, "auto" },
- { TypeAttributes.SequentialLayout, "sequential" },
- { TypeAttributes.ExplicitLayout, "explicit" },
- };
-
- EnumNameCollection<TypeAttributes> typeStringFormat = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.AutoClass, "auto" },
- { TypeAttributes.AnsiClass, "ansi" },
- { TypeAttributes.UnicodeClass, "unicode" },
- };
-
- EnumNameCollection<TypeAttributes> typeAttributes = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.Abstract, "abstract" },
- { TypeAttributes.Sealed, "sealed" },
- { TypeAttributes.SpecialName, "specialname" },
- { TypeAttributes.Import, "import" },
- { TypeAttributes.Serializable, "serializable" },
- { TypeAttributes.WindowsRuntime, "windowsruntime" },
- { TypeAttributes.BeforeFieldInit, "beforefieldinit" },
- { TypeAttributes.HasSecurity, null },
- };
-
- 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;
- }
-
- void WriteTypeParameters(ITextOutput output, IGenericParameterProvider p)
- {
- if (p.HasGenericParameters) {
- output.Write('<');
- for (int i = 0; i < p.GenericParameters.Count; i++) {
- if (i > 0)
- output.Write(", ");
- GenericParameter 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 (int 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('>');
- }
- }
- #endregion
-
- #region Helper methods
- void WriteAttributes(Collection<CustomAttribute> attributes)
- {
- foreach (CustomAttribute a in attributes) {
- output.Write(".custom ");
- a.Constructor.WriteTo(output);
- byte[] blob = a.GetBlob();
- if (blob != null) {
- output.Write(" = ");
- WriteBlob(blob);
- }
- output.WriteLine();
- }
- }
-
- void WriteBlob(byte[] blob)
- {
- output.Write("(");
- output.Indent();
-
- for (int i = 0; i < blob.Length; i++) {
- if (i % 16 == 0 && i < blob.Length - 1) {
- output.WriteLine();
- } else {
- output.Write(' ');
- }
- output.Write(blob[i].ToString("x2"));
- }
-
- output.WriteLine();
- output.Unindent();
- output.Write(")");
- }
-
- void OpenBlock(bool defaultCollapsed)
- {
- output.MarkFoldStart(defaultCollapsed: defaultCollapsed);
- output.WriteLine();
- output.WriteLine("{");
- output.Indent();
- }
-
- void CloseBlock(string comment = null)
- {
- output.Unindent();
- output.Write("}");
- if (comment != null)
- output.Write(" // " + comment);
- output.MarkFoldEnd();
- output.WriteLine();
- }
-
- void WriteFlags<T>(T flags, EnumNameCollection<T> flagNames) where T : struct
- {
- long val = Convert.ToInt64(flags);
- long tested = 0;
- foreach (var pair in flagNames) {
- tested |= pair.Key;
- if ((val & pair.Key) != 0 && pair.Value != null) {
- output.Write(pair.Value);
- output.Write(' ');
- }
- }
- if ((val & ~tested) != 0)
- output.Write("flag({0:x4}) ", val & ~tested);
- }
-
- void WriteEnum<T>(T enumValue, EnumNameCollection<T> enumNames) where T : struct
- {
- long val = Convert.ToInt64(enumValue);
- foreach (var pair in enumNames) {
- if (pair.Key == val) {
- if (pair.Value != null) {
- output.Write(pair.Value);
- output.Write(' ');
- }
- return;
- }
- }
- if (val != 0) {
- output.Write("flag({0:x4})", val);
- output.Write(' ');
- }
-
- }
-
- sealed class EnumNameCollection<T> : IEnumerable<KeyValuePair<long, string>> where T : struct
- {
- List<KeyValuePair<long, string>> names = new List<KeyValuePair<long, string>>();
-
- public void Add(T flag, string name)
- {
- names.Add(new KeyValuePair<long, string>(Convert.ToInt64(flag), name));
- }
-
- public IEnumerator<KeyValuePair<long, string>> GetEnumerator()
- {
- return names.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return names.GetEnumerator();
- }
- }
- #endregion
-
- 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 WriteAssemblyHeader(AssemblyDefinition asm)
- {
- output.Write(".assembly ");
- if (asm.Name.IsWindowsRuntime)
- output.Write("windowsruntime ");
- output.Write(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 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 ");
- if (aref.IsWindowsRuntime)
- output.Write("windowsruntime ");
- output.Write(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 WriteModuleHeader(ModuleDefinition module)
- {
- if (module.HasExportedTypes) {
- foreach (ExportedType exportedType in module.ExportedTypes) {
- output.Write(".class extern ");
- if (exportedType.IsForwarder)
- output.Write("forwarder ");
- output.Write(exportedType.DeclaringType != null ? exportedType.Name : exportedType.FullName);
- OpenBlock(false);
- if (exportedType.DeclaringType != null)
- output.WriteLine(".class extern {0}", DisassemblerHelpers.Escape(exportedType.DeclaringType.FullName));
- else
- output.WriteLine(".assembly extern {0}", DisassemblerHelpers.Escape(exportedType.Scope.Name));
- CloseBlock();
- }
- }
-
- output.WriteLine(".module {0}", module.Name);
- output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant());
- // TODO: imagebase, file alignment, stackreserve, subsystem
- output.WriteLine(".corflags 0x{0:x} // {1}", module.Attributes, module.Attributes.ToString());
-
- WriteAttributes(module.CustomAttributes);
- }
-
- public void WriteModuleContents(ModuleDefinition module)
- {
- foreach (TypeDefinition td in module.Types) {
- DisassembleType(td);
- output.WriteLine();
- }
- }
- }
-}