예제 #1
0
        Stream GetDecompiledStream(CancellationToken token)
        {
            var output = new PlainTextOutput();

            Decompile(output, token);
            return(ResourceUtils.StringToStream(output.ToString()));
        }
        public static void WriteTo(this Instruction instruction, PlainTextOutput writer)
        {
            writer.Write($"IL_{instruction.Offset:x4}");
            writer.Write(": ");
            writer.Write(instruction.OpCode.Name);

            if (instruction.Operand == null)
            {
                return;
            }

            writer.Write(' ');
            if (instruction.OpCode == OpCodes.Ldtoken)
            {
                if (instruction.Operand is MethodReference)
                {
                    writer.Write("method ");
                }
                else if (instruction.Operand is FieldReference)
                {
                    writer.Write("field ");
                }
            }
            WriteOperand(writer, instruction.Operand);
        }
예제 #3
0
        public static string Disassemble <T>(this T member)
            where T : class, IMemberDefinition
        {
            var writer = new PlainTextOutput();
            var dasm   = new ReflectionDisassembler(writer);

            if (typeof(T) == typeof(EventDefinition))
            {
                dasm.DisassembleEvent(member as EventDefinition);
            }
            else if (typeof(T) == typeof(FieldDefinition))
            {
                dasm.DisassembleField(member as FieldDefinition);
            }
            else if (typeof(T) == typeof(PropertyDefinition))
            {
                dasm.DisassembleProperty(member as PropertyDefinition);
            }
            else if (typeof(T) == typeof(MethodDefinition))
            {
                dasm.DisassembleMethod(member as MethodDefinition);
            }
            else if (typeof(T) == typeof(TypeDefinition))
            {
                dasm.DisassembleType(member as TypeDefinition);
            }
            else
            {
                throw new NotImplementedException($"the type {typeof(T).FullName} cannot be disassembled.");
            }

            return(writer.ToString());
        }
예제 #4
0
 public static async Task <string> GetSourceCode(TypeDefinition typeDefinition)
 {
     return(await Task.Run(() =>
     {
         try
         {
             var settings = new DecompilerSettings {
                 UsingDeclarations = true
             };
             var context = new DecompilerContext(typeDefinition.Module)
             {
                 CurrentType = typeDefinition,
                 Settings = settings
             };
             var astBuilder = new AstBuilder(context);
             var textOutput = new PlainTextOutput();
             astBuilder.GenerateCode(textOutput);
             return textOutput.ToString();
         }
         catch (Exception ex)
         {
             return "Error in creating source code from Type: " + ex.Message + ex.Message + Environment.NewLine + ex.StackTrace;
         }
     }));
 }
예제 #5
0
파일: SearchPane.cs 프로젝트: xornand/dnSpy
        public override string ToString()
        {
            var output = new PlainTextOutput();

            CreateUI(output, NameObject, false);
            return(output.ToString());
        }
예제 #6
0
 private void WriteHeaderInto(PlainTextOutput output)
 {
     output.WriteHeader();
     output.WriteSeparator();
     output.WriteRuntimeEnvironment();
     output.WriteSeparator();
 }
예제 #7
0
 public override void Create(DecompileContext ctx)
 {
     using (var writer = new StreamWriter(Filename, false, Encoding.UTF8)) {
         var output = new PlainTextOutput(writer);
         Decompile(ctx, output);
     }
 }
예제 #8
0
        public override string TypeToString(TypeReference t, bool includeNamespace, ICustomAttributeProvider attributeProvider)
        {
            PlainTextOutput output = new PlainTextOutput();

            t.WriteTo(output, true, shortName: !includeNamespace);
            return(output.ToString());
        }
