Example #1
0
		public static void Run(DecompilerContext context, ILBlock method)
		{
			if (!context.Settings.YieldReturn)
				return; // abort if enumerator decompilation is disabled
			var yrd = new YieldReturnDecompiler();
			yrd.context = context;
			if (!yrd.MatchEnumeratorCreationPattern(method))
				return;
			yrd.enumeratorType = yrd.enumeratorCtor.DeclaringType;
			#if DEBUG
			if (Debugger.IsAttached) {
				yrd.Run();
			} else {
				#endif
				try {
					yrd.Run();
				} catch (SymbolicAnalysisFailedException) {
					return;
				}
				#if DEBUG
			}
			#endif
			method.Body.Clear();
			method.EntryGoto = null;
			method.Body.AddRange(yrd.newBody);
			
			// 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();
		}
Example #2
0
		public static void Run(DecompilerContext context, ILBlock method)
		{
			if (!context.Settings.YieldReturn)
				return; // abort if enumerator decompilation is disabled
			var yrd = new YieldReturnDecompiler();
			yrd.context = context;
			if (!yrd.MatchEnumeratorCreationPattern(method))
				return;
			yrd.enumeratorType = yrd.enumeratorCtor.DeclaringType;
			#if DEBUG
			if (Debugger.IsAttached) {
				yrd.Run();
			} else {
				#endif
				try {
					yrd.Run();
				} catch (YieldAnalysisFailedException) {
					return;
				}
				#if DEBUG
			}
			#endif
			method.Body.Clear();
			method.EntryGoto = null;
			method.Body.AddRange(yrd.newBody);
		}
Example #3
0
		public void RemoveGotos(ILBlock method)
		{
			// Build the navigation data
			parent[method] = null;
			foreach (ILNode node in method.GetSelfAndChildrenRecursive<ILNode>()) {
				ILNode previousChild = null;
				foreach (ILNode child in node.GetChildren()) {
					if (parent.ContainsKey(child))
						throw new Exception("The following expression is linked from several locations: " + child.ToString());
					parent[child] = node;
					if (previousChild != null)
						nextSibling[previousChild] = child;
					previousChild = child;
				}
				if (previousChild != null)
					nextSibling[previousChild] = null;
			}
			
			// Simplify gotos
			bool modified;
			do {
				modified = false;
				foreach (ILExpression gotoExpr in method.GetSelfAndChildrenRecursive<ILExpression>(e => e.Code == ILCode.Br || e.Code == ILCode.Leave)) {
					modified |= TrySimplifyGoto(gotoExpr);
				}
			} while(modified);
			
			RemoveRedundantCode(method);
		}
Example #4
0
		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);
		}
Example #5
0
        public ILBlockTranslator(AssemblyTranslator translator, DecompilerContext context, MethodReference methodReference, MethodDefinition methodDefinition, ILBlock ilb, IEnumerable<ILVariable> parameters, IEnumerable<ILVariable> allVariables)
        {
            Translator = translator;
            Context = context;
            ThisMethodReference = methodReference;
            ThisMethod = methodDefinition;
            Block = ilb;

            SpecialIdentifiers = new JSIL.SpecialIdentifiers(TypeSystem);

            if (methodReference.HasThis)
                Variables.Add("this", JSThisParameter.New(methodReference.DeclaringType, methodReference));

            foreach (var parameter in parameters) {
                if ((parameter.Name == "this") && (parameter.OriginalParameter.Index == -1))
                    continue;

                ParameterNames.Add(parameter.Name);
                Variables.Add(parameter.Name, new JSParameter(parameter.Name, parameter.Type, methodReference));
            }

            foreach (var variable in allVariables) {
                var v = JSVariable.New(variable, methodReference);
                if (Variables.ContainsKey(v.Identifier)) {
                    v = new JSVariable(variable.OriginalVariable.Name, variable.Type, methodReference);
                    RenamedVariables[variable] = v;
                    Variables.Add(v.Identifier, v);
                } else {
                    Variables.Add(v.Identifier, v);
                }
            }
        }
Example #6
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;
		}
Example #7
0
		public static void Run(DecompilerContext context, ILBlock method, List<ILNode> list_ILNode, Func<ILBlock, ILInlining> getILInlining)
		{
			if (!context.Settings.YieldReturn)
				return; // abort if enumerator decompilation is disabled
			var yrd = new YieldReturnDecompiler();
			yrd.context = context;
			if (!yrd.MatchEnumeratorCreationPattern(method))
				return;
			yrd.enumeratorType = yrd.enumeratorCtor.DeclaringType;
			#if DEBUG && CRASH_IN_DEBUG_MODE
			if (Debugger.IsAttached) {
				yrd.Run();
			} else {
				#endif
				try {
					yrd.Run();
				} catch (SymbolicAnalysisFailedException) {
					return;
				}
				#if DEBUG && CRASH_IN_DEBUG_MODE
			}
			#endif
			method.Body.Clear();
			method.EntryGoto = null;
			method.Body.AddRange(yrd.newBody);//TODO: Make sure that the removed ILRanges from Clear() above is saved in the new body
			
			// Repeat the inlining/copy propagation optimization because the conversion of field access
			// to local variables can open up additional inlining possibilities.
			var inlining = getILInlining(method);
			inlining.InlineAllVariables();
			inlining.CopyPropagation(list_ILNode);
		}
Example #8
0
        public void Optimize(ILBlock method)
        {
            foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().ToList()) {
                SplitToMovableBlocks(block);
            }

            foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().Where(b => !(b is ILMoveableBlock)).ToList()) {
                ControlFlowGraph graph;
                graph = BuildGraph(block.Body, block.EntryPoint);
                graph.ComputeDominance();
                graph.ComputeDominanceFrontier();
                block.Body = FindLoops(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint, true);
            }

            foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>().Where(b => !(b is ILMoveableBlock)).ToList()) {
                ControlFlowGraph graph;
                graph = BuildGraph(block.Body, block.EntryPoint);
                graph.ComputeDominance();
                graph.ComputeDominanceFrontier();
                block.Body = FindConditions(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint);
            }

            // OrderNodes(method);
            FlattenNestedMovableBlocks(method);
            SimpleGotoRemoval(method);
            RemoveDeadLabels(method);
        }
Example #9
0
		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();
			}
		}
Example #10
0
    protected override ILBlock VisitBlock(ILBlock block)
    {
        currentScope++;

        var result = base.VisitBlock(block);

        currentScope--;

        if (block.Body.Count == 0)
            return result;

        var toOffset = block.LastILOffset();

        if (toOffset < 0)
            return result;

        foreach (var start in starts.Where(kvp => kvp.Key.Item2 == currentScope + 1).ToList())
        {
            starts.Remove(start.Key);

            List<ILExpression> args;
            if (block.Body.Last().Match(ILCode.Ret, out args) && args.Count == 1 && args[0].MatchLdloc(start.Key.Item1))
                continue; // Returning the variable

            UsingRanges.Add(new ILRange { From = start.Value, To = toOffset });
        }

        return result;
    }
        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();

            NameVariables.AssignNamesToVariables(methodDef.Parameters.Select(p => p.Name), astBuilder.Variables, 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;
        }
