Beispiel #1
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);
        }
Beispiel #2
0
 public void Return(ILAstOptimizer opt)
 {
     ilAstOptimizerPool.Free(opt);
 }
Beispiel #3
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);
        }
Beispiel #4
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);
                    }
                }
            }
        }