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); }
public void Return(ILAstOptimizer opt) { ilAstOptimizerPool.Free(opt); }
public override void Decompile(MethodDef method, IDecompilerOutput output, DecompilationContext ctx) { WriteCommentBegin(output, true); output.Write("Method: ", BoxedTextColor.Comment); output.Write(IdentifierEscaper.Escape(method.FullName), method, DecompilerReferenceFlags.Definition, BoxedTextColor.Comment); WriteCommentEnd(output, true); output.WriteLine(); if (!method.HasBody) { return; } var bodyInfo = StartKeywordBlock(output, ".body", method); ILAstBuilder astBuilder = new ILAstBuilder(); ILBlock ilMethod = new ILBlock(CodeBracesRangeFlags.MethodBraces); DecompilerContext context = new DecompilerContext(settingsVersion, method.Module, MetadataTextColorProvider) { CurrentType = method.DeclaringType, CurrentMethod = method, CalculateILSpans = ctx.CalculateILSpans, }; ilMethod.Body = astBuilder.Build(method, inlineVariables, context); var stateMachineKind = StateMachineKind.None; MethodDef? inlinedMethod = null; AsyncMethodDebugInfo?asyncInfo = null; string? compilerName = null; if (!(abortBeforeStep is null)) { var optimizer = new ILAstOptimizer(); optimizer.Optimize(context, ilMethod, out stateMachineKind, out inlinedMethod, out asyncInfo, abortBeforeStep.Value); compilerName = optimizer.CompilerName; } if (context.CurrentMethodIsYieldReturn) { output.Write("yield", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); output.WriteLine("return", BoxedTextColor.Keyword); } if (context.CurrentMethodIsAsync) { output.Write("async", BoxedTextColor.Keyword); output.Write("/", BoxedTextColor.Punctuation); output.WriteLine("await", BoxedTextColor.Keyword); } var allVariables = ilMethod.GetSelfAndChildrenRecursive <ILExpression>().Select(e => e.Operand as ILVariable) .Where(v => !(v is null) && !v.IsParameter).Distinct(); foreach (ILVariable v in allVariables) { output.Write(IdentifierEscaper.Escape(v.Name), v.GetTextReferenceObject(), DecompilerReferenceFlags.Local | DecompilerReferenceFlags.Definition, v.IsParameter ? BoxedTextColor.Parameter : BoxedTextColor.Local); if (!(v.Type is null)) { output.Write(" ", BoxedTextColor.Text); output.Write(":", BoxedTextColor.Punctuation); output.Write(" ", BoxedTextColor.Text); if (v.IsPinned) { output.Write("pinned", BoxedTextColor.Keyword); output.Write(" ", BoxedTextColor.Text); } v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } if (v.GeneratedByDecompiler) { output.Write(" ", BoxedTextColor.Text); var start = output.NextPosition; output.Write("[", BoxedTextColor.Punctuation); output.Write("generated", BoxedTextColor.Keyword); var end = output.NextPosition; output.Write("]", BoxedTextColor.Punctuation); output.AddBracePair(new TextSpan(start, 1), new TextSpan(end, 1), CodeBracesRangeFlags.SquareBrackets); } output.WriteLine(); } var localVariables = new HashSet <ILVariable>(GetVariables(ilMethod)); var builder = new MethodDebugInfoBuilder(settingsVersion, stateMachineKind, inlinedMethod ?? method, !(inlinedMethod is null) ? method : null, CreateSourceLocals(localVariables), CreateSourceParameters(localVariables), asyncInfo); builder.CompilerName = compilerName; foreach (ILNode node in ilMethod.Body) { node.WriteTo(output, builder); if (!node.WritesNewLine) { output.WriteLine(); } } output.AddDebugInfo(builder.Create()); EndKeywordBlock(output, bodyInfo, CodeBracesRangeFlags.MethodBraces, addLineSeparator: true); }
public void 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); } } } }