Example #12
0
		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);
		}
Example #13
0
		/// <summary>
		/// Inlines the stloc instruction at block.Body[pos] into the next instruction, if possible.
		/// </summary>
		public static bool InlineIfPossible(ILBlock block, int pos, ILBlock method)
		{
			if (InlineIfPossible((ILExpression)block.Body[pos], block.Body.ElementAtOrDefault(pos+1), method)) {
				block.Body.RemoveAt(pos);
				return true;
			}
			return false;
		}
Example #14
0
 public static void AssignNamesToVariables(IEnumerable<string> existingNames, IEnumerable<ILVariable> variables, ILBlock methodBody)
 {
     NameVariables nv = new NameVariables();
     nv.AddExistingNames(existingNames);
     foreach (ILVariable varDef in variables) {
         nv.AssignNameToVariable(varDef, methodBody.GetSelfAndChildrenRecursive<ILExpression>());
     }
 }
		public void FindConditions(ILBlock block)
		{
			if (block.Body.Count > 0) {
				ControlFlowGraph graph;
				graph = BuildGraph(block.Body, (ILLabel)block.EntryGoto.Operand);
				graph.ComputeDominance(context.CancellationToken);
				graph.ComputeDominanceFrontier();
				block.Body = FindConditions(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint);
			}
		}
Example #16
0
 public static void Run(DecompilerContext context, ILBlock method)
 {
     TypeAnalysis ta = new TypeAnalysis();
     ta.context = context;
     ta.module = context.CurrentMethod.Module;
     ta.typeSystem = ta.module.TypeSystem;
     ta.method = method;
     ta.InferTypes(method);
     ta.InferRemainingStores();
 }
Example #17
0
		Ast.BlockStatement TransformBlock(ILBlock block)
		{
			Ast.BlockStatement astBlock = new BlockStatement();
			if (block != null) {
				foreach(ILNode node in block.GetChildren()) {
					astBlock.AddRange(TransformNode(node));
				}
			}
			return astBlock;
		}
		public void FindLoops(ILBlock block)
		{
			if (block.Body.Count > 0) {
				ControlFlowGraph graph;
				graph = BuildGraph(block.Body, (ILLabel)block.EntryGoto.Operand);
				graph.ComputeDominance(context.VerifyProgress);
				graph.ComputeDominanceFrontier();
				block.Body = FindLoops(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint, false);
			}
		}
Example #19
0
        public BlockStatement CreateMethodBody()
        {
            if (methodDef.Body == null) return null;

            ILBlock ilMethod = new ILBlock();
            ILAstBuilder astBuilder = new ILAstBuilder();
            ilMethod.Body = astBuilder.Build(methodDef, true);

            ILAstOptimizer bodyGraph = new ILAstOptimizer();
            bodyGraph.Optimize(ilMethod);

            List<string> intNames = new List<string>(new string[] {"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"});
            Dictionary<string, int> typeNames = new Dictionary<string, int>();
            foreach(ILVariable varDef in astBuilder.Variables) {
                if (varDef.Type.FullName == Constants.Int32 && intNames.Count > 0) {
                    varDef.Name = intNames[0];
                    intNames.RemoveAt(0);
                } else {
                    string name;
                    if (varDef.Type.IsArray) {
                        name = "array";
                    } else if (!typeNameToVariableNameDict.TryGetValue(varDef.Type.FullName, out name)) {
                        name = varDef.Type.Name;
                        // remove the 'I' for interfaces
                        if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2]))
                            name = name.Substring(1);
                        // remove the backtick (generics)
                        int pos = name.IndexOf('`');
                        if (pos >= 0)
                            name = name.Substring(0, pos);
                        if (name.Length == 0)
                            name = "obj";
                        else
                            name = char.ToLower(name[0]) + name.Substring(1);
                    }
                    if (!typeNames.ContainsKey(name)) {
                        typeNames.Add(name, 0);
                    }
                    int count = ++(typeNames[name]);
                    if (count > 1) {
                        name += count.ToString();
                    }
                    varDef.Name = name;
                }

            //				Ast.VariableDeclaration astVar = new Ast.VariableDeclaration(varDef.Name);
            //				Ast.LocalVariableDeclaration astLocalVar = new Ast.LocalVariableDeclaration(astVar);
            //				astLocalVar.TypeReference = new Ast.TypeReference(varDef.VariableType.FullName);
            //				astBlock.Children.Add(astLocalVar);
            }

            Ast.BlockStatement astBlock = TransformBlock(ilMethod);
            CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments
            return astBlock;
        }
        public static void Transform(ILBlock method)
        {
            // TODO: move this somewhere else
            // Eliminate 'dups':
            foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
                for (int i = 0; i < expr.Arguments.Count; i++) {
                    if (expr.Arguments[i].Code == ILCode.Dup)
                        expr.Arguments[i] = expr.Arguments[i].Arguments[0];
                }
            }

            var newArrPattern = new StoreToVariable(new ILExpression(ILCode.Newarr, ILExpression.AnyOperand, new ILExpression(ILCode.Ldc_I4, ILExpression.AnyOperand)));
            var arg1 = new StoreToVariable(new LoadFromVariable(newArrPattern)) { MustBeGenerated = true };
            var arg2 = new StoreToVariable(new LoadFromVariable(newArrPattern)) { MustBeGenerated = true };
            var initializeArrayPattern = new ILCall(
                "System.Runtime.CompilerServices.RuntimeHelpers", "InitializeArray",
                new LoadFromVariable(arg1), new ILExpression(ILCode.Ldtoken, ILExpression.AnyOperand));
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
                for (int i = block.Body.Count - 1; i >= 0; i--) {
                    if (!newArrPattern.Match(block.Body[i]))
                        continue;
                    ILExpression newArrInst = ((ILExpression)block.Body[i]).Arguments[0];
                    int arrayLength = (int)newArrInst.Arguments[0].Operand;
                    if (arrayLength == 0)
                        continue;
                    if (arg1.Match(block.Body.ElementAtOrDefault(i + 1)) && arg2.Match(block.Body.ElementAtOrDefault(i + 2))) {
                        if (initializeArrayPattern.Match(block.Body.ElementAtOrDefault(i + 3))) {
                            if (HandleStaticallyInitializedArray(arg2, block, i, newArrInst, arrayLength)) {
                                i -= ILInlining.InlineInto(block, i + 1, method) - 1;
                            }
                            continue;
                        }
                    }
                    if (i + 1 + arrayLength > block.Body.Count)
                        continue;
                    List<ILExpression> operands = new List<ILExpression>();
                    for (int j = 0; j < arrayLength; j++) {
                        ILExpression expr = block.Body[i + 1 + j] as ILExpression;
                        if (expr == null || !IsStoreToArray(expr.Code))
                            break;
                        if (!(expr.Arguments[0].Code == ILCode.Ldloc && expr.Arguments[0].Operand == newArrPattern.LastVariable))
                            break;
                        if (!(expr.Arguments[1].Code == ILCode.Ldc_I4 && (int)expr.Arguments[1].Operand == j))
                            break;
                        operands.Add(expr.Arguments[2]);
                    }
                    if (operands.Count == arrayLength) {
                        ((ILExpression)block.Body[i]).Arguments[0] = new ILExpression(
                            ILCode.InitArray, newArrInst.Operand, operands.ToArray());
                        block.Body.RemoveRange(i + 1, arrayLength);
                        i -= ILInlining.InlineInto(block, i + 1, method) - 1;
                    }
                }
            }
        }