예제 #9
0
        private void TestMet2()
        {
            if (structureViever.SelectedNode == null)
            {
                return;
            }
            MethodDefinition MetDef = structureViever.SelectedNode.Tag as MethodDefinition;

            if (MetDef == null)
            {
                return;
            }

            DecompilerContext decon = new DecompilerContext(dataStruct.AssemblyDefinition.MainModule);

            decon.CancellationToken = new System.Threading.CancellationToken();
            decon.CurrentType       = MetDef.DeclaringType;
            DecompilerSettings decoset = new DecompilerSettings();

            decon.Settings = decoset;
            AstBuilder ast = new AstBuilder(decon);

            ast.AddMethod(MetDef);
            PlainTextOutput pto = new PlainTextOutput();

            ast.GenerateCode(pto);

            var emc = new Actions.EditorMethodCreator(dataStruct);

            //emc.txtInjectCode.Text = pto.ToString();
            PushPanel(emc, "Debug Disassemble");
        }
        public override string TypeToString(TypeReference t, bool includeNamespace, ICustomAttributeProvider attributeProvider = null)
        {
            PlainTextOutput output = new PlainTextOutput();

            t.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);
            return(output.ToString());
        }
예제 #11
0
        public string ToString(Language language)
        {
            var output = new PlainTextOutput();

            Write(output, language);
            return(output.ToString());
        }
예제 #12
0
파일: Commands.cs 프로젝트: xornand/dnSpy
        protected override void Execute(LocalsCtxMenuContext context)
        {
            var output = new PlainTextOutput();

            foreach (var vm in context.SelectedItems)
            {
                //TODO: Break if it takes too long and the user cancels
                var printer = new ValuePrinter(output, DebuggerSettings.Instance.UseHexadecimal);
                printer.WriteExpander(vm);
                output.Write('\t', TextTokenType.Text);
                // Add an extra here to emulate VS output
                output.Write('\t', TextTokenType.Text);
                printer.WriteName(vm);
                output.Write('\t', TextTokenType.Text);
                printer.WriteValue(vm);
                output.Write('\t', TextTokenType.Text);
                printer.WriteType(vm);
                output.WriteLine();
            }
            var s = output.ToString();

            if (s.Length > 0)
            {
                Clipboard.SetText(s);
            }
        }
예제 #13
0
파일: Tester.cs 프로젝트: zhanggvi/ILSpy
        public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
        {
            if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler))
            {
                using (ModuleDefinition module = ModuleDefinition.ReadModule(sourceFileName))
                    using (var writer = new StreamWriter(outputFile)) {
                        module.Name = Path.GetFileNameWithoutExtension(outputFile);
                        var output = new PlainTextOutput(writer);
                        ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None);
                        rd.DetectControlStructure = false;
                        rd.WriteAssemblyReferences(module);
                        if (module.Assembly != null)
                        {
                            rd.WriteAssemblyHeader(module.Assembly);
                        }
                        output.WriteLine();
                        rd.WriteModuleHeader(module, skipMVID: true);
                        output.WriteLine();
                        rd.WriteModuleContents(module);
                    }
                return(outputFile);
            }

            string ildasmPath = SdkUtility.GetSdkPath("ildasm.exe");

            ProcessStartInfo info = new ProcessStartInfo(ildasmPath);

            info.Arguments              = $"/nobar /utf8 /out=\"{outputFile}\" \"{sourceFileName}\"";
            info.RedirectStandardError  = true;
            info.RedirectStandardOutput = true;
            info.UseShellExecute        = false;

            Process process = Process.Start(info);

            var outputTask = process.StandardOutput.ReadToEndAsync();
            var errorTask  = process.StandardError.ReadToEndAsync();

            Task.WaitAll(outputTask, errorTask);
            process.WaitForExit();

            Console.WriteLine("output: " + outputTask.Result);
            Console.WriteLine("errors: " + errorTask.Result);

            // Unlike the .imagebase directive (which is a fixed value when compiling with /deterministic),
            // the image base comment still varies... ildasm putting a random number here?
            string il = File.ReadAllText(outputFile);

            il = Regex.Replace(il, @"^// Image base: 0x[0-9A-F]+\r?\n", "", RegexOptions.Multiline);
            // and while we're at it, also remove the MVID
            il = Regex.Replace(il, @"^// MVID: \{[0-9A-F-]+\}\r?\n", "", RegexOptions.Multiline);
            // and the ildasm version info (varies from system to system)
            il = Regex.Replace(il, @"^// +Microsoft .* Disassembler\. +Version.*\r?\n", "", RegexOptions.Multiline);
            // copyright header "All rights reserved" is dependent on system language
            il = Regex.Replace(il, @"^// +Copyright .* Microsoft.*\r?\n", "", RegexOptions.Multiline);
            // filename may contain full path
            il = Regex.Replace(il, @"^// WARNING: Created Win32 resource file.*\r?\n", "", RegexOptions.Multiline);
            File.WriteAllText(outputFile, il);

            return(outputFile);
        }
