public static void RunStep1(DecompilerContext context, ILBlock method, List<ILExpression> listExpr, List<ILBlock> listBlock, Dictionary<ILLabel, int> labelRefCount) { if (!context.Settings.AsyncAwait) return; // abort if async decompilation is disabled var yrd = new AsyncDecompiler(); yrd.context = context; if (!yrd.MatchTaskCreationPattern(method)) return; #if DEBUG if (Debugger.IsAttached) { yrd.Run(); } else { #endif try { yrd.Run(); } catch (SymbolicAnalysisFailedException) { return; } #if DEBUG } #endif context.CurrentMethodIsAsync = true; method.Body.Clear(); method.EntryGoto = null; method.Body.AddRange(yrd.newTopLevelBody);//TODO: Make sure that the removed ILRanges from Clear() above is saved in the new body ILAstOptimizer.RemoveRedundantCode(context, method, listExpr, listBlock, labelRefCount); }
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 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; }
public static void RunStep2(DecompilerContext context, ILBlock method, List<ILExpression> listExpr, List<ILBlock> listBlock, Dictionary<ILLabel, int> labelRefCount, List<ILNode> list_ILNode, Func<ILBlock, ILInlining> getILInlining) { if (context.CurrentMethodIsAsync) { Step2(method.Body); ILAstOptimizer.RemoveRedundantCode(context, method, listExpr, listBlock, labelRefCount); // Repeat the inlining/copy propagation optimization because the conversion of field access // to local variables can open up additional inlining possibilities. ILInlining inlining = getILInlining(method); inlining.InlineAllVariables(); inlining.CopyPropagation(list_ILNode); } }
public static void RunStep2(DecompilerContext context, ILBlock method) { if (context.CurrentMethodIsAsync) { Step2(method.Body); ILAstOptimizer.RemoveRedundantCode(method); // Repeat the inlining/copy propagation optimization because the conversion of field access // to local variables can open up additional inlining possibilities. ILInlining inlining = new ILInlining(method); inlining.InlineAllVariables(); inlining.CopyPropagation(); } }
/// <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 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 static void RunStep1(DecompilerContext context, ILBlock method) { if (!context.Settings.AsyncAwait) { return; // abort if async decompilation is disabled } var yrd = new AsyncDecompiler(); yrd.context = context; if (!yrd.MatchTaskCreationPattern(method)) { return; } #if DEBUG if (Debugger.IsAttached) { yrd.Run(); } else { #endif try { yrd.Run(); } catch (SymbolicAnalysisFailedException) { return; } #if DEBUG } #endif context.CurrentMethodIsAsync = true; method.Body.Clear(); method.EntryGoto = null; method.Body.AddRange(yrd.newTopLevelBody); ILAstOptimizer.RemoveRedundantCode(method); }
/// <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; }
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 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; } }
public void Return(ILAstOptimizer opt) { ilAstOptimizerPool.Free(opt); }