Example #21
0
		bool MatchEnumeratorCreationPattern(ILBlock method)
		{
			if (method.Body.Count == 0)
				return false;
			ILExpression newObj;
			if (method.Body.Count == 1) {
				// ret(newobj(...))
				if (method.Body[0].Match(ILCode.Ret, out newObj))
					return MatchEnumeratorCreationNewObj(newObj, out enumeratorCtor);
				else
					return false;
			}
			// stloc(var_1, newobj(..)
			ILVariable var1;
			if (!method.Body[0].Match(ILCode.Stloc, out var1, out newObj))
				return false;
			if (!MatchEnumeratorCreationNewObj(newObj, out enumeratorCtor))
				return false;
			
			int i;
			for (i = 1; i < method.Body.Count; i++) {
				// stfld(..., ldloc(var_1), ldloc(parameter))
				FieldReference storedField;
				ILExpression ldloc, loadParameter;
				if (!method.Body[i].Match(ILCode.Stfld, out storedField, out ldloc, out loadParameter))
					break;
				ILVariable loadedVar, loadedArg;
				if (!ldloc.Match(ILCode.Ldloc, out loadedVar) || !loadParameter.Match(ILCode.Ldloc, out loadedArg))
					return false;
				storedField = GetFieldDefinition(storedField);
				if (loadedVar != var1 || storedField == null || !loadedArg.IsParameter)
					return false;
				fieldToParameterMap[(FieldDefinition)storedField] = loadedArg;
			}
			ILVariable var2;
			ILExpression ldlocForStloc2;
			if (i < method.Body.Count && method.Body[i].Match(ILCode.Stloc, out var2, out ldlocForStloc2)) {
				// stloc(var_2, ldloc(var_1))
				if (ldlocForStloc2.Code != ILCode.Ldloc || ldlocForStloc2.Operand != var1)
					return false;
				i++;
			} else {
				// the compiler might skip the above instruction in release builds; in that case, it directly returns stloc.Operand
				var2 = var1;
			}
			ILExpression retArg;
			if (i < method.Body.Count && method.Body[i].Match(ILCode.Ret, out retArg)) {
				// ret(ldloc(var_2))
				if (retArg.Code == ILCode.Ldloc && retArg.Operand == var2) {
					return true;
				}
			}
			return false;
		}
		public static void Run(DecompilerContext context, ILBlock method)
		{
			TypeAnalysis ta = new TypeAnalysis();
			ta.context = context;
			ta.module = context.CurrentMethod.Module;
			ta.typeSystem = ta.module.TypeSystem;
			ta.method = method;
			ta.CreateDependencyGraph(method);
			ta.IdentifySingleLoadVariables();
			ta.RunInference();
		}
Example #23
0
		public void FindLoops(ILBlock block)
		{
			if (block.Body.Count > 0) {
				ControlFlowGraph graph;
				graph = BuildGraph(block.Body, (ILLabel)block.EntryGoto.Operand);
				graph.ComputeDominance(context.CancellationToken);
				graph.ComputeDominanceFrontier();
				//TODO: Keep ILRanges when writing to Body
				block.Body = FindLoops(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint, false);
			}
		}
Example #24
0
    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;
    }
Example #25
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;
		}
Example #26
0
		Ast.BlockStatement TransformBlock(ILBlock block)
		{
			Ast.BlockStatement astBlock = new BlockStatement();
			if (block != null) {
				if (block.EntryGoto != null)
					astBlock.Add((Statement)TransformExpression(block.EntryGoto));
				foreach(ILNode node in block.Body) {
					astBlock.AddRange(TransformNode(node));
				}
			}
			return astBlock;
		}
Example #27
0
		public static void Run(DecompilerContext context, ILBlock method)
		{
			PeepholeTransforms transforms = new PeepholeTransforms();
			transforms.context = context;
			transforms.method = method;
			
			PeepholeTransform[] blockTransforms = {
				ArrayInitializers.Transform(method),
				transforms.CachedDelegateInitialization
			};
			Func<ILExpression, ILExpression>[] exprTransforms = {
				EliminateDups,
				HandleDecimalConstants
			};
			// Traverse in post order so that nested blocks are transformed first. This is required so that
			// patterns on the parent block can assume that all nested blocks are already transformed.
			foreach (var node in TreeTraversal.PostOrder<ILNode>(method, c => c != null ? c.GetChildren() : null)) {
				ILBlock block = node as ILBlock;
				ILExpression expr;
				if (block != null) {
					// go through the instructions in reverse so that transforms can build up nested structures inside-out
					for (int i = block.Body.Count - 1; i >= 0; i--) {
						context.CancellationToken.ThrowIfCancellationRequested();
						expr = block.Body[i] as ILExpression;
						if (expr != null) {
							// apply expr transforms to top-level expr in block
							foreach (var t in exprTransforms)
								expr = t(expr);
							block.Body[i] = expr;
						}
						// apply block transforms
						foreach (var t in blockTransforms) {
							t(block, ref i);
							Debug.Assert(i <= block.Body.Count && i >= 0);
							if (i == block.Body.Count) // special case: retry all transforms
								break;
						}
					}
				}
				expr = node as ILExpression;
				if (expr != null) {
					// apply expr transforms to all arguments
					for (int i = 0; i < expr.Arguments.Count; i++) {
						ILExpression arg = expr.Arguments[i];
						foreach (var t in exprTransforms)
							arg = t(arg);
						expr.Arguments[i] = arg;
					}
				}
			}
		}