예제 #14
0
 public override void Create(DecompileContext ctx)
 {
     using (var writer = new StreamWriter(Filename, false, Encoding.UTF8)) {
         var output = new PlainTextOutput(writer);
         language.Decompile(DecompilationType.AssemblyInfo, new DecompileAssemblyInfo(module, output, decompilationContext));
     }
 }
예제 #15
0
 public void DebugSave(string filename, string fileHeader = null)
 {
     using (PlainTextOutput pto = new PlainTextOutput(new System.IO.StreamWriter(filename)))
     {
         WriteBlock(pto, fileHeader);
     }
 }
예제 #16
0
        public static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Please enter a file path");
                return(1);
            }

            var filePath = args[0];

            Console.WriteLine(filePath);
            if (!File.Exists(filePath))
            {
                Console.WriteLine("File not Exist");
                return(1);
            }

            var modDef = ModuleDefinition.ReadModule(args[0]);

            foreach (var typeDef in modDef.GetTypes())
            {
                Console.WriteLine(Environment.NewLine + typeDef.Name + Environment.NewLine);
                var builder = new AstBuilder(new DecompilerContext(modDef));
                builder.AddType(typeDef);
                builder.RunTransformations();
                var output = new PlainTextOutput();
                builder.GenerateCode(output);
                Console.Write(output.ToString());
            }

            return(0);
        }
예제 #17
0
        public static async Task <string> Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
        {
            if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler))
            {
                using (var peFileStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read))
                    using (var peFile = new PEFile(sourceFileName, peFileStream))
                        using (var writer = new StringWriter())
                        {
                            var metadata = peFile.Metadata;
                            var output   = new PlainTextOutput(writer);
                            ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None);
                            rd.AssemblyResolver       = new UniversalAssemblyResolver(sourceFileName, true, null);
                            rd.DetectControlStructure = false;
                            rd.WriteAssemblyReferences(metadata);
                            if (metadata.IsAssembly)
                            {
                                rd.WriteAssemblyHeader(peFile);
                            }
                            output.WriteLine();
                            rd.WriteModuleHeader(peFile, skipMVID: true);
                            output.WriteLine();
                            rd.WriteModuleContents(peFile);

                            File.WriteAllText(outputFile, ReplacePrivImplDetails(writer.ToString()));
                        }
                return(outputFile);
            }

            string ildasmPath = Path.Combine(
                Path.GetDirectoryName(typeof(Tester).Assembly.Location),
                "ildasm.exe");

            var command = Cli.Wrap(ildasmPath)
                          .WithArguments($"/utf8 /out=\"{outputFile}\" \"{sourceFileName}\"")
                          .WithValidation(CommandResultValidation.None);

            var result = await command.ExecuteBufferedAsync().ConfigureAwait(false);

            Console.WriteLine("output: " + result.StandardOutput);
            Console.WriteLine("errors: " + result.StandardError);
            Assert.AreEqual(0, result.ExitCode, "ildasm failed");

            // Unlike the .imagebase directive (which is a fixed value when compiling with /deterministic),
            // the image base comment still varies... ildasm putting a random number here?
            string il = File.ReadAllText(outputFile);

            il = Regex.Replace(il, @"^// Image base: 0x[0-9A-F]+\r?\n", "", RegexOptions.Multiline);
            // and while we're at it, also remove the MVID
            il = Regex.Replace(il, @"^// MVID: \{[0-9A-F-]+\}\r?\n", "", RegexOptions.Multiline);
            // and the ildasm version info (varies from system to system)
            il = Regex.Replace(il, @"^// +Microsoft .* Disassembler\. +Version.*\r?\n", "", RegexOptions.Multiline);
            // copyright header "All rights reserved" is dependent on system language
            il = Regex.Replace(il, @"^// +Copyright .* Microsoft.*\r?\n", "", RegexOptions.Multiline);
            // filename may contain full path
            il = Regex.Replace(il, @"^// WARNING: Created Win32 resource file.*\r?\n", "", RegexOptions.Multiline);
            il = ReplacePrivImplDetails(il);
            File.WriteAllText(outputFile, il);

            return(outputFile);
        }
