示例#1
0
		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);
		}
示例#2
0
		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;
		}
示例#3
0
		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;
		}
示例#4
0
		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);
        }
示例#7
0
        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;
        }
示例#8
0
		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);
        }
示例#10
0
		/// <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;
		}
示例#11
0
		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;
		}
示例#12
0
        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);
                    }
                }
            }
        }
示例#13
0
        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;
            }
        }
示例#14
0
 public void Return(ILAstOptimizer opt)
 {
     ilAstOptimizerPool.Free(opt);
 }