Example #28
0
		/// <summary>
		/// Inlines instructions before pos into block.Body[pos].
		/// </summary>
		/// <returns>The number of instructions that were inlined.</returns>
		public static int InlineInto(ILBlock block, int pos, ILBlock method)
		{
			int count = 0;
			while (--pos >= 0) {
				ILExpression expr = block.Body[pos] as ILExpression;
				if (expr == null || expr.Code != ILCode.Stloc)
					break;
				if (InlineIfPossible(block, pos, method))
					count++;
				else
					break;
			}
			return count;
		}
Example #29
0
		public SimpleControlFlow(DecompilerContext context, ILBlock method)
		{
			this.context = context;
			this.typeSystem = context.CurrentMethod.Module.TypeSystem;
			
			foreach(ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())) {
				labelGlobalRefCount[target] = labelGlobalRefCount.GetOrDefault(target) + 1;
			}
			foreach(ILBasicBlock bb in method.GetSelfAndChildrenRecursive<ILBasicBlock>()) {
				foreach(ILLabel label in bb.GetChildren().OfType<ILLabel>()) {
					labelToBasicBlock[label] = bb;
				}
			}
		}
Example #30
0
		/// <summary>
		/// Inlines 'expr' into 'next', if possible.
		/// </summary>
		public static bool InlineIfPossible(ILExpression expr, ILNode next, ILBlock method)
		{
			if (expr.Code != ILCode.Stloc)
				throw new ArgumentException("expr must be stloc");
			// ensure the variable is accessed only a single time
			if (method.GetSelfAndChildrenRecursive<ILExpression>().Count(e => e != expr && e.Operand == expr.Operand) != 1)
				return false;
			ILExpression parent;
			int pos;
			if (FindLoadInNext(next as ILExpression, (ILVariable)expr.Operand, out parent, out pos) == true) {
				parent.Arguments[pos] = expr.Arguments[0];
				return true;
			}
			return false;
		}
Example #31
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            //Get the ID (i.e. ASM label) of the method to load a pointer to
            Types.MethodInfo methodInfo       = conversionState.TheILLibrary.GetMethodInfo(theOp.MethodToCall);
            string           methodID         = methodInfo.ID;
            bool             addExternalLabel = methodID != conversionState.Input.TheMethodInfo.ID;

            //If we want to load the pointer at a specified IL op number:
            if (theOp.LoadAtILOpAfterOp != null)
            {
                ILBlock anILBlock = conversionState.TheILLibrary.GetILBlock(methodInfo);
                int     index     = anILBlock.ILOps.IndexOf(theOp.LoadAtILOpAfterOp);
                index++;

                methodID = ASM.ASMBlock.GenerateLabel(methodID, anILBlock.PositionOf(anILBlock.ILOps[index]));
            }
            else if (theOp.LoadAtILOffset != int.MaxValue)
            {
                //Append the IL sub-label to the ID
                ILBlock anILBlock = conversionState.TheILLibrary.GetILBlock(methodInfo);
                methodID = ASM.ASMBlock.GenerateLabel(methodID, anILBlock.PositionOf(anILBlock.At(theOp.LoadAtILOffset)));

                //Note: This is used by try/catch/finally blocks for pushing pointers
                //      to catch/finally handlers and filters
            }

            if (addExternalLabel)
            {
                conversionState.AddExternalLabel(methodID);
            }

            //Push the pointer to the function
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Dword, Src = methodID
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isGCManaged        = false
            });
        }
Example #32
0
        internal void Build(ILBlock block)
        {
            var node = block.FirstChild;

            while (node != null)
            {
                switch (node.NodeType)
                {
                case ILNodeType.Block:
                    Build((ILBlock)node);
                    break;

                case ILNodeType.Instruction:
                    Build((ILInstruction)node);
                    break;
                }

                node = node.NextSibling;
            }
        }
Example #33
0
        public void Transform()
        {
            if (this.pipeline == null)
            {
                throw new InvalidOperationException("Transformer already used.");
            }

            foreach (IPostTransform handler in this.pipeline)
            {
                handler.Initialize(this);

                this.RootScope.ProcessBasicBlocks <ILInstrList>(block =>
                {
                    this.Block = (ILBlock)block;
                    handler.Transform(this);
                });
            }

            this.pipeline = null;
        }
Example #34
0
 IEnumerable <ILVariable> GetVariables(ILBlock ilMethod)
 {
     foreach (var n in ilMethod.GetSelfAndChildrenRecursive(new List <ILNode>()))
     {
         var expr = n as ILExpression;
         if (expr != null)
         {
             var v = expr.Operand as ILVariable;
             if (v != null && !v.IsParameter)
             {
                 yield return(v);
             }
             continue;
         }
         var cb = n as ILTryCatchBlock.CatchBlockBase;
         if (cb != null && cb.ExceptionVariable != null)
         {
             yield return(cb.ExceptionVariable);
         }
     }
 }
Example #35
0
            public bool WriteWithLiaison(object target, Interval field_update_interval, object liaison, Buffer buffer)
            {
                if (object_liaison_writer == null)
                {
                    object_liaison_writer = GetTargetType().CreateDynamicMethodDelegateWithForcedParameterTypes <ObjectLiaisonWriter>(delegate(ILValue il_target, ILValue il_field_update_interval, ILValue il_liaison, ILValue il_buffer) {
                        ILBlock block = new ILBlock();

                        ILLocal il_to_return = block.CreateNamedLocal(typeof(bool), "to_return");

                        block.AddStatements(
                            target_serializer_prop_groups
                            .Convert(g => g.GenerateWrite(il_target, il_field_update_interval, type_update_interval, il_liaison, il_to_return, il_buffer))
                            );

                        block.AddStatement(new ILReturn(il_to_return));
                        return(block);
                    }, GetTargetType(), typeof(Interval), GetLiaisonType(), typeof(Buffer));
                }

                return(object_liaison_writer(target, field_update_interval, liaison, buffer));
            }
Example #36
0
        public static bool RunOptimization(this ILBlock block, Func <IList <ILNode>, ILExpression, int, bool> optimization)
        {
            bool modified = false;

            foreach (ILBasicBlock bb in block.Body)
            {
                for (int i = bb.Body.Count - 1; i >= 0; i--)
                {
                    ILExpression expr = bb.Body.ElementAtOrDefault(i) as ILExpression;
                    if (expr != null && optimization(bb.Body, expr, i))
                    {
                        modified = true;
                    }
                }
            }
            if (Context.Debug)
            {
                block.FixParents();
            }
            return(modified);
        }