예제 #18
0
        protected override void CopyItemsAsText(LocalVM[] locals)
        {
            Array.Sort(locals, (a, b) => a.Index.CompareTo(b.Index));

            var output = new PlainTextOutput();

            for (int i = 0; i < locals.Length; i++)
            {
                if (i > 0)
                {
                    output.WriteLine();
                }

                var local = locals[i];
                output.Write(local.Index.ToString(), TextTokenType.Number);
                output.Write('\t', TextTokenType.Text);
                output.Write(local.IsPinned ? "P" : string.Empty, TextTokenType.Text);
                output.Write('\t', TextTokenType.Text);
                output.Write(local.IsCompilerGenerated ? "C" : string.Empty, TextTokenType.Text);
                output.Write('\t', TextTokenType.Text);
                output.Write(local.Name ?? string.Empty, TextTokenType.Local);
                output.Write('\t', TextTokenType.Text);
                BodyUtils.WriteObject(output, local.Type);
            }
            if (locals.Length > 1)
            {
                output.WriteLine();
            }

            Clipboard.SetText(output.ToString());
        }
예제 #19
0
        private bool _isInType;         // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)

        public ReflectionDisassembler(PlainTextOutput output)
        {
            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }
            _o = output;
        }
예제 #20
0
 private static void WriteTo(this FieldReference field, PlainTextOutput writer)
 {
     field.FieldType.WriteTo(writer, IlNameSyntax.SignatureNoNamedTypeParameters);
     writer.Write(' ');
     field.DeclaringType.WriteTo(writer, IlNameSyntax.TypeName);
     writer.Write("::");
     writer.Write(Escape(field.Name));
 }
예제 #21
0
        public static string Disassemble(this MethodBody body)
        {
            var writer = new PlainTextOutput();
            var dasm   = new MethodBodyDisassembler(writer);

            dasm.Disassemble(body);
            return(writer.ToString());
        }
예제 #22
0
        /// <summary>
        /// Converts a type reference into a string. This method is used by the member tree node for parameter and return types.
        /// </summary>
        public string TypeToString(ITypeDefOrRef type, bool includeNamespace, IHasCustomAttribute typeAttributes = null)
        {
            var writer = new StringWriter();
            var output = new PlainTextOutput(writer);

            TypeToString(output, type, includeNamespace, typeAttributes);
            return(writer.ToString());
        }
        public static string GetMethodDecompiledILCode(MethodDefinition method)
        {
            StringBuilder   sb         = new StringBuilder();
            PlainTextOutput textOutput = new PlainTextOutput(new StringWriter(sb));

            GetMethodDecompiledILCode(textOutput, method);
            return(sb.ToString());
        }
예제 #24
0
        public string Decompile(object @object)
        {
            if (@object == null)
            {
                return(String.Empty);
            }
            Language l = new CSharpLanguage();

            //ITextOutput output = new RtfTextOutput();
            ITextOutput output  = new PlainTextOutput();
            var         options = new DecompilationOptions();

            if (@object is AssemblyDefinition)
            {
                l.DecompileAssembly((AssemblyDefinition)@object, output, options);
            }
            else if (@object is TypeDefinition)
            {
                l.DecompileType((TypeDefinition)@object, output, options);
            }
            else if (@object is MethodDefinition)
            {
                l.DecompileMethod((MethodDefinition)@object, output, options);
            }
            else if (@object is FieldDefinition)
            {
                l.DecompileField((FieldDefinition)@object, output, options);
            }
            else if (@object is PropertyDefinition)
            {
                l.DecompileProperty((PropertyDefinition)@object, output, options);
            }
            else if (@object is EventDefinition)
            {
                l.DecompileEvent((EventDefinition)@object, output, options);
            }
            else if (@object is AssemblyNameReference)
            {
                output.Write("// Assembly Reference ");
                output.WriteDefinition(@object.ToString(), null);
                output.WriteLine();
            }
            else if (@object is ModuleReference)
            {
                output.Write("// Module Reference ");
                output.WriteDefinition(@object.ToString(), null);
                output.WriteLine();
            }
            else
            {
                output.Write(String.Format("// {0} ", @object.GetType().Name));
                output.WriteDefinition(@object.ToString(), null);
                output.WriteLine();
            }

            return(output.ToString());
        }
