public BlockStatement CreateMethodBody() { if (methodDef.Body == null) return null; context.CancellationToken.ThrowIfCancellationRequested(); ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); ilMethod.Body = astBuilder.Build(methodDef, true); context.CancellationToken.ThrowIfCancellationRequested(); ILAstOptimizer bodyGraph = new ILAstOptimizer(); bodyGraph.Optimize(context, ilMethod); context.CancellationToken.ThrowIfCancellationRequested(); var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable).Where(v => v != null && !v.IsGenerated).Distinct(); NameVariables.AssignNamesToVariables(methodDef.Parameters.Select(p => p.Name), allVariables, ilMethod); context.CancellationToken.ThrowIfCancellationRequested(); Ast.BlockStatement astBlock = TransformBlock(ilMethod); CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments foreach (ILVariable v in localVariablesToDefine) { DeclareVariableInSmallestScope.DeclareVariable(astBlock, AstBuilder.ConvertType(v.Type), v.Name); } return astBlock; }
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 void Run(DevirtualisationContext context) { foreach (var method in context.VirtualisedMethods) { if (method.IsExport && !context.Options.SelectedExports.Contains(method.ExportId.Value)) { continue; } context.Logger.Debug(Tag, $"Building IL AST for function_{method.Function.EntrypointAddress:X4}..."); // Create builder. var builder = new ILAstBuilder { Logger = context.Logger, MaxSimplificationPasses = context.Options.MaxSimplificationPasses }; // Subscribe to progress events if user specified it in the options. if (context.Options.OutputOptions.DumpAllControlFlowGraphs) { int step = 1; builder.InitialAstBuilt += (sender, args) => { context.Logger.Debug2(Tag, $"Dumping initial IL AST for function_{method.Function.EntrypointAddress:X4}..."); method.ILCompilationUnit = args; DumpILAst(context, method, $" (0. Initial)"); }; builder.TransformEnd += (sender, args) => { context.Logger.Debug2(Tag, $"Dumping tentative IL AST for function_{method.Function.EntrypointAddress:X4}..."); method.ILCompilationUnit = args.Unit; DumpILAst(context, method, $" ({step++}. {args.Transform.Name}-{args.Iteration})"); }; } // Build the AST. try { method.ILCompilationUnit = builder.BuildAst(method.ControlFlowGraph, method.Function.FrameLayout, context.Constants); } catch (Exception ex) when(context.Options.EnableSalvageMode) { context.Logger.Error(Tag, $"Failed to construct IL-AST of function_{method.Function.EntrypointAddress:X4}. " + $"The function will not be recompiled. {ex.Message}"); } // Dump graphs if user specified it in the options. if (method.ILCompilationUnit != null && context.Options.OutputOptions.DumpControlFlowGraphs) { context.Logger.Log(Tag, $"Dumping IL AST for function_{method.Function.EntrypointAddress:X4}..."); DumpILAst(context, method); DumpILAstTree(context, method); } } }
InterMethod IResolver.Resolve(MethodReference methodRef, List <InterGenericArgument> genericArgs) { InterMethod founded = null; InterMethod tmp = new InterMethod(methodRef, genericArgs, this, M => founded = M); if (founded == null) { Messages.Verbose("Adding method {0} to compile...", tmp.ToString()); tmp.DeclaringType.Methods.Add(tmp); founded = tmp; var unionedGenericArgs = tmp.FullGenericArguments; if (tmp.HasBody) { MethodDefinition methodDef = tmp.Body.Method; ILAstBuilder builder = new ILAstBuilder(); ILBlock ilBody = new ILBlock(); DecompilerContext context = new DecompilerContext(methodDef.Module) { CurrentType = methodDef.DeclaringType, CurrentMethod = methodDef }; Utils.SetDecompillerSettings(context.Settings); ilBody.Body = builder.Build(methodDef, true, context); new ILAstOptimizer().Optimize(context, ilBody); ProcessMethodDecencies(tmp, ilBody, tmp.FullGenericArguments); } } return(founded); }
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(); 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.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) { 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.IsGenerated) { output.Write(" [generated]"); } output.WriteLine(); } output.WriteLine(); foreach (ILNode node in ilMethod.Body) { node.WriteTo(output); output.WriteLine(); } }
public BlockStatement CreateMethodBody(IEnumerable<ParameterDeclaration> parameters, ConcurrentDictionary<int, IEnumerable<ILVariable>> localVariables) { if (methodDef.Body == null) return null; if (localVariables == null) throw new ArgumentException("localVariables must be instantiated"); context.CancellationToken.ThrowIfCancellationRequested(); ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); ilMethod.Body = astBuilder.Build(methodDef, true); context.CancellationToken.ThrowIfCancellationRequested(); ILAstOptimizer bodyGraph = new ILAstOptimizer(); bodyGraph.Optimize(context, ilMethod); context.CancellationToken.ThrowIfCancellationRequested(); var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); Debug.Assert(context.CurrentMethod == methodDef); NameVariables.AssignNamesToVariables(context, astBuilder.Parameters, allVariables, ilMethod); if (parameters != null) { foreach (var pair in (from p in parameters join v in astBuilder.Parameters on p.Annotation<ParameterDefinition>() equals v.OriginalParameter select new { p, v.Name })) { pair.p.Name = pair.Name; } } context.CancellationToken.ThrowIfCancellationRequested(); Ast.BlockStatement astBlock = TransformBlock(ilMethod); CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments Statement insertionPoint = astBlock.Statements.FirstOrDefault(); foreach (ILVariable v in localVariablesToDefine) { AstType type; if (v.Type.ContainsAnonymousType()) type = new SimpleType("var"); else type = AstBuilder.ConvertType(v.Type); var newVarDecl = new VariableDeclarationStatement(type, v.Name); astBlock.Statements.InsertBefore(insertionPoint, newVarDecl); } // store the variables - used for debugger int token = methodDef.MetadataToken.ToInt32(); localVariables.AddOrUpdate(token, allVariables, (key, oldValue) => allVariables); return astBlock; }
private static ILBlock Decompile(MethodDefinition method) { bool inlineVariables = false; 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); new ILAstOptimizer().Optimize(context, ilMethod, ILAstOptimizationStep.None); return ilMethod; }
public void Run(DevirtualisationContext context) { foreach (var method in context.VirtualisedMethods) { if (method.IsExport && !context.Options.SelectedExports.Contains(method.ExportId.Value, method.ExportInfo)) { continue; } context.Logger.Debug(Tag, $"Building IL AST for function_{method.Function.EntrypointAddress:X4}..."); // Create builder. var builder = new ILAstBuilder(context.TargetImage) { Logger = context.Logger }; // Subscribe to progress events if user specified it in the options. if (context.Options.OutputOptions.DumpAllControlFlowGraphs) { int step = 1; builder.InitialAstBuilt += (sender, args) => { context.Logger.Debug(Tag, $"Dumping initial IL AST for function_{method.Function.EntrypointAddress:X4}..."); method.ILCompilationUnit = args; DumpILAst(context, method, $" (0. Initial)"); }; builder.TransformEnd += (sender, args) => { context.Logger.Debug(Tag, $"Dumping tentative IL AST for function_{method.Function.EntrypointAddress:X4}..."); method.ILCompilationUnit = args.Unit; DumpILAst(context, method, $" ({step++}. {args.Transform.Name}-{args.Iteration})"); }; } // Build the AST. method.ILCompilationUnit = builder.BuildAst(method.ControlFlowGraph, method.Function.FrameLayout, context.Constants); // Dump graphs if user specified it in the options. if (context.Options.OutputOptions.DumpControlFlowGraphs) { context.Logger.Log(Tag, $"Dumping IL AST for function_{method.Function.EntrypointAddress:X4}..."); DumpILAst(context, method); DumpILAstTree(context, method); } } }
protected override ILBlock CreateNewBlock() { if (Context.Version != UndertaleVersion.V10000) { throw new Exception("Cannot compile old code using new"); } Locals = new Dictionary <string, ILVariable>(); // Don't need any of that above since we don't do asms anymore var error = new ErrorContext(name); ILBlock block = new ILBlock(); block.Body = new Dissasembler.OldByteCodeAst().Build(this, error); block = new ILAstBuilder().Build(block, Locals, error); block.FixParents(); return(block); }
private static ILBlock Decompile(MethodDefinition method) { bool inlineVariables = false; 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); new ILAstOptimizer().Optimize(context, ilMethod, ILAstOptimizationStep.None); return(ilMethod); }
public Dictionary<int, EventRegistration[]> DecompileEventMappings(string fullTypeName) { var result = new Dictionary<int, EventRegistration[]>(); TypeDefinition type = this.assembly.MainModule.GetType(fullTypeName); if (type == null) return result; MethodDefinition def = null; foreach (var method in type.Methods) { if (method.Name == "System.Windows.Markup.IComponentConnector.Connect") { def = method; break; } } if (def == null) return result; // decompile method and optimize the switch ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); ILAstOptimizer optimizer = new ILAstOptimizer(); var context = new DecompilerContext(type.Module) { CurrentMethod = def, CurrentType = type }; ilMethod.Body = astBuilder.Build(def, true, context); optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.RemoveRedundantCode3); ILSwitch ilSwitch = ilMethod.Body.OfType<ILSwitch>().FirstOrDefault(); ILCondition condition = ilMethod.Body.OfType<ILCondition>().FirstOrDefault(); if (ilSwitch != null) { foreach (var caseBlock in ilSwitch.CaseBlocks) { if (caseBlock.Values == null) continue; var events = FindEvents(caseBlock); foreach (int id in caseBlock.Values) result.Add(id, events); } } else if (condition != null) { result.Add(1, FindEvents(condition.FalseBlock)); } return result; }
public BlockStatement CreateMethodBody(IEnumerable<ParameterDeclaration> parameters) { if (methodDef.Body == null) return null; context.CancellationToken.ThrowIfCancellationRequested(); ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); ilMethod.Body = astBuilder.Build(methodDef, true); context.CancellationToken.ThrowIfCancellationRequested(); ILAstOptimizer bodyGraph = new ILAstOptimizer(); bodyGraph.Optimize(context, ilMethod); context.CancellationToken.ThrowIfCancellationRequested(); var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); Debug.Assert(context.CurrentMethod == methodDef); NameVariables.AssignNamesToVariables(context, astBuilder.Parameters, allVariables, ilMethod); if (parameters != null) { foreach (var pair in (from p in parameters join v in astBuilder.Parameters on p.Annotation<ParameterDefinition>() equals v.OriginalParameter select new { p, v.Name })) { pair.p.Name = pair.Name; } } context.CancellationToken.ThrowIfCancellationRequested(); Ast.BlockStatement astBlock = TransformBlock(ilMethod); CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments Statement insertionPoint = astBlock.Statements.FirstOrDefault(); foreach (ILVariable v in localVariablesToDefine) { var newVarDecl = new VariableDeclarationStatement(AstBuilder.ConvertType(v.Type), v.Name); astBlock.Statements.InsertBefore(insertionPoint, newVarDecl); } return astBlock; }
public override void Decompile(MethodDef method, IDecompilerOutput output, DecompilationContext ctx) { WriteCommentBegin(output, true); output.Write("Method: ", BoxedTextColor.Comment); output.Write(IdentifierEscaper.Escape(method.FullName), method, DecompilerReferenceFlags.Definition, BoxedTextColor.Comment); WriteCommentEnd(output, true); output.WriteLine(); if (!method.HasBody) { return; } var bodyInfo = StartKeywordBlock(output, ".body", method); ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(CodeBracesRangeFlags.MethodBraces); DecompilerContext context = new DecompilerContext(method.Module, MetadataTextColorProvider) { CurrentType = method.DeclaringType, CurrentMethod = method, CalculateBinSpans = ctx.CalculateBinSpans, }; ilMethod.Body = astBuilder.Build(method, inlineVariables, context); if (abortBeforeStep != null) { new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value); } if (context.CurrentMethodIsYieldReturn) { output.Write("yield", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); output.WriteLine("return", BoxedTextColor.Keyword); } if (context.CurrentMethodIsAsync) { output.Write("async", BoxedTextColor.Keyword); output.Write("/", BoxedTextColor.Punctuation); output.WriteLine("await", BoxedTextColor.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.Write(IdentifierEscaper.Escape(v.Name), (object)v.OriginalVariable ?? (object)v.OriginalParameter ?? v.Id, DecompilerReferenceFlags.Local | DecompilerReferenceFlags.Definition, v.IsParameter ? BoxedTextColor.Parameter : BoxedTextColor.Local); if (v.Type != null) { output.Write(" ", BoxedTextColor.Text); output.Write(":", BoxedTextColor.Punctuation); output.Write(" ", BoxedTextColor.Text); if (v.IsPinned) { output.Write("pinned", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.GeneratedByDecompiler) { output.Write(" ", BoxedTextColor.Text); var start = output.NextPosition; output.Write("[", BoxedTextColor.Punctuation); output.Write("generated", BoxedTextColor.Keyword); var end = output.NextPosition; output.Write("]", BoxedTextColor.Punctuation); output.AddBracePair(new TextSpan(start, 1), new TextSpan(end, 1), CodeBracesRangeFlags.SquareBrackets); } output.WriteLine(); } var builder = new MethodDebugInfoBuilder(method); foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, builder); if (!node.WritesNewLine) { output.WriteLine(); } } output.AddDebugInfo(builder.Create()); EndKeywordBlock(output, bodyInfo, CodeBracesRangeFlags.MethodBraces, addLineSeparator: true); }
public void Compile() { MethodDefinition methodDef = thisMethod.Body.Method; Messages.Verbose(" Generating IL graph..."); ILAstBuilder builder = new ILAstBuilder(); ilBody = new ILBlock(); DecompilerContext context = new DecompilerContext(methodDef.Module) { CurrentType = methodDef.DeclaringType, CurrentMethod = methodDef }; Utils.SetDecompillerSettings(context.Settings); ilBody.Body = builder.Build(methodDef, true, context); new ILAstOptimizer().Optimize(context, ilBody); FillVars(builder.Parameters); Messages.Verbose(" Preprocess IL graph..."); RunPreprocessor(); Messages.Verbose(" Compiling IL graph to java bytecode..."); CompileNode(ilBody, ExpectType.None); //Checking for deleted last ret if (ilBody.Body.Count > 0) { ILNode lastNode = ilBody.Body.Last(); if ((lastNode is ILExpression) && (((ILExpression)lastNode).Code != ILCode.Ret) && (((ILExpression)lastNode).Code != ILCode.Throw)) { CompileRet(null, ExpectType.None); } else if (thisMethod.ReturnParameter.Type.PrimitiveType == PrimitiveType.Void) { CompileRet(null, ExpectType.None); } } else { CompileRet(null, ExpectType.None); } oldCodeGenerator = codeGenerator; byte[] prolog = GenerateMethodProlog(); codeGenerator = oldCodeGenerator; Messages.Verbose(" Linking java bytecode..."); codeGenerator.StartOffset = prolog.Length; byte[] codeBytes = codeGenerator.Link(constsPool); GenerateJavaExceptionTable(); resultCode = new Java.Attributes.Code(); resultCode.CodeBytes = prolog.Concat(codeBytes).ToArray(); WriteJavaExceptionTable(prolog.Length); Messages.Verbose(" Simulating stack to calculate MaxStack and MaxLocals..."); StackSimulator.SimulateStack(constsPool, resultCode); resultCode.MaxLocals = (ushort)nextVarIndex; if (Program.Debug) { GenerateDebugInfo(prolog.Length); } }
public Dictionary <int, EventRegistration[]> DecompileEventMappings(string fullTypeName) { var result = new Dictionary <int, EventRegistration[]>(); TypeDefinition type = this.assembly.MainModule.GetType(fullTypeName); if (type == null) { return(result); } MethodDefinition def = null; foreach (var method in type.Methods) { if (method.Name == "System.Windows.Markup.IComponentConnector.Connect") { def = method; break; } } if (def == null) { return(result); } // decompile method and optimize the switch ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); ilMethod.Body = astBuilder.Build(def, true); ILAstOptimizer optimizer = new ILAstOptimizer(); var context = new DecompilerContext(type.Module) { CurrentMethod = def, CurrentType = type }; optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.RemoveRedundantCode3); ILSwitch ilSwitch = ilMethod.Body.OfType <ILSwitch>().FirstOrDefault(); ILCondition condition = ilMethod.Body.OfType <ILCondition>().FirstOrDefault(); if (ilSwitch != null) { foreach (var caseBlock in ilSwitch.CaseBlocks) { if (caseBlock.Values == null) { continue; } var events = FindEvents(caseBlock); foreach (int id in caseBlock.Values) { result.Add(id, events); } } } else if (condition != null) { result.Add(1, FindEvents(condition.FalseBlock)); } return(result); }
/// <summary> /// Creates ILAst for the specified method, optimized up to before the 'YieldReturn' step. /// </summary> ILBlock CreateILAst(MethodDefinition method) { if (method == null || !method.HasBody) throw new SymbolicAnalysisFailedException(); ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); ilMethod.Body = astBuilder.Build(method, true, context); ILAstOptimizer optimizer = new ILAstOptimizer(); optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.YieldReturn); return ilMethod; }
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); }
public override void Decompile(MethodDef method, IDecompilerOutput output, DecompilationContext ctx) { WriteCommentBegin(output, true); output.Write("Method: ", BoxedTextColor.Comment); output.Write(IdentifierEscaper.Escape(method.FullName), method, DecompilerReferenceFlags.Definition, BoxedTextColor.Comment); 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, MetadataTextColorProvider) { 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", BoxedTextColor.Keyword); output.Write("/", BoxedTextColor.Punctuation); output.WriteLine("await", BoxedTextColor.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.Write(IdentifierEscaper.Escape(v.Name), v, DecompilerReferenceFlags.Local | DecompilerReferenceFlags.Definition, v.IsParameter ? BoxedTextColor.Parameter : BoxedTextColor.Local); if (v.Type != null) { output.Write(" ", BoxedTextColor.Text); output.Write(":", BoxedTextColor.Punctuation); output.Write(" ", BoxedTextColor.Text); if (v.IsPinned) { output.Write("pinned", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.GeneratedByDecompiler) { output.Write(" ", BoxedTextColor.Text); output.Write("[", BoxedTextColor.Punctuation); output.Write("generated", BoxedTextColor.Keyword); output.Write("]", BoxedTextColor.Punctuation); } output.WriteLine(); } var builder = new MethodDebugInfoBuilder(method); foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, builder); if (!node.WritesNewLine) output.WriteLine(); } output.AddDebugInfo(builder.Create()); EndKeywordBlock(output); }
public override void Decompile(MethodDef method, IDecompilerOutput output, DecompilationContext ctx) { WriteCommentBegin(output, true); output.Write("Method: ", BoxedTextColor.Comment); output.Write(IdentifierEscaper.Escape(method.FullName), method, DecompilerReferenceFlags.Definition, BoxedTextColor.Comment); WriteCommentEnd(output, true); output.WriteLine(); if (!method.HasBody) { return; } var bodyInfo = StartKeywordBlock(output, ".body", method); ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(CodeBracesRangeFlags.MethodBraces); DecompilerContext context = new DecompilerContext(settingsVersion, method.Module, MetadataTextColorProvider) { CurrentType = method.DeclaringType, CurrentMethod = method, CalculateILSpans = ctx.CalculateILSpans, }; ilMethod.Body = astBuilder.Build(method, inlineVariables, context); var stateMachineKind = StateMachineKind.None; MethodDef? inlinedMethod = null; AsyncMethodDebugInfo?asyncInfo = null; string? compilerName = null; if (!(abortBeforeStep is null)) { var optimizer = new ILAstOptimizer(); optimizer.Optimize(context, ilMethod, out stateMachineKind, out inlinedMethod, out asyncInfo, abortBeforeStep.Value); compilerName = optimizer.CompilerName; } if (context.CurrentMethodIsYieldReturn) { output.Write("yield", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); output.WriteLine("return", BoxedTextColor.Keyword); } if (context.CurrentMethodIsAsync) { output.Write("async", BoxedTextColor.Keyword); output.Write("/", BoxedTextColor.Punctuation); output.WriteLine("await", BoxedTextColor.Keyword); } var allVariables = ilMethod.GetSelfAndChildrenRecursive <ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => !(v is null) && !v.IsParameter).Distinct(); foreach (ILVariable v in allVariables) { output.Write(IdentifierEscaper.Escape(v.Name), v.GetTextReferenceObject(), DecompilerReferenceFlags.Local | DecompilerReferenceFlags.Definition, v.IsParameter ? BoxedTextColor.Parameter : BoxedTextColor.Local); if (!(v.Type is null)) { output.Write(" ", BoxedTextColor.Text); output.Write(":", BoxedTextColor.Punctuation); output.Write(" ", BoxedTextColor.Text); if (v.IsPinned) { output.Write("pinned", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.GeneratedByDecompiler) { output.Write(" ", BoxedTextColor.Text); var start = output.NextPosition; output.Write("[", BoxedTextColor.Punctuation); output.Write("generated", BoxedTextColor.Keyword); var end = output.NextPosition; output.Write("]", BoxedTextColor.Punctuation); output.AddBracePair(new TextSpan(start, 1), new TextSpan(end, 1), CodeBracesRangeFlags.SquareBrackets); } output.WriteLine(); } var localVariables = new HashSet <ILVariable>(GetVariables(ilMethod)); var builder = new MethodDebugInfoBuilder(settingsVersion, stateMachineKind, inlinedMethod ?? method, !(inlinedMethod is null) ? method : null, CreateSourceLocals(localVariables), CreateSourceParameters(localVariables), asyncInfo); builder.CompilerName = compilerName; foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, builder); if (!node.WritesNewLine) { output.WriteLine(); } } output.AddDebugInfo(builder.Create()); EndKeywordBlock(output, bodyInfo, CodeBracesRangeFlags.MethodBraces, addLineSeparator: true); }
public void Return(ILAstBuilder builder) { ilAstBuilderPool.Free(builder); }
public void WalkMethod(MethodReference methodReference, TypeReference targetType = null, bool virt = false) { if (!AddMethod(methodReference, targetType, virt)) { return; } var method = methodReference.Resolve(); var context = new DecompilerContext(method.Module) { Settings = { AnonymousMethods = true, AsyncAwait = false, YieldReturn = false, QueryExpressions = false, LockStatement = false, FullyQualifyAmbiguousTypeNames = true, ForEachStatement = false, ExpressionTrees = false, ObjectOrCollectionInitializers = false, }, CurrentModule = method.Module, CurrentMethod = method, CurrentType = method.DeclaringType }; List <Instruction> foundInstructions = (from instruction in method.Body.Instructions where method.HasBody && method.Body.Instructions != null && instruction.Operand != null select instruction).ToList(); IEnumerable <TypeReference> typesFound = from instruction in foundInstructions let tRef = instruction.Operand as TypeReference where tRef != null select tRef; IEnumerable <FieldReference> fieldsFound = from instruction in foundInstructions let fRef = instruction.Operand as FieldReference where fRef != null && fRef.FieldType != null select fRef; foreach (TypeReference typeDefinition in typesFound) { AddType(typeDefinition); } foreach (FieldReference fieldDefinition in fieldsFound) { AddField(fieldDefinition); } ILBlock ilb = null; bool useSimpleMethodWalk = Configuration.NonAggressiveVirtualMethodElimination; if (!useSimpleMethodWalk) { var virtCalls = from instruction in foundInstructions let mRef = instruction.Operand as MethodReference where (instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Ldvirtftn) && mRef.Resolve().IsVirtual select instruction; if (virtCalls.Any()) { try { var decompiler = new ILAstBuilder(); var optimizer = new ILAstOptimizer(); ilb = new ILBlock(decompiler.Build(method, false, context)); optimizer.Optimize(context, ilb); } catch (Exception) { useSimpleMethodWalk = true; } } else { useSimpleMethodWalk = true; } } if (!useSimpleMethodWalk) { var expressions = ilb.GetSelfAndChildrenRecursive <ILExpression>(); foreach (var ilExpression in expressions) { var mRef = ilExpression.Operand as MethodReference; if (mRef != null && mRef.DeclaringType != null) { bool isVirtual = false; TypeReference thisArg = null; switch (ilExpression.Code) { case ILCode.Ldftn: case ILCode.Newobj: case ILCode.Jmp: case ILCode.Call: case ILCode.CallGetter: case ILCode.CallSetter: break; case ILCode.CallvirtGetter: case ILCode.CallvirtSetter: case ILCode.Callvirt: case ILCode.Ldvirtftn: isVirtual = true; thisArg = ilExpression.Arguments.Count > 0 ? ilExpression.Arguments[0].InferredType : null; break; case ILCode.Ldtoken: isVirtual = true; break; } WalkMethod(mRef, thisArg, isVirtual); } } } else { IEnumerable <MethodReference> methodsFound = from instruction in foundInstructions let mRef = instruction.Operand as MethodReference where mRef != null && mRef.DeclaringType != null select mRef; foreach (MethodReference methodDefinition in methodsFound) { if (methodDefinition != method) { WalkMethod(methodDefinition, null, true); } } } }
public void WalkMethod(MethodReference methodReference, TypeReference targetType = null, bool virt = false) { if (!AddMethod(methodReference, targetType, virt)) { return; } var method = methodReference.Resolve(); var context = new DecompilerContext(method.Module) { Settings = { AnonymousMethods = true, AsyncAwait = false, YieldReturn = false, QueryExpressions = false, LockStatement = false, FullyQualifyAmbiguousTypeNames = true, ForEachStatement = false, ExpressionTrees = false, ObjectOrCollectionInitializers = false, }, CurrentModule = method.Module, CurrentMethod = method, CurrentType = method.DeclaringType }; List<Instruction> foundInstructions = (from instruction in method.Body.Instructions where method.HasBody && method.Body.Instructions != null && instruction.Operand != null select instruction).ToList(); IEnumerable<TypeReference> typesFound = from instruction in foundInstructions let tRef = instruction.Operand as TypeReference where tRef != null select tRef; IEnumerable<FieldReference> fieldsFound = from instruction in foundInstructions let fRef = instruction.Operand as FieldReference where fRef != null && fRef.FieldType != null select fRef; foreach (TypeReference typeDefinition in typesFound) { AddType(typeDefinition); } foreach (FieldReference fieldDefinition in fieldsFound) { AddField(fieldDefinition); } ILBlock ilb = null; bool useSimpleMethodWalk = Configuration.NonAggressiveVirtualMethodElimination; if (!useSimpleMethodWalk) { var virtCalls = from instruction in foundInstructions let mRef = instruction.Operand as MethodReference where (instruction.OpCode == OpCodes.Callvirt || instruction.OpCode == OpCodes.Ldvirtftn) && mRef.Resolve().IsVirtual select instruction; if (virtCalls.Any()) { try { var decompiler = new ILAstBuilder(); var optimizer = new ILAstOptimizer(); ilb = new ILBlock(decompiler.Build(method, false, context)); optimizer.Optimize(context, ilb); } catch (Exception) { useSimpleMethodWalk = true; } } else { useSimpleMethodWalk = true; } } if (!useSimpleMethodWalk) { var expressions = ilb.GetSelfAndChildrenRecursive<ILExpression>(); foreach (var ilExpression in expressions) { var mRef = ilExpression.Operand as MethodReference; if (mRef != null && mRef.DeclaringType != null) { bool isVirtual = false; TypeReference thisArg = null; switch (ilExpression.Code) { case ILCode.Ldftn: case ILCode.Newobj: case ILCode.Jmp: case ILCode.Call: case ILCode.CallGetter: case ILCode.CallSetter: break; case ILCode.CallvirtGetter: case ILCode.CallvirtSetter: case ILCode.Callvirt: case ILCode.Ldvirtftn: isVirtual = true; thisArg = ilExpression.Arguments.Count >0 ? ilExpression.Arguments[0].InferredType : null; break; case ILCode.Ldtoken: isVirtual = true; break; } WalkMethod(mRef, thisArg, isVirtual); } } } else { IEnumerable<MethodReference> methodsFound = from instruction in foundInstructions let mRef = instruction.Operand as MethodReference where mRef != null && mRef.DeclaringType != null select mRef; foreach (MethodReference methodDefinition in methodsFound) { if (methodDefinition != method) { WalkMethod(methodDefinition, null, true); } } } }
internal JSFunctionExpression TranslateMethodExpression(DecompilerContext context, MethodReference method, MethodDefinition methodDef) { var oldMethod = context.CurrentMethod; try { if (method == null) throw new ArgumentNullException("method"); if (methodDef == null) throw new ArgumentNullException("methodDef"); var methodInfo = TypeInfoProvider.GetMemberInformation<JSIL.Internal.MethodInfo>(methodDef); var identifier = new QualifiedMemberIdentifier( methodInfo.DeclaringType.Identifier, methodInfo.Identifier ); JSFunctionExpression function = null; if (FunctionCache.TryGetExpression(identifier, out function)) return function; if (methodInfo.IsExternal) { FunctionCache.CreateNull(methodInfo, method, identifier); return null; } var bodyDef = methodDef; if (methodInfo.IsFromProxy && methodInfo.Member.HasBody) bodyDef = methodInfo.Member; var pr = new ProgressReporter(); context.CurrentMethod = methodDef; if ((methodDef.Body.Instructions.Count > LargeMethodThreshold) && (this.DecompilingMethod != null)) this.DecompilingMethod(method.FullName, pr); ILBlock ilb; var decompiler = new ILAstBuilder(); var optimizer = new ILAstOptimizer(); try { ilb = new ILBlock(decompiler.Build(bodyDef, true)); optimizer.Optimize(context, ilb); } catch (Exception exception) { if (CouldNotDecompileMethod != null) CouldNotDecompileMethod(bodyDef.FullName, exception); FunctionCache.CreateNull(methodInfo, method, identifier); pr.OnFinished(); return null; } var allVariables = ilb.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); foreach (var v in allVariables) { if (ILBlockTranslator.IsIgnoredType(v.Type)) { FunctionCache.CreateNull(methodInfo, method, identifier); pr.OnFinished(); return null; } } NameVariables.AssignNamesToVariables(context, decompiler.Parameters, allVariables, ilb); var translator = new ILBlockTranslator( this, context, method, methodDef, ilb, decompiler.Parameters, allVariables ); var body = translator.Translate(); if (body == null) { FunctionCache.CreateNull(methodInfo, method, identifier); pr.OnFinished(); return null; } var parameters = from p in translator.ParameterNames select translator.Variables[p]; if (method.HasGenericParameters) { var type = new TypeReference("System", "Type", context.CurrentModule.TypeSystem.Object.Module, context.CurrentModule.TypeSystem.Object.Scope); parameters = (from gp in method.GenericParameters select new JSVariable(gp.Name, type, method)).Concat(parameters); } function = FunctionCache.Create( methodInfo, methodDef, method, identifier, translator, parameters, body ); pr.OnFinished(); return function; } finally { context.CurrentMethod = oldMethod; } }
BlockStatement CreateMethodBody(IEnumerable<ParameterDeclaration> parameters, out MemberMapping mm) { if (methodDef.Body == null) { mm = null; return null; } context.CancellationToken.ThrowIfCancellationRequested(); ILBlock ilMethod = new ILBlock(); ILAstBuilder astBuilder = new ILAstBuilder(); ilMethod.Body = astBuilder.Build(methodDef, true, context); context.CancellationToken.ThrowIfCancellationRequested(); ILAstOptimizer bodyGraph = new ILAstOptimizer(); bodyGraph.Optimize(context, ilMethod); context.CancellationToken.ThrowIfCancellationRequested(); var localVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => v != null && !v.IsParameter).Distinct(); Debug.Assert(context.CurrentMethod == methodDef); NameVariables.AssignNamesToVariables(context, astBuilder.Parameters, localVariables, ilMethod); if (parameters != null) { foreach (var pair in (from p in parameters join v in astBuilder.Parameters on p.Annotation<Parameter>() equals v.OriginalParameter select new { p, v.Name })) { pair.p.NameToken = Identifier.Create(pair.Name).WithAnnotation(TextTokenType.Parameter); } } context.CancellationToken.ThrowIfCancellationRequested(); Ast.BlockStatement astBlock = TransformBlock(ilMethod); CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments Statement insertionPoint = astBlock.Statements.FirstOrDefault(); foreach (ILVariable v in localVariablesToDefine) { AstType type; if (v.Type.ContainsAnonymousType()) type = new SimpleType("var").WithAnnotation(TextTokenType.Keyword); else type = AstBuilder.ConvertType(v.Type); var newVarDecl = new VariableDeclarationStatement(v.IsParameter ? TextTokenType.Parameter : TextTokenType.Local, type, v.Name); newVarDecl.Variables.Single().AddAnnotation(v); astBlock.Statements.InsertBefore(insertionPoint, newVarDecl); } mm = new MemberMapping(methodDef) { LocalVariables = localVariables.ToList() }; return astBlock; }
public bool RemoveDeadCode(MethodDef method, List <Instruction> dead) { ILAstBuilder astBuilder = new ILAstBuilder(); bool inlineVariables = true; if (!method.HasBody) { return(false); } DecompilerContext context = new DecompilerContext(method.Module) { CurrentType = method.DeclaringType, CurrentMethod = method }; try { ILMethod.Body = astBuilder.Build(method, inlineVariables, context); } catch (Exception ex) { if (DeFlowSettings.Settings.Logs) { OutputLog.Instance.WriteLine("Failed to de-obfuscate method: " + method.MDToken.Raw.ToString()); } return(false); } Instructions = method.Body.Instructions.Where(x => x.OpCode.Code != Code.Constrained).ToList(); foreach (ILNode node in ILMethod.Body) { GetNodes(node); } if (ILNodes.Count != method.Body.Instructions.Count() + ILNodes.Where(x => x is ILLabel).Count() + ILNodes.Where(x => x is string && (x as string) != "pop" && (x as string) != "prefix").Count() + ILNodes.Where(x => x is ILExpression && IsReAssign(x as ILExpression)).Count()) { if (DeFlowSettings.Settings.Logs) { OutputLog.Instance.WriteLine("ilNodes is wrong: " + string.Format("0x{0:X8}", method.MDToken.Raw)); } return(false); } var entries = CreateILEntries(); var exprs = entries.Where(x => x.Node is ILExpression && (x.Node as ILExpression).Operand != null && (x.Node as ILExpression).Operand is ILVariable).ToList(); var catchs = ILNodes.Where(y => y is string && (y as string).Contains("catch")); var rets = entries.Where(x => x.Instr != null && x.Instr.OpCode.Code == Code.Ret); SetILEntriesRefs(entries, exprs); bool modified; do { modified = false; var unused = exprs.Where(x => x.Targets == null || x.Targets.All(y => y.Instr != null && y.Instr.OpCode == OpCodes.Pop)).ToList(); foreach (var expr in unused) { if (expr.Instr != null) { // If its func call without returned value, we cant delete it. if (!CallInstruction(expr.Instr.OpCode.Code)) { // If its func call with returned value we dont want to delete this returned value too even if its unused. if (!(expr.Sources != null && expr.Sources.Any(x => CallInstruction(x.Instr.OpCode.Code)))) { // Exception Variable if (!(expr.Node as ILExpression).Arguments.Any(x => x.Operand is ILVariable && catchs.Any(y => (y as string).Contains((x.Operand as ILVariable).Name)))) { // Dups List <ILEntry> path = new List <ILEntry>(); if (!(expr.Instr.OpCode.Code != Code.Dup && CheckDupSources(expr, path))) { modified = true; dead.Add(expr.Instr); foreach (var source in exprs.Where(x => x.Targets != null && x.Targets.Any(y => y == expr)).ToList()) { source.Targets = source.Targets.Where(x => x != expr).ToList(); } exprs.Remove(expr); if (expr.Targets != null) { foreach (var pop in expr.Targets) { dead.Add(pop.Instr); exprs.Remove(pop); } } } } } } } } }while (modified); return(true); }