public override void DecompileMethod(MethodDef method, ITextOutput output, DecompilationOptions options) { WriteComment(output, "Method: "); output.WriteDefinition(IdentifierEscaper.Escape(method.FullName), method, TextTokenType.Comment, false); output.WriteLine(); if (!method.HasBody) { return; } StartKeywordBlock(output, ".body", method); ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(); DecompilerContext context = new DecompilerContext(method.Module) { CurrentType = method.DeclaringType, CurrentMethod = method }; ilMethod.Body = astBuilder.Build(method, inlineVariables, context); if (abortBeforeStep != null) { new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value); } if (context.CurrentMethodIsAsync) { output.Write("async", TextTokenType.Keyword); output.Write('/', TextTokenType.Operator); output.WriteLine("await", TextTokenType.Keyword); } var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); foreach (ILVariable v in allVariables) { output.WriteDefinition(IdentifierEscaper.Escape(v.Name), v, v.IsParameter ? TextTokenType.Parameter : TextTokenType.Local); if (v.Type != null) { output.WriteSpace(); output.Write(':', TextTokenType.Operator); output.WriteSpace(); if (v.IsPinned) { output.Write("pinned", TextTokenType.Keyword); output.WriteSpace(); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.IsGenerated) { output.WriteSpace(); output.Write('[', TextTokenType.Operator); output.Write("generated", TextTokenType.Keyword); output.Write(']', TextTokenType.Operator); } output.WriteLine(); } var memberMapping = new MemberMapping(method); foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, memberMapping); if (!node.WritesNewLine) output.WriteLine(); } output.AddDebugSymbols(memberMapping); EndKeywordBlock(output); }
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) { if (!method.HasBody) { return; } ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(); ilMethod.Body = astBuilder.Build(method, inlineVariables); if (abortBeforeStep != null) { DecompilerContext context = new DecompilerContext(method.Module) { CurrentType = method.DeclaringType, CurrentMethod = method }; new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value); } var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); foreach (ILVariable v in allVariables) { output.WriteDefinition(v.Name, v); if (v.Type != null) { output.Write(" : "); if (v.IsPinned) output.Write("pinned "); v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } output.WriteLine(); } output.WriteLine(); foreach (ILNode node in ilMethod.Body) { node.WriteTo(output); output.WriteLine(); } }
public static void WriteTo(this Instruction instruction, ITextOutput writer, Func<OpCode, string> getOpCodeDocumentation) { writer.WriteDefinition(DnlibExtensions.OffsetToString(instruction.GetOffset()), instruction, TextTokenType.Label, false); writer.Write(':', TextTokenType.Operator); writer.WriteSpace(); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, TextTokenType.OpCode); if (instruction.Operand != null) { writer.WriteSpace(); if (instruction.OpCode == OpCodes.Ldtoken) { var member = instruction.Operand as IMemberRef; if (member != null && member.IsMethod) { writer.Write("method", TextTokenType.Keyword); writer.WriteSpace(); } else if (member != null && member.IsField) { writer.Write("field", TextTokenType.Keyword); writer.WriteSpace(); } } WriteOperand(writer, instruction.Operand); } if (getOpCodeDocumentation != null) { var doc = getOpCodeDocumentation(instruction.OpCode); if (doc != null) { writer.Write("\t", TextTokenType.Text); writer.Write("// " + doc, TextTokenType.Comment); } } }
public static void WriteTo(this Instruction instruction, ITextOutput writer) { writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction); writer.Write(": "); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode); if(null != instruction.Operand) { writer.Write(' '); WriteOperand(writer, instruction.Operand); } }
public static void WriteTo(this Instruction instruction, ITextOutput writer) { writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction); writer.Write(": "); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode); if (instruction.Operand != null) { 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); } }
public static void WriteTo(this Instruction instruction, MethodDef method, CilBody body, ITextOutput writer) { writer.WriteDefinition(dnlibExtensions.OffsetToString(instruction.Offset), instruction, true); writer.Write(": "); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, true); if (instruction.Operand != null) { writer.Write(' '); if (instruction.OpCode == OpCodes.Ldtoken) { if (dnlibExtensions.IsMethod(instruction.Operand)) writer.WriteKeyword("method "); else if (dnlibExtensions.IsField(instruction.Operand)) writer.WriteKeyword("field "); } WriteOperand(writer, instruction.Operand); } else if (method != null && body != null) { switch (instruction.OpCode.Code) { case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: writer.WriteComment(" // "); var local = instruction.GetLocal(body.Variables); if (local != null) WriteOperand(writer, local); break; case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: writer.WriteComment(" // "); var arg = instruction.GetParameter(method.Parameters); if (arg != null) WriteOperand(writer, arg); break; } } }
public override void WriteShort(ITextOutput output, ILanguage language, bool showOffset) { var smartOutput = output as ISmartTextOutput; if (smartOutput != null) { language.WriteCommentBegin(output, true); output.WriteOffsetComment(this, showOffset); smartOutput.AddUIElement(() => { return(new System.Windows.Controls.Image { Source = imageSource, }); }); output.Write(" = ", TextTokenKind.Comment); const string LTR = "\u200E"; output.WriteDefinition(NameUtils.CleanName(Name) + LTR, this, TextTokenKind.Comment); language.WriteCommentEnd(output, true); output.WriteLine(); return; } base.WriteShort(output, language, showOffset); }
public virtual void Decompile(Language language, ITextOutput output) { language.WriteComment(output, string.Empty); output.WriteOffsetComment(this); output.WriteDefinition(UIUtils.CleanUpName(Name), this, TextTokenType.Comment); string extra = null; if (r.ResourceType == ResourceType.AssemblyLinked) { extra = ((AssemblyLinkedResource)r).Assembly.FullName; } else if (r.ResourceType == ResourceType.Linked) { var file = ((LinkedResource)r).File; extra = string.Format("{0}, {1}, {2}", file.Name, file.ContainsNoMetaData ? "ContainsNoMetaData" : "ContainsMetaData", NumberVMUtils.ByteArrayToString(file.HashValue)); } else if (r.ResourceType == ResourceType.Embedded) { extra = string.Format("{0} bytes", ((EmbeddedResource)r).Data.Length); } output.Write(string.Format(" ({0}{1}, {2})", extra == null ? string.Empty : string.Format("{0}, ", extra), r.ResourceType, r.Attributes), TextTokenType.Comment); output.WriteLine(); }
public virtual void Decompile(Language language, ITextOutput output) { language.WriteComment(output, string.Empty); if (Options.DecompilerSettingsPanel.CurrentDecompilerSettings.ShowTokenAndRvaComments) { long fo = FileOffset; if (fo != 0) output.Write(string.Format("0x{0:X8}: ", fo), TextTokenType.Comment); } output.WriteDefinition(UIUtils.CleanUpName(Name), this, TextTokenType.Comment); string extra = null; if (r.ResourceType == ResourceType.AssemblyLinked) extra = ((AssemblyLinkedResource)r).Assembly.FullName; else if (r.ResourceType == ResourceType.Linked) { var file = ((LinkedResource)r).File; extra = string.Format("{0}, {1}, {2}", file.Name, file.ContainsNoMetaData ? "ContainsNoMetaData" : "ContainsMetaData", AsmEditor.NumberVMUtils.ByteArrayToString(file.HashValue)); } output.Write(string.Format(" ({0}{1}, {2})", extra == null ? string.Empty : string.Format("{0}, ", extra), r.ResourceType, r.Attributes), TextTokenType.Comment); output.WriteLine(); }
public void Disassemble(MethodBody body) { // start writing IL code var 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); if (!string.IsNullOrEmpty(v.ToString())) { _output.Write(' '); _output.Write(DisassemblerHelpers.Escape(v.ToString())); } if (v.Index + 1 < method.Body.Variables.Count) { _output.Write(','); } _output.WriteLine(); } _output.Unindent(); _output.WriteLine(")"); } _output.WriteLine(); if (_detectControlStructure && body.Instructions.Count > 0) { var inst = body.Instructions[0]; var branchTargets = GetBranchTargets(body.Instructions); WriteStructureBody(new ILStructure(body), branchTargets, ref inst); } else { foreach (var inst in method.Body.Instructions) { inst.WriteTo(_output); _output.WriteLine(); } if (method.Body.HasExceptionHandlers) { _output.WriteLine(); foreach (var eh in method.Body.ExceptionHandlers) { eh.WriteTo(_output); _output.WriteLine(); } } } }
public virtual void WriteShort(ITextOutput output, ILanguage language, bool showOffset) { language.WriteCommentBegin(output, true); output.WriteOffsetComment(this, showOffset); output.WriteDefinition(NameUtils.CleanName(Name), this, TextTokenKind.Comment); string extra = null; switch (resource.ResourceType) { case ResourceType.AssemblyLinked: extra = ((AssemblyLinkedResource)resource).Assembly.FullName; break; case ResourceType.Linked: var file = ((LinkedResource)resource).File; extra = string.Format("{0}, {1}, {2}", file.Name, file.ContainsNoMetaData ? "ContainsNoMetaData" : "ContainsMetaData", NumberVMUtils.ByteArrayToString(file.HashValue)); break; case ResourceType.Embedded: extra = string.Format(dnSpy_Shared_Resources.NumberOfBytes, ((EmbeddedResource)resource).Data.Length); break; } output.Write(string.Format(" ({0}{1}, {2})", extra == null ? string.Empty : string.Format("{0}, ", extra), resource.ResourceType, resource.Attributes), TextTokenKind.Comment); language.WriteCommentEnd(output, true); output.WriteLine(); }
public virtual void Decompile(Language language, ITextOutput output) { language.WriteComment(output, string.Empty); if (Options.DecompilerSettingsPanel.CurrentDecompilerSettings.ShowTokenAndRvaComments) { long fo = FileOffset; if (fo != 0) output.Write(string.Format("0x{0:X8}: ", fo), TextTokenType.Comment); } output.WriteDefinition(UIUtils.CleanUpName(Name), this, TextTokenType.Comment); output.Write(string.Format(" = {0}", ValueString), TextTokenType.Comment); output.WriteLine(); }
public override void Decompile(FieldDef field, ITextOutput output, DecompilationContext ctx) { output.WriteReference(IdentifierEscaper.Escape(field.FieldType.GetFullName()), field.FieldType.ToTypeDefOrRef(), TextTokenKindUtils.GetTextTokenType(field.FieldType)); output.WriteSpace(); output.WriteDefinition(IdentifierEscaper.Escape(field.Name), field, TextTokenKindUtils.GetTextTokenType(field), false); var c = field.Constant; if (c != null) { output.WriteSpace(); output.Write("=", TextTokenKind.Operator); output.WriteSpace(); if (c.Value == null) { output.Write("null", TextTokenKind.Keyword); } else { switch (c.Type) { case ElementType.Boolean: if (c.Value is bool) { output.Write((bool)c.Value ? "true" : "false", TextTokenKind.Keyword); } else { goto default; } break; case ElementType.Char: output.Write(string.Format("'{0}'", c.Value), TextTokenKind.Char); break; case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.I: case ElementType.U: output.Write(string.Format("{0}", c.Value), TextTokenKind.Number); break; case ElementType.String: output.Write(string.Format("{0}", c.Value), TextTokenKind.String); break; default: output.Write(string.Format("{0}", c.Value), TextTokenKind.Text); break; } } } }
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 static void WriteTo(this Instruction instruction, ITextOutput writer, DisassemblerOptions options, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method) { if (options != null && (options.ShowTokenAndRvaComments || options.ShowILBytes)) { writer.Write("/* ", TextTokenType.Comment); bool needSpace = false; if (options.ShowTokenAndRvaComments) { ulong fileOffset = (ulong)baseOffs + instruction.Offset; writer.WriteReference(string.Format("0x{0:X8}", fileOffset), new AddressReference(options.OwnerModule == null ? null : options.OwnerModule.Location, false, fileOffset, (ulong)instruction.GetSize()), TextTokenType.Comment, false); needSpace = true; } if (options.ShowILBytes) { if (needSpace) writer.Write(' ', TextTokenType.Comment); if (byteReader == null) writer.Write("??", TextTokenType.Comment); else { int size = instruction.GetSize(); for (int i = 0; i < size; i++) { var b = byteReader.ReadByte(); if (b < 0) writer.Write("??", TextTokenType.Comment); else writer.Write(string.Format("{0:X2}", b), TextTokenType.Comment); } // Most instructions should be at most 5 bytes in length, but use 6 since // ldftn/ldvirtftn are 6 bytes long. The longest instructions are those with // 8 byte operands, ldc.i8 and ldc.r8: 9 bytes. const int MIN_BYTES = 6; for (int i = size; i < MIN_BYTES; i++) writer.Write(" ", TextTokenType.Comment); } } writer.Write(" */", TextTokenType.Comment); writer.WriteSpace(); } writer.WriteDefinition(DnlibExtensions.OffsetToString(instruction.GetOffset()), new InstructionReference(method, instruction), TextTokenType.Label, false); writer.Write(':', TextTokenType.Operator); writer.WriteSpace(); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, TextTokenType.OpCode); if (instruction.Operand != null) { int count = OPERAND_ALIGNMENT - instruction.OpCode.Name.Length; if (count <= 0) count = 1; writer.Write(spaces[count], TextTokenType.Text); if (instruction.OpCode == OpCodes.Ldtoken) { var member = instruction.Operand as IMemberRef; if (member != null && member.IsMethod) { writer.Write("method", TextTokenType.Keyword); writer.WriteSpace(); } else if (member != null && member.IsField) { writer.Write("field", TextTokenType.Keyword); writer.WriteSpace(); } } WriteOperand(writer, instruction.Operand, method); } if (options != null && options.GetOpCodeDocumentation != null) { var doc = options.GetOpCodeDocumentation(instruction.OpCode); if (doc != null) { writer.Write("\t", TextTokenType.Text); writer.Write("// " + doc, TextTokenType.Comment); } } }
public override void WriteIdentifier(Identifier identifier) { if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { output.Write('@'); } var definition = GetCurrentDefinition(); if (definition != null) { output.WriteDefinition(identifier.Name, definition, false); return; } var member = GetCurrentMemberReference(); if (member != null) { MemberReference cecil; if (member is IType type) { cecil = typeSystem.GetCecil(type.GetDefinition()); } else if (member is IMember) { cecil = typeSystem.GetCecil((IMember)member); } else { cecil = null; } if (cecil != null) { output.WriteReference(identifier.Name, cecil); return; } } definition = GetCurrentLocalDefinition(); if (definition != null) { output.WriteDefinition(identifier.Name, definition); return; } var memberRef = GetCurrentLocalReference(); if (memberRef != null) { output.WriteReference(identifier.Name, memberRef, true); return; } if (firstUsingDeclaration) { output.MarkFoldStart(defaultCollapsed: true); firstUsingDeclaration = false; } output.Write(identifier.Name); }
public virtual void Decompile(Language language, ITextOutput output) { language.WriteComment(output, string.Empty); output.WriteOffsetComment(this); output.WriteDefinition(UIUtils.CleanUpName(Name), this, TextTokenType.Comment); string extra = null; if (r.ResourceType == ResourceType.AssemblyLinked) extra = ((AssemblyLinkedResource)r).Assembly.FullName; else if (r.ResourceType == ResourceType.Linked) { var file = ((LinkedResource)r).File; extra = string.Format("{0}, {1}, {2}", file.Name, file.ContainsNoMetaData ? "ContainsNoMetaData" : "ContainsMetaData", NumberVMUtils.ByteArrayToString(file.HashValue)); } else if (r.ResourceType == ResourceType.Embedded) extra = string.Format("{0} bytes", ((EmbeddedResource)r).Data.Length); output.Write(string.Format(" ({0}{1}, {2})", extra == null ? string.Empty : string.Format("{0}, ", extra), r.ResourceType, r.Attributes), TextTokenType.Comment); output.WriteLine(); }
public virtual void Decompile(Language language, ITextOutput output) { language.WriteComment(output, string.Empty); output.WriteOffsetComment(this); output.WriteDefinition(UIUtils.CleanUpName(Name), this, TextTokenType.Comment); output.Write(string.Format(" = {0}", ValueString), TextTokenType.Comment); output.WriteLine(); }
public virtual void WriteShort(ITextOutput output, ILanguage language, bool showOffset) { language.WriteCommentBegin(output, true); output.WriteOffsetComment(this, showOffset); output.WriteDefinition(NameUtils.CleanName(Name), this, TextTokenKind.Comment); output.Write(string.Format(" = {0}", ValueString), TextTokenKind.Comment); language.WriteCommentEnd(output, true); 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(); } } } }
void WriteDefinition(string value, string def = null) { string str = NumberVMUtils.ToString(value, true); output.WriteDefinition(str, BamlToolTipReference.Create(def ?? IdentifierEscaper.Escape(value)), TextTokenKind.String, true); }
public static void WriteTo(this Instruction instruction, ITextOutput writer, DisassemblerOptions options, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method) { if (options != null && (options.ShowTokenAndRvaComments || options.ShowILBytes)) { writer.Write("/* ", TextTokenType.Comment); bool needSpace = false; if (options.ShowTokenAndRvaComments) { ulong fileOffset = (ulong)baseOffs + instruction.Offset; writer.WriteReference(string.Format("0x{0:X8}", fileOffset), new AddressReference(options.OwnerModule == null ? null : options.OwnerModule.Location, false, fileOffset, (ulong)instruction.GetSize()), TextTokenType.Comment, false); needSpace = true; } if (options.ShowILBytes) { if (needSpace) { writer.Write(' ', TextTokenType.Comment); } if (byteReader == null) { writer.Write("??", TextTokenType.Comment); } else { int size = instruction.GetSize(); for (int i = 0; i < size; i++) { var b = byteReader.ReadByte(); if (b < 0) { writer.Write("??", TextTokenType.Comment); } else { writer.Write(string.Format("{0:X2}", b), TextTokenType.Comment); } } // Most instructions should be at most 5 bytes in length, but use 6 since // ldftn/ldvirtftn are 6 bytes long. The longest instructions are those with // 8 byte operands, ldc.i8 and ldc.r8: 9 bytes. const int MIN_BYTES = 6; for (int i = size; i < MIN_BYTES; i++) { writer.Write(" ", TextTokenType.Comment); } } } writer.Write(" */", TextTokenType.Comment); writer.WriteSpace(); } writer.WriteDefinition(DnlibExtensions.OffsetToString(instruction.GetOffset()), new InstructionReference(method, instruction), TextTokenType.Label, false); writer.Write(':', TextTokenType.Operator); writer.WriteSpace(); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, TextTokenType.OpCode); if (instruction.Operand != null) { int count = OPERAND_ALIGNMENT - instruction.OpCode.Name.Length; if (count <= 0) { count = 1; } writer.Write(spaces[count], TextTokenType.Text); if (instruction.OpCode == OpCodes.Ldtoken) { var member = instruction.Operand as IMemberRef; if (member != null && member.IsMethod) { writer.Write("method", TextTokenType.Keyword); writer.WriteSpace(); } else if (member != null && member.IsField) { writer.Write("field", TextTokenType.Keyword); writer.WriteSpace(); } } WriteOperand(writer, instruction.Operand, method); } if (options != null && options.GetOpCodeDocumentation != null) { var doc = options.GetOpCodeDocumentation(instruction.OpCode); if (doc != null) { writer.Write("\t", TextTokenType.Text); writer.Write("// " + doc, TextTokenType.Comment); } } }
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 override void Decompile(MethodDef method, ITextOutput output, DecompilationContext ctx) { WriteCommentBegin(output, true); output.Write("Method: ", TextTokenKind.Comment); output.WriteDefinition(IdentifierEscaper.Escape(method.FullName), method, TextTokenKind.Comment, false); WriteCommentEnd(output, true); output.WriteLine(); if (!method.HasBody) { return; } StartKeywordBlock(output, ".body", method); ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(); DecompilerContext context = new DecompilerContext(method.Module) { CurrentType = method.DeclaringType, CurrentMethod = method }; ilMethod.Body = astBuilder.Build(method, inlineVariables, context); if (abortBeforeStep != null) { new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value); } if (context.CurrentMethodIsAsync) { output.Write("async", TextTokenKind.Keyword); output.Write("/", TextTokenKind.Operator); output.WriteLine("await", TextTokenKind.Keyword); } var allVariables = ilMethod.GetSelfAndChildrenRecursive <ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); foreach (ILVariable v in allVariables) { output.WriteDefinition(IdentifierEscaper.Escape(v.Name), v, v.IsParameter ? TextTokenKind.Parameter : TextTokenKind.Local); if (v.Type != null) { output.WriteSpace(); output.Write(":", TextTokenKind.Operator); output.WriteSpace(); if (v.IsPinned) { output.Write("pinned", TextTokenKind.Keyword); output.WriteSpace(); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.GeneratedByDecompiler) { output.WriteSpace(); output.Write("[", TextTokenKind.Operator); output.Write("generated", TextTokenKind.Keyword); output.Write("]", TextTokenKind.Operator); } output.WriteLine(); } var memberMapping = new MemberMapping(method); foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, memberMapping); if (!node.WritesNewLine) { output.WriteLine(); } } output.AddDebugSymbols(memberMapping); EndKeywordBlock(output); }
void StartKeywordBlock(ITextOutput output, string keyword, IMemberDef member) { output.Write(keyword, TextTokenType.Keyword); output.WriteSpace(); output.WriteDefinition(IdentifierEscaper.Escape(member.Name), member, TextTokenHelper.GetTextTokenType(member), false); output.WriteSpace(); output.WriteLeftBrace(); output.WriteLine(); output.Indent(); }
internal void WriteDefinitionTo(ITextOutput output) { switch (Kind) { case VariableKind.Local: output.Write("local "); break; case VariableKind.PinnedLocal: output.Write("pinned local "); break; case VariableKind.Parameter: output.Write("param "); break; case VariableKind.Exception: output.Write("exception "); break; case VariableKind.StackSlot: output.Write("stack "); break; case VariableKind.InitializerTarget: output.Write("initializer "); break; case VariableKind.ForeachLocal: output.Write("foreach "); break; case VariableKind.UsingLocal: output.Write("using "); break; default: throw new ArgumentOutOfRangeException(); } output.WriteDefinition(this.Name, this, isLocal: true); output.Write(" : "); Type.WriteTo(output); output.Write('('); if (Kind == VariableKind.Parameter || Kind == VariableKind.Local || Kind == VariableKind.PinnedLocal) { output.Write("Index={0}, ", Index); } output.Write("LoadCount={0}, AddressCount={1}, StoreCount={2})", LoadCount, AddressCount, StoreCount); if (hasInitialValue && Kind != VariableKind.Parameter) { output.Write(" init"); } if (CaptureScope != null) { output.Write(" captured in " + CaptureScope.EntryPoint.Label); } if (StateMachineField != null) { output.Write(" from state-machine"); } }
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 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 DisassembleMethod(MethodDefinition method) { // write method header output.WriteDefinition(".method ", method); DisassembleMethodInternal(method); }
public override void WriteTo(ITextOutput output) { output.WriteDefinition(Name + ":", this); }
public void WriteDefinition(string text, object definition, bool isLocal = true) { _inner.WriteDefinition(text, definition, isLocal); _currentLineLength += text.Length; }
public override void DecompileField(FieldDef field, ITextOutput output, DecompilationOptions options) { output.WriteReference(IdentifierEscaper.Escape(field.FieldType.GetFullName()), field.FieldType.ToTypeDefOrRef(), TextTokenHelper.GetTextTokenType(field.FieldType)); output.WriteSpace(); output.WriteDefinition(IdentifierEscaper.Escape(field.Name), field, TextTokenHelper.GetTextTokenType(field), false); var c = field.Constant; if (c != null) { output.WriteSpace(); output.Write('=', TextTokenType.Operator); output.WriteSpace(); if (c.Value == null) output.Write("null", TextTokenType.Keyword); else { switch (c.Type) { case ElementType.Boolean: if (c.Value is bool) output.Write((bool)c.Value ? "true" : "false", TextTokenType.Keyword); else goto default; break; case ElementType.Char: output.Write(string.Format("'{0}'", c.Value), TextTokenType.Char); break; case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.I: case ElementType.U: output.Write(string.Format("{0}", c.Value), TextTokenType.Number); break; case ElementType.String: output.Write(string.Format("{0}", c.Value), TextTokenType.String); break; default: output.Write(string.Format("{0}", c.Value), TextTokenType.Text); break; } } } }
public override void WriteShort(ITextOutput output, ILanguage language, bool showOffset) { var smartOutput = output as ISmartTextOutput; if (smartOutput != null) { language.WriteCommentBegin(output, true); output.WriteOffsetComment(this, showOffset); smartOutput.AddUIElement(() => { return new System.Windows.Controls.Image { Source = imageSource, }; }); output.Write(" = ", TextTokenKind.Comment); output.WriteDefinition(NameUtils.CleanName(Name), this, TextTokenKind.Comment); language.WriteCommentEnd(output, true); output.WriteLine(); return; } base.WriteShort(output, language, showOffset); }
/// <summary> /// Write human readable output. /// </summary> public override void WriteTo(ITextOutput output, FormattingOptions format) { output.WriteDefinition(Name + ":", this); }
void WriteDefinition(string value, string def = null) { string str = string.Format("\"{0}\"", TextWriterTokenWriter.ConvertString(value)); output.WriteDefinition(str, def ?? IdentifierEscaper.Escape(value), TextTokenType.String, true); }