Example #37
0
 public uint ComputeOffset(ILBlock block, uint offset)
 {
     foreach (var instr in block.Content)
     {
         instr.Offset = offset;
         offset      += 2;
         if (instr.Operand != null)
         {
             if (instr.Operand is ILRegister)
             {
                 offset++;
             }
             else if (instr.Operand is ILImmediate)
             {
                 var value = ((ILImmediate)instr.Operand).Value;
                 if (value is uint || value is int || value is float)
                 {
                     offset += 4;
                 }
                 else if (value is ulong || value is long || value is double)
                 {
                     offset += 8;
                 }
                 else
                 {
                     throw new NotSupportedException();
                 }
             }
             else if (instr.Operand is ILRelReference)
             {
                 offset += 4;
             }
             else
             {
                 throw new NotSupportedException();
             }
         }
     }
     return(offset);
 }
Example #38
0
            protected override ILBlock CreateNewBlock()
            {
                if (Context.Version != UndertaleVersion.V10001)
                {
                    throw new Exception("Cannot compile new code using old");
                }
                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 dblock = new ILBlock();

                dblock.Body = new Dissasembler.NewByteCodeToAst().Build(this, error);
                ILBlock block = new ILAstBuilder().Build(dblock, Locals, error);

                Debug.Assert(block != null);
                block.FixParents();

                return(block);
            }
Example #39
0
        public void Initialize(ILTransformer tr)
        {
            this.trampoline = null;
            tr.RootScope.ProcessBasicBlocks <ILInstrList>(b =>
            {
                if (b.Content.Any(instr => instr.IR != null && instr.IR.Annotation == SMCBlock.AddressPart2))
                {
                    this.trampoline = (ILBlock)b;
                }
            });
            if (this.trampoline == null)
            {
                return;
            }

            CFG.ScopeBlock scope = tr.RootScope.SearchBlock(this.trampoline).Last();
            this.newTrampoline = new SMCBlock(this.trampoline.Id, this.trampoline.Content);
            scope.Content[scope.Content.IndexOf(this.trampoline)] = this.newTrampoline;

            this.adrKey            = tr.VM.Random.Next();
            this.newTrampoline.Key = (byte)tr.VM.Random.Next();
        }
Example #40
0
        public override void Preprocess(ILPreprocessState preprocessState, ILOp theOp)
        {
            Types.MethodInfo methodInfo = preprocessState.TheILLibrary.GetMethodInfo(theOp.MethodToCall);

            if (theOp.LoadAtILOpAfterOp != null)
            {
                ILBlock anILBlock = preprocessState.TheILLibrary.GetILBlock(methodInfo);
                int     index     = anILBlock.ILOps.IndexOf(theOp.LoadAtILOpAfterOp);
                if (index == -1)
                {
                    throw new NullReferenceException("LoadAtILOpAfterOp not found in IL block!");
                }

                index++;
                anILBlock.ILOps[index].LabelRequired = true;
            }
            else if (theOp.LoadAtILOffset != int.MaxValue)
            {
                int  offset      = theOp.LoadAtILOffset;
                ILOp theLoadedOp = preprocessState.TheILLibrary.GetILBlock(methodInfo).At(offset);
                theLoadedOp.LabelRequired = true;
            }
        }
Example #41
0
        void FixIfStatements(ILBlock method)
        {
            bool modified;

            do
            {
                // We have to do this here as we want clean if statments
                // ILSpy does this later when it converts the ILAst to normal Ast, but since were skipping that
                // step, this "should" make if statements a bit cleaner
                modified = false;
                foreach (ILCondition ilCond in method.GetSelfAndChildrenRecursive <ILCondition>())
                {
                    if (ilCond.TrueBlock.Body.Count == 0 && (ilCond.FalseBlock != null && ilCond.FalseBlock.Body.Count != 0))
                    { // If we have an empty true block but stuff in the falls block, negate the condition and swap blocks
                        var swap = ilCond.TrueBlock;
                        ilCond.TrueBlock  = ilCond.FalseBlock;
                        ilCond.FalseBlock = swap;
                        ilCond.Condition  = ilCond.Condition.NegateCondition();
                        modified         |= true;
                    }
                }
            } while (modified);
        }
Example #42
0
        protected void WriteSingleLineOrBlock(ILBlock block)
        {
            ILExpression e = null;

            if (SingleExpressionInBlock(block, out e))
            {
                if (e.ToString().Length + this.Column > 80)
                {
                    WriteLine();
                }
                this.Indent++;
                Write(' ');
                Write(e);
                Write(';');
                this.Indent--;
            }
            else
            {
                WriteLine(" {");
                Write(block, true);
                Write("}");
            }
        }
Example #43
0
        static public FingerPrintOperation CreateFingerPrintOperation(this Type item)
        {
            MethodInfoEX get_hash_code_ex_method = typeof(TypeExtensions_Finger_Create).GetStaticMethod <object>("GetHashCodeEX");

            return(item.CreateDynamicMethodDelegate <FingerPrintOperation>("FingerPrint_" + item.Name, delegate(MethodBase method){
                ILBlock body = new ILBlock();

                ILLocal obj = body.CreateNamedLocal(item, "this", method.GetTechnicalILParameter(0));
                ILLocal hash = body.CreateNamedLocal(typeof(int), "hash", 17);

                foreach (FieldInfo field in item.GetAllInstanceFields())
                {
                    body.AddStatement(
                        new ILAssign(
                            hash,
                            hash * 23 + get_hash_code_ex_method.GetStaticILMethodInvokation(obj.GetILField(field))
                            )
                        );
                }

                body.AddStatement(new ILReturn(hash));
                return body;
            }));
        }
        private void Obfuscate(ILBlock block)
        {
            var node = block.FirstChild;

            while (node != null)
            {
                switch (node.NodeType)
                {
                case ILNodeType.Block:
                {
                    Obfuscate((ILBlock)node);
                }
                break;

                case ILNodeType.Instruction:
                {
                    Obfuscate((ILInstruction)node);
                }
                break;
                }

                node = node.NextSibling;
            }
        }
        private bool Map(ILBlock block)
        {
            bool changed = false;

            var node = block.FirstChild;

            while (node != null)
            {
                switch (node.NodeType)
                {
                case ILNodeType.Block:
                    changed |= Map((ILBlock)node);
                    break;

                case ILNodeType.Instruction:
                    changed |= Map((ILInstruction)node);
                    break;
                }

                node = node.NextSibling;
            }

            return(changed);
        }
Example #46
0
    protected override ILBlock VisitBlock(ILBlock block)
    {
        currentScope++;

        var result = base.VisitBlock(block);

        currentScope--;

        if (block.Body.Count == 0)
        {
            return(result);
        }

        var toOffset = block.LastILOffset();

        if (toOffset < 0)
        {
            return(result);
        }

        foreach (var start in starts.Where(kvp => kvp.Key.Item2 == currentScope + 1).ToList())
        {
            starts.Remove(start.Key);

            List <ILExpression> args;
            if (block.Body.Last().Match(ILCode.Ret, out args) && args.Count == 1 && args[0].MatchLdloc(start.Key.Item1))
            {
                continue; // Returning the variable
            }
            UsingRanges.Add(new ILRange {
                From = start.Value, To = toOffset
            });
        }

        return(result);
    }