예제 #25
0
        public void Execute(CommandExecutionContext context)
        {
            _context = context;
            _output  = new PlainTextOutput();

            if (!String.IsNullOrEmpty(AssemblyName))
            {
                ClrModule module = context.Runtime.Modules.SingleOrDefault(
                    m => Path.GetFileNameWithoutExtension(m.FileName).Equals(
                        Path.GetFileNameWithoutExtension(AssemblyName),
                        StringComparison.InvariantCultureIgnoreCase
                        )
                    );
                if (module == null)
                {
                    context.WriteErrorLine("Could not find the assembly '{0}'.", AssemblyName);
                    return;
                }
                if (!String.IsNullOrEmpty(TypeName))
                {
                    DecompileTypeFromModule(TypeName, module.FileName);
                }
                else
                {
                    DecompileModule(module);
                }
            }
            else if (!String.IsNullOrEmpty(TypeName))
            {
                ClrType type = context.Heap.GetTypeByName(TypeName);
                if (type == null)
                {
                    context.WriteErrorLine(
                        "Could not find the type '{0}' on the heap. Try specifying the assembly name.",
                        TypeName);
                    return;
                }
                if (!String.IsNullOrEmpty(MethodName))
                {
                    var methods = type.Methods.Where(m => m.Name == MethodName).ToArray();
                    if (methods.Length == 0)
                    {
                        context.WriteErrorLine("Could not find the method '{0}'.", MethodName);
                        return;
                    }
                    DecompileMethods(methods);
                }
                else
                {
                    DecompileType(type);
                }
            }
            else
            {
                context.WriteErrorLine("At least one of --assembly or --type must be specified.");
            }
        }
예제 #26
0
        public static void DebugIlAst(ILFunction ilMethod, string stage, Func <ILInstruction, string> callback)
        {
            StringWriter w      = new StringWriter();
            ITextOutput  output = new PlainTextOutput(w);

            //if (context.CurrentMethodIsAsync)
            //	output.WriteLine("async/await");

            //var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable)
            //	.Where(v => v != null && !v.IsParameter).Distinct();
            //foreach (ILVariable v in allVariables) {
            //	if (v.Name == null)
            //		continue;

            //	output.WriteDefinition(v.Name, v);
            //	if (v.Type != null) {
            //		output.Write(" : ");
            //		if (v.IsPinned)
            //			output.Write("pinned ");
            //		v.Type.WriteTo(output, ILNameSyntax.ShortTypeName);

            //		if (v.Type.IsByReference)
            //			output.Write("*");

            //	}
            //	if (v.IsGenerated) {
            //		output.Write(" [generated]");
            //	}
            //	output.WriteLine();
            //}
            //output.WriteLine();

            //for (int idx = 0; idx < ilMethod.Body.Count; idx++) {
            //	if (info != null) {
            //		output.Write(info[idx]);
            //		output.Write("\t");
            //	}

            //	var node = ilMethod.Body[idx];
            //	node.WriteTo(output);


            //	output.WriteLine();
            //}

            WriteIlFunctionTo(ilMethod, output, new ILAstWritingOptions(), callback);


            var filename = s_totalCount++ + "_" + ilMethod.Method.Name + "_" + stage;

            if (filename.Length > 50)
            {
                filename = filename.Substring(0, 50);
            }
            File.WriteAllText(logsDir + "/" + filename + ".ilasm", w.ToString());
        }
		private static void WriteLabelList(PlainTextOutput writer, Instruction[] instructions)
		{
			writer.Write("(");
			for (var i = 0; i < instructions.Length; i++)
			{
				if (i != 0) writer.Write(", ");
				WriteOffsetReference(writer, instructions[i]);
			}
			writer.Write(")");
		}