Example #47
0
        public ILBlock Build(ILBlock method, Dictionary <string, ILVariable> locals, ErrorContext error)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }
            if (error == null)
            {
                throw new ArgumentNullException("error");
            }
            if (locals == null)
            {
                throw new ArgumentNullException("locals");
            }
            this.error  = error;
            this.locals = locals;
            error.CheckDebugThenSave(method, "raw.txt", true);
            // Not sure I need this pass now
            // WE doo now, This converts popenv to either breaks or branchs.   This is needed
            // as if you return from a pushenv, a popenv break is called
            FixAllPushesAndPopenv(method.Body); // makes sure all pushes have no operands and are all expressions for latter matches


            Optimize.RemoveRedundantCode(method);

            foreach (var block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                Optimize.SplitToBasicBlocks(block, true);
            }
            error.CheckDebugThenSave(method, "basic_blocks.txt");

            bool modified   = false;
            bool debug_once = true;

            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                do
                {
                    modified = false;

                    do     // Does all the internal things to a blocks for other passes to be easyer
                    {
                        modified  = false;
                        modified |= block.RunOptimization(MatchVariablePush);      // checks pushes for instance or indexs for vars
                        modified |= block.RunOptimization(SimpleAssignments);
                        modified |= block.RunOptimization(AssignValueTo);
                        modified |= block.RunOptimization(ComplexAssignments);    // basicly self increment, this SHOULDN'T cross block boundrys
                        modified |= block.RunOptimization(SimplifyBranches);      // Any resolved pushes are put into a branch argument
                        modified |= block.RunOptimization(CombineCall);           // Any resolved pushes are put into a branch argument
                        modified |= block.RunOptimization(CombineExpressions);
                        modified |= block.RunOptimization(FixTempReturnValues);
                    } while (modified);
                    if (Context.Debug)
                    {
                        if (debug_once)
                        {
                            error.CheckDebugThenSave(method, "basic_blocks_resolved.txt"); debug_once = false;
                        }
                    }



                    //  modified |= block.RunOptimization(new SimpleControlFlow(method,error).DetectSwitch);
                    //       modified |= block.RunOptimization(new SimpleControlFlow(method, error).DetectSwitchAndConvertToBranches);
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).DetectSwitch_GenerateSwitch);

                    modified |= block.RunOptimization(MultiDimenionArray);

                    modified |= block.RunOptimization(Optimize.SimplifyBoolTypes);
                    modified |= block.RunOptimization(Optimize.SimplifyLogicNot);

                    modified |= block.RunOptimization(PushEnviromentFix); // match all with's with expressions
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).SimplifyShortCircuit);
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).SimplifyTernaryOperator);
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).MatchRepeatStructure);



                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).JoinBasicBlocks);
                    // somewhere, so bug, is leaving an empty block, I think because of switches
                    // It screws up the flatten block check for some reason
                    modified |= block.RunOptimization(new SimpleControlFlow(method, error).RemoveRedundentBlocks);
                    // want to run this at the end to fix return stuff
                } while (modified);
            }
            error.CheckDebugThenSave(method, "before_loops.txt");
            if (BeforeConditionsDebugSainityCheck(method))
            {
                return(null);                                           // sainity check, evething must be ready for this
            }
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(error).FindLoops(block);
            }

            error.CheckDebugThenSave(method, "before_conditions.txt");

            foreach (ILBlock block in method.GetSelfAndChildrenRecursive <ILBlock>())
            {
                new LoopsAndConditions(error).FindConditions(block);
            }

            error.CheckDebugThenSave(method, "before_flatten.txt");
            FlattenBasicBlocks(method);
            error.CheckDebugThenSave(method, "before_gotos.txt");

            Optimize.RemoveRedundantCode(method);
            new GotoRemoval().RemoveGotos(method);

            error.CheckDebugThenSave(method, "before_if.txt");

            // This is cleaned up in ILSpy latter when its converted to another ast structure, but I clean it up here
            // cause I don't convert it and mabye not converting all bt's to bf's dosn't
            //   FixIfStatements(method);



            Optimize.RemoveRedundantCode(method);
            new GotoRemoval().RemoveGotos(method);

            error.CheckDebugThenSave(method, "final.txt");
            if (AfterLoopsAndConditions(method))
            {
                return(null);                                 // another sanity check
            }
            return(method);
        }
Example #48
0
        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);
        }
Example #49
0
        private List <ILVariable> PreprocessorCheckUninitializedLocalVarsBranch(ILBlock branch, List <ILVariable> initializedVars)
        {
            List <ILVariable> result = new List <ILVariable>(initializedVars);

            foreach (ILNode node in branch.Body)
            {
                if (node is ILExpression)
                {
                    PreprocessorCheckUninitializedLocalVarsExpression((ILExpression)node, result);
                }
                else if (node is ILBlock)
                {
                    result = PreprocessorCheckUninitializedLocalVarsBranch((ILBlock)node, result);
                }
                else if (node is ILTryCatchBlock)
                {
                    ILTryCatchBlock block = (ILTryCatchBlock)node;

                    List <ILVariable> newResult = new List <ILVariable>(result);

                    if (block.TryBlock != null)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(block.TryBlock, result)).ToList();
                    }
                    if (block.FaultBlock != null)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(block.FaultBlock, result)).ToList();
                    }
                    if (block.FinallyBlock != null)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(block.FinallyBlock, result)).ToList();
                    }
                    if (block.CatchBlocks != null)
                    {
                        foreach (ILTryCatchBlock.CatchBlock c in block.CatchBlocks)
                        {
                            newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(c, result)).ToList();
                        }
                    }

                    result = newResult;
                }
                else if (node is ILWhileLoop)
                {
                    PreprocessorCheckUninitializedLocalVarsExpression(((ILWhileLoop)node).Condition, result);
                    result = PreprocessorCheckUninitializedLocalVarsBranch(((ILWhileLoop)node).BodyBlock, result);
                }
                else if (node is ILCondition)
                {
                    ILCondition cond = (ILCondition)node;
                    PreprocessorCheckUninitializedLocalVarsExpression(cond.Condition, result);

                    List <ILVariable> fromTrue  = PreprocessorCheckUninitializedLocalVarsBranch(cond.TrueBlock, result);
                    List <ILVariable> fromFalse = PreprocessorCheckUninitializedLocalVarsBranch(cond.FalseBlock, result);

                    result = fromTrue.Union(fromFalse).ToList();
                }
                else if (node is ILSwitch)
                {
                    ILSwitch sw = (ILSwitch)node;

                    PreprocessorCheckUninitializedLocalVarsExpression(sw.Condition, result);

                    List <ILVariable> newResult = new List <ILVariable>(result);
                    foreach (var cas in sw.CaseBlocks)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(cas, result)).ToList();
                    }
                    result = newResult;
                }
            }

            return(result);
        }
Example #50
0
 public void AddBlock(MethodDef method, ILBlock block)
 {
     basicBlocks.Add(Tuple.Create(method, block));
 }
        Dictionary <int, Action <XamlContext, XElement> > ExtractConnectionId(XamlContext ctx, MethodDef method)
        {
            var context = new DecompilerContext(method.Module)
            {
                CurrentType       = method.DeclaringType,
                CurrentMethod     = method,
                CancellationToken = ctx.CancellationToken
            };
            var body = new ILBlock(new ILAstBuilder().Build(method, true, context));

            new ILAstOptimizer().Optimize(context, body);

            var sw = body.GetSelfAndChildrenRecursive <ILSwitch>().FirstOrDefault();

            if (sw == null)
            {
                return(null);
            }

            var connIds = new Dictionary <int, Action <XamlContext, XElement> >();

            foreach (var cas in sw.CaseBlocks)
            {
                if (cas.Values == null)
                {
                    continue;
                }

                Action <XamlContext, XElement> cb = null;
                foreach (var node in cas.Body)
                {
                    var expr = node as ILExpression;
                    if (expr == null)
                    {
                        continue;
                    }

                    switch (expr.Code)
                    {
                    case ILCode.Stfld:
                        cb += new FieldAssignment {
                            FieldName = ((IField)expr.Operand).Name
                        }.Callback;
                        break;

                    case ILCode.Call:
                    case ILCode.Callvirt:
                        var operand = (IMethod)expr.Operand;
                        if (operand.Name == "AddHandler" && operand.DeclaringType.FullName == "System.Windows.UIElement")
                        {
                            // Attached event
                            var re      = expr.Arguments[1];
                            var ctor    = expr.Arguments[2];
                            var reField = re.Operand as IField;

                            if (re.Code != ILCode.Ldsfld || ctor.Code != ILCode.Newobj ||
                                ctor.Arguments.Count != 2 || ctor.Arguments[1].Code != ILCode.Ldftn)
                            {
                                cb += new Error {
                                    Msg = string.Format(dnSpy_BamlDecompiler_Resources.Error_AttachedEvent, reField.Name)
                                }.Callback;
                                break;
                            }
                            var    handler = (IMethod)ctor.Arguments[1].Operand;
                            string evName  = reField.Name;
                            if (evName.EndsWith("Event"))
                            {
                                evName = evName.Substring(0, evName.Length - 5);
                            }

                            cb += new EventAttachment {
                                AttachedType = reField.DeclaringType.ResolveTypeDefThrow(),
                                EventName    = evName,
                                MethodName   = handler.Name
                            }.Callback;
                        }
                        else
                        {
                            // CLR event
                            var add = operand.ResolveMethodDefThrow();
                            var ev  = add.DeclaringType.Events.FirstOrDefault(e => e.AddMethod == add);

                            var ctor = expr.Arguments[1];
                            if (ev == null || ctor.Code != ILCode.Newobj ||
                                ctor.Arguments.Count != 2 || ctor.Arguments[1].Code != ILCode.Ldftn)
                            {
                                cb += new Error {
                                    Msg = string.Format(dnSpy_BamlDecompiler_Resources.Error_AttachedEvent, add.Name)
                                }.Callback;
                                break;
                            }
                            var handler = (IMethod)ctor.Arguments[1].Operand;

                            cb += new EventAttachment {
                                EventName  = ev.Name,
                                MethodName = handler.Name
                            }.Callback;
                        }
                        break;
                    }
                }

                if (cb != null)
                {
                    foreach (var id in cas.Values)
                    {
                        connIds[id] = cb;
                    }
                }
            }

            return(connIds.Count == 0 ? null : connIds);
        }
Example #52
0
        public void WriteData(ILBlock block, BinaryWriter writer)
        {
            uint          offset     = 0;
            SequencePoint prevSeq    = null;
            uint          prevOffset = 0;

            foreach (var instr in block.Content)
            {
                if (rt.dbgWriter != null && instr.IR.ILAST is ILASTExpression)
                {
                    var expr = (ILASTExpression)instr.IR.ILAST;
                    var seq  = expr.CILInstr == null ? null : expr.CILInstr.SequencePoint;

                    if (seq != null && seq.StartLine != 0xfeefee && (prevSeq == null || !Equals(seq, prevSeq)))
                    {
                        if (prevSeq != null)
                        {
                            uint len = offset - prevOffset, line = (uint)prevSeq.StartLine;
                            var  doc = prevSeq.Document.Url;

                            rt.dbgWriter.AddSequencePoint(block, prevOffset, len, doc, line);
                        }
                        prevSeq    = seq;
                        prevOffset = offset;
                    }
                }

                writer.Write(rt.Descriptor.Architecture.OpCodes[instr.OpCode]);
                // Leave a padding to let BasicBlockChunk fixup block exit key
                writer.Write((byte)rt.Descriptor.Random.Next());
                offset += 2;

                if (instr.Operand != null)
                {
                    if (instr.Operand is ILRegister)
                    {
                        writer.Write(rt.Descriptor.Architecture.Registers[((ILRegister)instr.Operand).Register]);
                        offset++;
                    }
                    else if (instr.Operand is ILImmediate)
                    {
                        var value = ((ILImmediate)instr.Operand).Value;
                        if (value is int)
                        {
                            writer.Write((int)value);
                            offset += 4;
                        }
                        else if (value is uint)
                        {
                            writer.Write((uint)value);
                            offset += 4;
                        }
                        else if (value is long)
                        {
                            writer.Write((long)value);
                            offset += 8;
                        }
                        else if (value is ulong)
                        {
                            writer.Write((ulong)value);
                            offset += 8;
                        }
                        else if (value is float)
                        {
                            writer.Write((float)value);
                            offset += 4;
                        }
                        else if (value is double)
                        {
                            writer.Write((double)value);
                            offset += 8;
                        }
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                }
            }

            if (prevSeq != null)
            {
                uint len = offset - prevOffset, line = (uint)prevSeq.StartLine;
                var  doc = prevSeq.Document.Url;

                rt.dbgWriter.AddSequencePoint(block, prevOffset, len, doc, line);
            }
        }
Example #53
0
        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);
        }
Example #54
0
 internal void AddHelper(MethodDef method, ScopeBlock rootScope, ILBlock entry)
 {
     methodMap[method] = Tuple.Create(rootScope, entry);
 }