예제 #28
0
        private void SetupDecompilerAndOriginalSource(MethodDefinition method)
        {
            _cSharpDecompiler = new CSharpLanguage();
            var decompilationOutput = new PlainTextOutput();

            _decompilationOptions = new DecompilationOptions();
            _cSharpDecompiler.DecompileMethod(method, decompilationOutput, _decompilationOptions);
            _oldText = decompilationOutput.ToString();
            _differ  = new SideBySideDiffBuilder(new Differ());
        }
예제 #29
0
        public static void WriteTo(this MethodReference method, PlainTextOutput writer)
        {
            if (method.ExplicitThis)
            {
                writer.Write("instance explicit ");
            }
            else if (method.HasThis)
            {
                writer.Write("instance ");
            }
            method.ReturnType.WriteTo(writer, IlNameSyntax.SignatureNoNamedTypeParameters);
            writer.Write(' ');
            if (method.DeclaringType != null)
            {
                method.DeclaringType.WriteTo(writer, IlNameSyntax.TypeName);
                writer.Write("::");
            }
            var md = method as MethodDefinition;

            if (md != null && md.IsCompilerControlled)
            {
                writer.Write(Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")));
            }
            else
            {
                writer.Write(Escape(method.Name));
            }
            var gim = method as GenericInstanceMethod;

            if (gim != null)
            {
                writer.Write('<');
                for (var i = 0; i < gim.GenericArguments.Count; i++)
                {
                    if (i > 0)
                    {
                        writer.Write(", ");
                    }
                    gim.GenericArguments[i].WriteTo(writer);
                }
                writer.Write('>');
            }
            writer.Write("(");
            var parameters = method.Parameters;

            for (var i = 0; i < parameters.Count; ++i)
            {
                if (i > 0)
                {
                    writer.Write(", ");
                }
                parameters[i].ParameterType.WriteTo(writer, IlNameSyntax.SignatureNoNamedTypeParameters);
            }
            writer.Write(")");
        }
예제 #30
0
        public string DumpIL()
        {
            TextWriter ilWriter               = new StringWriter();
            var        assemblyDefinition     = AssemblyDefinition.ReadAssembly(this.dllStream);
            var        ilOutput               = new PlainTextOutput(ilWriter);
            var        reflectionDisassembler = new ReflectionDisassembler(ilOutput, false, CancellationToken.None);

            reflectionDisassembler.WriteModuleContents(assemblyDefinition.MainModule);
            this.engine.UpdateLog("Dynamic assembly disassembled to IL.");
            return(ilWriter.ToString());
        }
예제 #31
0
        public override string ToString()
        {
            var output = new PlainTextOutput();

            WriteTo(output, new ILAstWritingOptions());
            if (!ILRange.IsEmpty)
            {
                output.Write(" at IL_" + ILRange.Start.ToString("x4"));
            }
            return(output.ToString());
        }
예제 #32
0
        public static int Main(string[] args)
        {
            var p = new Program();
            var options = new ConsoleOptions(args);
            var output = new PlainTextOutput(System.Console.Out);
            int returnVal = p.HandleInput(options, output);
            if (returnVal != 0)
                return returnVal;

            if (!options.help)
                p.Run(options, output);
            return 0;
        }
		public static void WriteTo(this Instruction instruction, PlainTextOutput writer)
		{
			writer.Write($"IL_{instruction.Offset:x4}");
			writer.Write(": ");
			writer.Write(instruction.OpCode.Name);

			if (instruction.Operand == null)
				return;

			writer.Write(' ');
			if (instruction.OpCode == OpCodes.Ldtoken)
			{
				if (instruction.Operand is MethodReference)
					writer.Write("method ");
				else if (instruction.Operand is FieldReference)
					writer.Write("field ");
			}
			WriteOperand(writer, instruction.Operand);
		}
		private static void WriteTo(this FieldReference field, PlainTextOutput writer)
		{
			field.FieldType.WriteTo(writer, IlNameSyntax.SignatureNoNamedTypeParameters);
			writer.Write(' ');
			field.DeclaringType.WriteTo(writer, IlNameSyntax.TypeName);
			writer.Write("::");
			writer.Write(Escape(field.Name));
		}
		public static void WriteOperand(PlainTextOutput writer, object operand)
		{
			if (operand == null)
				throw new ArgumentNullException(nameof(operand));
			var targetInstruction = operand as Instruction;
			if (targetInstruction != null)
			{
				WriteOffsetReference(writer, targetInstruction);
				return;
			}
			var targetInstructions = operand as Instruction[];
			if (targetInstructions != null)
			{
				WriteLabelList(writer, targetInstructions);
				return;
			}
			var variableRef = operand as VariableReference;
			if (variableRef != null)
			{
			    writer.Write(string.IsNullOrEmpty(variableRef.Name) ? variableRef.Index.ToString() : Escape(variableRef.Name));
			    return;
			}
			var paramRef = operand as ParameterReference;
			if (paramRef != null)
			{
			    writer.Write(string.IsNullOrEmpty(paramRef.Name) ? paramRef.Index.ToString() : Escape(paramRef.Name));
			    return;
			}
			var methodRef = operand as MethodReference;
			if (methodRef != null)
			{
				methodRef.WriteTo(writer);
				return;
			}
			var typeRef = operand as TypeReference;
			if (typeRef != null)
			{
				typeRef.WriteTo(writer, IlNameSyntax.TypeName);
				return;
			}
			var fieldRef = operand as FieldReference;
			if (fieldRef != null)
			{
				fieldRef.WriteTo(writer);
				return;
			}
			var s = operand as string;
			if (s != null)
			{
				writer.Write("\"" + ConvertString(s) + "\"");
			}
			else if (operand is char)
			{
				writer.Write(((int)(char)operand).ToString());
			}
			else if (operand is float)
			{
				var val = (float)operand;
				if (val == 0)
				{
					if (float.IsNegativeInfinity(1 / val))
						// negative zero is a special case
						writer.Write('-');
					writer.Write("0.0");
				}
				else if (float.IsInfinity(val) || float.IsNaN(val))
				{
					var data = BitConverter.GetBytes(val);
					writer.Write('(');
					for (var i = 0; i < data.Length; i++)
					{
						if (i > 0)
							writer.Write(' ');
						writer.Write(data[i].ToString("X2"));
					}
					writer.Write(')');
				}
				else
				{
					writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
				}
			}
			else if (operand is double)
			{
				var val = (double)operand;
				if (val == 0)
				{
					if (double.IsNegativeInfinity(1 / val))
						// negative zero is a special case
						writer.Write('-');
					writer.Write("0.0");
				}
				else if (double.IsInfinity(val) || double.IsNaN(val))
				{
					var data = BitConverter.GetBytes(val);
					writer.Write('(');
					for (var i = 0; i < data.Length; i++)
					{
						if (i > 0)
							writer.Write(' ');
						writer.Write(data[i].ToString("X2"));
					}
					writer.Write(')');
				}
				else
				{
					writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
				}
			}
			else if (operand is bool)
			{
				writer.Write((bool)operand ? "true" : "false");
			}
			else
			{
				s = ToInvariantCultureString(operand);
				writer.Write(s);
			}
		}
		public static void WriteOffsetReference(PlainTextOutput writer, Instruction instruction)
		{
			writer.Write($"IL_{instruction.Offset:x4}");
		}
		public static void WriteTo(this MethodReference method, PlainTextOutput writer)
		{
			if (method.ExplicitThis)
				writer.Write("instance explicit ");
			else if (method.HasThis)
				writer.Write("instance ");
			method.ReturnType.WriteTo(writer, IlNameSyntax.SignatureNoNamedTypeParameters);
			writer.Write(' ');
			if (method.DeclaringType != null)
			{
				method.DeclaringType.WriteTo(writer, IlNameSyntax.TypeName);
				writer.Write("::");
			}
			var md = method as MethodDefinition;
			if (md != null && md.IsCompilerControlled)
			{
				writer.Write(Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")));
			}
			else
			{
				writer.Write(Escape(method.Name));
			}
			var gim = method as GenericInstanceMethod;
			if (gim != null)
			{
				writer.Write('<');
				for (var i = 0; i < gim.GenericArguments.Count; i++)
				{
					if (i > 0)
						writer.Write(", ");
					gim.GenericArguments[i].WriteTo(writer);
				}
				writer.Write('>');
			}
			writer.Write("(");
			var parameters = method.Parameters;
			for (var i = 0; i < parameters.Count; ++i)
			{
				if (i > 0) writer.Write(", ");
				parameters[i].ParameterType.WriteTo(writer, IlNameSyntax.SignatureNoNamedTypeParameters);
			}
			writer.Write(")");
		}
		public MethodBodyDisassembler(PlainTextOutput output)
		{
			if (output == null)
				throw new ArgumentNullException(nameof(output));
			_o = output;
		}
		public static void WriteTo(this TypeReference type, PlainTextOutput writer, IlNameSyntax syntax = IlNameSyntax.Signature)
		{
			var syntaxForElementTypes = syntax == IlNameSyntax.SignatureNoNamedTypeParameters ? syntax : IlNameSyntax.Signature;
			if (type is PinnedType)
			{
				((PinnedType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
				writer.Write(" pinned");
			}
			else if (type is ArrayType)
			{
				var at = (ArrayType)type;
				at.ElementType.WriteTo(writer, syntaxForElementTypes);
				writer.Write('[');
				writer.Write(string.Join(", ", at.Dimensions));
				writer.Write(']');
			}
			else if (type is GenericParameter)
			{
				writer.Write('!');
				if (((GenericParameter)type).Owner.GenericParameterType == GenericParameterType.Method)
					writer.Write('!');
				if (string.IsNullOrEmpty(type.Name) || type.Name[0] == '!' || syntax == IlNameSyntax.SignatureNoNamedTypeParameters)
					writer.Write(((GenericParameter)type).Position.ToString());
				else
					writer.Write(Escape(type.Name));
			}
			else if (type is ByReferenceType)
			{
				((ByReferenceType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
				writer.Write('&');
			}
			else if (type is PointerType)
			{
				((PointerType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
				writer.Write('*');
			}
			else if (type is GenericInstanceType)
			{
				type.GetElementType().WriteTo(writer, syntaxForElementTypes);
				writer.Write('<');
				var arguments = ((GenericInstanceType)type).GenericArguments;
				for (var i = 0; i < arguments.Count; i++)
				{
					if (i > 0)
						writer.Write(", ");
					arguments[i].WriteTo(writer, syntaxForElementTypes);
				}
				writer.Write('>');
			}
			else if (type is OptionalModifierType)
			{
				((OptionalModifierType)type).ElementType.WriteTo(writer, syntax);
				writer.Write(" modopt(");
				((OptionalModifierType)type).ModifierType.WriteTo(writer, IlNameSyntax.TypeName);
				writer.Write(") ");
			}
			else if (type is RequiredModifierType)
			{
				((RequiredModifierType)type).ElementType.WriteTo(writer, syntax);
				writer.Write(" modreq(");
				((RequiredModifierType)type).ModifierType.WriteTo(writer, IlNameSyntax.TypeName);
				writer.Write(") ");
			}
			else
			{
				var name = PrimitiveTypeName(type.FullName);
				if ((syntax == IlNameSyntax.Signature || syntax == IlNameSyntax.SignatureNoNamedTypeParameters) && name != null)
				{
					writer.Write(name);
				}
				else
				{
					if (syntax == IlNameSyntax.Signature || syntax == IlNameSyntax.SignatureNoNamedTypeParameters)
						writer.Write(type.IsValueType ? "valuetype " : "class ");
					if (type.DeclaringType != null)
					{
						type.DeclaringType.WriteTo(writer, IlNameSyntax.TypeName);
						writer.Write('/');
						writer.Write(Escape(type.Name));
					}
					else
					{
						if (!type.IsDefinition && type.Scope != null && !(type is TypeSpecification))
							writer.Write("[{0}]", Escape(type.Scope.Name));
						writer.Write(Escape(type.FullName));
					}
				}
			}
		}