Example #55
0
        string GenerateNameForVariable(ILVariable variable, ILBlock methodBody)
        {
            string proposedName = null;

            if (variable.Type == context.CurrentType.Module.TypeSystem.Int32)
            {
                // test whether the variable might be a loop counter
                bool isLoopCounter = false;
                foreach (ILWhileLoop loop in methodBody.GetSelfAndChildrenRecursive <ILWhileLoop>())
                {
                    ILExpression expr = loop.Condition;
                    while (expr != null && expr.Code == ILCode.LogicNot)
                    {
                        expr = expr.Arguments[0];
                    }
                    if (expr != null)
                    {
                        switch (expr.Code)
                        {
                        case ILCode.Clt:
                        case ILCode.Clt_Un:
                        case ILCode.Cgt:
                        case ILCode.Cgt_Un:
                        case ILCode.Cle:
                        case ILCode.Cle_Un:
                        case ILCode.Cge:
                        case ILCode.Cge_Un:
                            ILVariable loadVar;
                            if (expr.Arguments[0].Match(ILCode.Ldloc, out loadVar) && loadVar == variable)
                            {
                                isLoopCounter = true;
                            }
                            break;
                        }
                    }
                }
                if (isLoopCounter)
                {
                    // For loop variables, use i,j,k,l,m,n
                    for (char c = 'i'; c <= maxLoopVariableName; c++)
                    {
                        if (!typeNames.ContainsKey(c.ToString()))
                        {
                            proposedName = c.ToString();
                            break;
                        }
                    }
                }
            }
            if (string.IsNullOrEmpty(proposedName))
            {
                var proposedNameForStores =
                    (from expr in methodBody.GetSelfAndChildrenRecursive <ILExpression>()
                     where expr.Code == ILCode.Stloc && expr.Operand == variable
                     select GetNameFromExpression(expr.Arguments.Single())
                    ).Except(fieldNamesInCurrentType).ToList();
                if (proposedNameForStores.Count == 1)
                {
                    proposedName = proposedNameForStores[0];
                }
            }
            if (string.IsNullOrEmpty(proposedName))
            {
                var proposedNameForLoads =
                    (from expr in methodBody.GetSelfAndChildrenRecursive <ILExpression>()
                     from i in Enumerable.Range(0, expr.Arguments.Count)
                     let arg = expr.Arguments[i]
                               where arg.Code == ILCode.Ldloc && arg.Operand == variable
                               select GetNameForArgument(expr, i)
                    ).Except(fieldNamesInCurrentType).ToList();
                if (proposedNameForLoads.Count == 1)
                {
                    proposedName = proposedNameForLoads[0];
                }
            }
            if (string.IsNullOrEmpty(proposedName))
            {
                proposedName = GetNameByType(variable.Type);
            }

            // remove any numbers from the proposed name
            int number;

            proposedName = SplitName(proposedName, out number);

            if (!typeNames.ContainsKey(proposedName))
            {
                typeNames.Add(proposedName, 0);
            }
            int count = ++typeNames[proposedName];

            if (count > 1)
            {
                return(proposedName + count.ToString());
            }
            else
            {
                return(proposedName);
            }
        }
Example #56
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();

            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);
        }
Example #57
0
        public static void AssignNamesToVariables(DecompilerContext context, IEnumerable <ILVariable> parameters, IEnumerable <ILVariable> variables, ILBlock methodBody)
        {
            NameVariables nv = new NameVariables();

            nv.context = context;
            nv.fieldNamesInCurrentType = context.CurrentType.Fields.Select(f => f.Name).ToList();
            // First mark existing variable names as reserved.
            foreach (string name in context.ReservedVariableNames)
            {
                nv.AddExistingName(name);
            }
            foreach (var p in parameters)
            {
                nv.AddExistingName(p.Name);
            }
            foreach (var v in variables)
            {
                if (v.IsGenerated)
                {
                    // don't introduce names for variables generated by ILSpy - keep "expr"/"arg"
                    nv.AddExistingName(v.Name);
                }
                else if (v.OriginalVariable != null && context.Settings.UseDebugSymbols)
                {
                    string varName = v.OriginalVariable.Name;
                    if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || !IsValidName(varName))
                    {
                        // don't use the name from the debug symbols if it looks like a generated name
                        v.Name = null;
                    }
                    else
                    {
                        // use the name from the debug symbols
                        // (but ensure we don't use the same name for two variables)
                        v.Name = nv.GetAlternativeName(varName);
                    }
                }
                else
                {
                    v.Name = null;
                }
            }
            // Now generate names:
            foreach (ILVariable p in parameters)
            {
                if (string.IsNullOrEmpty(p.Name))
                {
                    p.Name = nv.GenerateNameForVariable(p, methodBody);
                }
            }
            foreach (ILVariable varDef in variables)
            {
                if (string.IsNullOrEmpty(varDef.Name))
                {
                    varDef.Name = nv.GenerateNameForVariable(varDef, methodBody);
                }
            }
        }
        private void Load(LoadState state, ILBlock block)
        {
            var  zeroStackSizeNodes = new List <ILNode>();
            int  instructionCount   = 0;
            bool hasChildren        = false;
            var  node = block.FirstChild;

            while (node != null)
            {
                switch (node.NodeType)
                {
                case ILNodeType.Instruction:
                {
                    var instruction = (ILInstruction)node;

                    int stackSize;
                    if (state.StackSizeByInstruction.TryGetValue(instruction, out stackSize) && stackSize == 0)
                    {
                        if (CanBranchAtInstruction(instruction))
                        {
                            zeroStackSizeNodes.Add(instruction);
                        }
                    }

                    instructionCount++;
                }
                break;

                case ILNodeType.Block:
                {
                    var tryBlock = node as ILTryBlock;
                    if (tryBlock != null)
                    {
                        if (node.PreviousSibling != null)
                        {
                            zeroStackSizeNodes.Add(tryBlock);
                        }

                        hasChildren = true;
                        instructionCount++;
                    }
                }
                break;
                }

                node = node.NextSibling;
            }

            state.TotalInstructionCount += instructionCount;

            if (zeroStackSizeNodes.Count > 0)
            {
                var blockState = new BlockLoadState();
                blockState.Index              = state.Blocks.Count;
                blockState.InstructionCount   = instructionCount;
                blockState.Node               = block;
                blockState.ZeroStackSizeNodes = zeroStackSizeNodes;
                state.Blocks.Add(blockState);
            }

            // Load child blocks
            if (hasChildren)
            {
                node = block.FirstChild;
                while (node != null)
                {
                    var tryBlock = node as ILTryBlock;
                    if (tryBlock != null)
                    {
                        Load(state, tryBlock);
                    }

                    node = node.NextSibling;
                }
            }
        }
Example #59
0
        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);
        }
Example #60
0
 // The if statements are resolved so now lets try to build case statements out of them
 public void DetectSwitchFromIfStatements(ILBlock method)
 {
 }