internal DecompilationContext (MethodBody body, ControlFlowGraph cfg) { this.body = body; this.method = body.Method; this.variables = CloneCollection (body.Variables); this.cfg = cfg; }
public BlockStatement Process (DecompilationContext context, BlockStatement body) { this.cfg = context.ControlFlowGraph; this.annotations = AnnotationStore.CreateStore (cfg, optimization); this.body = context.Body; this.variables = context.Variables; this.expression_decompiler = new ExpressionDecompiler (context.Method, annotations); this.statements = new List<Statement> [cfg.Blocks.Length]; this.processed = new HashSet<InstructionBlock> (); this.assignments = new Dictionary<VariableReference, Expression> (); Run (); PopulateBodyBlock (body); return body; }
protected virtual void Visit(MethodDefinition method) { IEnumerable<Instruction> transformed = null; this.cfg = ControlFlowGraph.Create (method); foreach (var b in cfg.Blocks) { block = b; foreach (var instruction in block) { switch (instruction.OpCode.Code) { case Code.Nop: transformed = this.OnNop (instruction); break; case Code.Break: transformed = this.OnBreak (instruction); break; case Code.Ldarg_0: transformed = this.OnLdarg_0 (instruction); break; case Code.Ldarg_1: transformed = this.OnLdarg_1 (instruction); break; case Code.Ldarg_2: transformed = this.OnLdarg_2 (instruction); break; case Code.Ldarg_3: transformed = this.OnLdarg_3 (instruction); break; case Code.Ldloc_0: transformed = this.OnLdloc_0 (instruction); break; case Code.Ldloc_1: transformed = this.OnLdloc_1 (instruction); break; case Code.Ldloc_2: transformed = this.OnLdloc_2 (instruction); break; case Code.Ldloc_3: transformed = this.OnLdloc_3 (instruction); break; case Code.Stloc_0: transformed = this.OnStloc_0 (instruction); break; case Code.Stloc_1: transformed = this.OnStloc_1 (instruction); break; case Code.Stloc_2: transformed = this.OnStloc_2 (instruction); break; case Code.Stloc_3: transformed = this.OnStloc_3 (instruction); break; case Code.Ldarg: case Code.Ldarg_S: transformed = this.OnLdarg (instruction); break; case Code.Ldarga: case Code.Ldarga_S: transformed = this.OnLdarga (instruction); break; case Code.Starg: case Code.Starg_S: transformed = this.OnStarg (instruction); break; case Code.Ldloc: case Code.Ldloc_S: transformed = this.OnLdloc (instruction); break; case Code.Ldloca: case Code.Ldloca_S: transformed = this.OnLdloca (instruction); break; case Code.Stloc: case Code.Stloc_S: transformed = this.OnStloc (instruction); break; case Code.Ldnull: transformed = this.OnLdnull (instruction); break; case Code.Ldc_I4_M1: transformed = this.OnLdc_I4_M1 (instruction); break; case Code.Ldc_I4_0: transformed = this.OnLdc_I4_0 (instruction); break; case Code.Ldc_I4_1: transformed = this.OnLdc_I4_1 (instruction); break; case Code.Ldc_I4_2: transformed = this.OnLdc_I4_2 (instruction); break; case Code.Ldc_I4_3: transformed = this.OnLdc_I4_3 (instruction); break; case Code.Ldc_I4_4: transformed = this.OnLdc_I4_4 (instruction); break; case Code.Ldc_I4_5: transformed = this.OnLdc_I4_5 (instruction); break; case Code.Ldc_I4_6: transformed = this.OnLdc_I4_6 (instruction); break; case Code.Ldc_I4_7: transformed = this.OnLdc_I4_7 (instruction); break; case Code.Ldc_I4_8: transformed = this.OnLdc_I4_8 (instruction); break; case Code.Ldc_I4: case Code.Ldc_I4_S: transformed = this.OnLdc_I4 (instruction); break; case Code.Ldc_I8: transformed = this.OnLdc_I8 (instruction); break; case Code.Ldc_R4: transformed = this.OnLdc_R4 (instruction); break; case Code.Ldc_R8: transformed = this.OnLdc_R8 (instruction); break; case Code.Dup: transformed = this.OnDup (instruction); break; case Code.Pop: transformed = this.OnPop (instruction); break; case Code.Jmp: transformed = this.OnJmp (instruction); break; case Code.Call: transformed = this.OnCall (instruction); break; case Code.Calli: transformed = this.OnCalli (instruction); break; case Code.Ret: transformed = this.OnRet (instruction); break; case Code.Br: case Code.Br_S: transformed = this.OnBr (instruction); break; case Code.Brfalse: case Code.Brfalse_S: transformed = this.OnBrfalse (instruction); break; case Code.Brtrue: case Code.Brtrue_S: transformed = this.OnBrtrue (instruction); break; case Code.Beq: case Code.Beq_S: transformed = this.OnBeq (instruction); break; case Code.Bge: case Code.Bge_S: transformed = this.OnBge (instruction); break; case Code.Bgt: case Code.Bgt_S: transformed = this.OnBgt (instruction); break; case Code.Ble: case Code.Ble_S: transformed = this.OnBle (instruction); break; case Code.Blt: case Code.Blt_S: transformed = this.OnBlt (instruction); break; case Code.Bne_Un: case Code.Bne_Un_S: transformed = this.OnBne_Un (instruction); break; case Code.Bge_Un: case Code.Bge_Un_S: transformed = this.OnBge_Un (instruction); break; case Code.Bgt_Un: case Code.Bgt_Un_S: transformed = this.OnBgt_Un (instruction); break; case Code.Ble_Un: case Code.Ble_Un_S: transformed = this.OnBle_Un (instruction); break; case Code.Blt_Un: case Code.Blt_Un_S: transformed = this.OnBlt_Un (instruction); break; case Code.Switch: transformed = this.OnSwitch (instruction); break; case Code.Ldind_I1: transformed = this.OnLdind_I1 (instruction); break; case Code.Ldind_U1: transformed = this.OnLdind_U1 (instruction); break; case Code.Ldind_I2: transformed = this.OnLdind_I2 (instruction); break; case Code.Ldind_U2: transformed = this.OnLdind_U2 (instruction); break; case Code.Ldind_I4: transformed = this.OnLdind_I4 (instruction); break; case Code.Ldind_U4: transformed = this.OnLdind_U4 (instruction); break; case Code.Ldind_I8: transformed = this.OnLdind_I8 (instruction); break; case Code.Ldind_I: transformed = this.OnLdind_I (instruction); break; case Code.Ldind_R4: transformed = this.OnLdind_R4 (instruction); break; case Code.Ldind_R8: transformed = this.OnLdind_R8 (instruction); break; case Code.Ldind_Ref: transformed = this.OnLdind_Ref (instruction); break; case Code.Stind_Ref: transformed = this.OnStind_Ref (instruction); break; case Code.Stind_I1: transformed = this.OnStind_I1 (instruction); break; case Code.Stind_I2: transformed = this.OnStind_I2 (instruction); break; case Code.Stind_I4: transformed = this.OnStind_I4 (instruction); break; case Code.Stind_I8: transformed = this.OnStind_I8 (instruction); break; case Code.Stind_R4: transformed = this.OnStind_R4 (instruction); break; case Code.Stind_R8: transformed = this.OnStind_R8 (instruction); break; case Code.Add: transformed = this.OnAdd (instruction); break; case Code.Sub: transformed = this.OnSub (instruction); break; case Code.Mul: transformed = this.OnMul (instruction); break; case Code.Div: transformed = this.OnDiv (instruction); break; case Code.Div_Un: transformed = this.OnDiv_Un (instruction); break; case Code.Rem: transformed = this.OnRem (instruction); break; case Code.Rem_Un: transformed = this.OnRem_Un (instruction); break; case Code.And: transformed = this.OnAnd (instruction); break; case Code.Or: transformed = this.OnOr (instruction); break; case Code.Xor: transformed = this.OnXor (instruction); break; case Code.Shl: transformed = this.OnShl (instruction); break; case Code.Shr: transformed = this.OnShr (instruction); break; case Code.Shr_Un: transformed = this.OnShr_Un (instruction); break; case Code.Neg: transformed = this.OnNeg (instruction); break; case Code.Not: transformed = this.OnNot (instruction); break; case Code.Conv_I1: transformed = this.OnConv_I1 (instruction); break; case Code.Conv_I2: transformed = this.OnConv_I2 (instruction); break; case Code.Conv_I4: transformed = this.OnConv_I4 (instruction); break; case Code.Conv_I8: transformed = this.OnConv_I8 (instruction); break; case Code.Conv_R4: transformed = this.OnConv_R4 (instruction); break; case Code.Conv_R8: transformed = this.OnConv_R8 (instruction); break; case Code.Conv_U4: transformed = this.OnConv_U4 (instruction); break; case Code.Conv_U8: transformed = this.OnConv_U8 (instruction); break; case Code.Callvirt: transformed = this.OnCallvirt (instruction); break; case Code.Cpobj: transformed = this.OnCpobj (instruction); break; case Code.Ldobj: transformed = this.OnLdobj (instruction); break; case Code.Ldstr: transformed = this.OnLdstr (instruction); break; case Code.Newobj: transformed = this.OnNewobj (instruction); break; case Code.Castclass: transformed = this.OnCastclass (instruction); break; case Code.Isinst: transformed = this.OnIsinst (instruction); break; case Code.Conv_R_Un: transformed = this.OnConv_R_Un (instruction); break; case Code.Unbox: transformed = this.OnUnbox (instruction); break; case Code.Throw: transformed = this.OnThrow (instruction); break; case Code.Ldfld: transformed = this.OnLdfld (instruction); break; case Code.Ldflda: transformed = this.OnLdflda (instruction); break; case Code.Stfld: transformed = this.OnStfld (instruction); break; case Code.Ldsfld: transformed = this.OnLdsfld (instruction); break; case Code.Ldsflda: transformed = this.OnLdsflda (instruction); break; case Code.Stsfld: transformed = this.OnStsfld (instruction); break; case Code.Stobj: transformed = this.OnStobj (instruction); break; case Code.Conv_Ovf_I1_Un: transformed = this.OnConv_Ovf_I1_Un (instruction); break; case Code.Conv_Ovf_I2_Un: transformed = this.OnConv_Ovf_I2_Un (instruction); break; case Code.Conv_Ovf_I4_Un: transformed = this.OnConv_Ovf_I4_Un (instruction); break; case Code.Conv_Ovf_I8_Un: transformed = this.OnConv_Ovf_I8_Un (instruction); break; case Code.Conv_Ovf_U1_Un: transformed = this.OnConv_Ovf_U1_Un (instruction); break; case Code.Conv_Ovf_U2_Un: transformed = this.OnConv_Ovf_U2_Un (instruction); break; case Code.Conv_Ovf_U4_Un: transformed = this.OnConv_Ovf_U4_Un (instruction); break; case Code.Conv_Ovf_U8_Un: transformed = this.OnConv_Ovf_U8_Un (instruction); break; case Code.Conv_Ovf_I_Un: transformed = this.OnConv_Ovf_I_Un (instruction); break; case Code.Conv_Ovf_U_Un: transformed = this.OnConv_Ovf_U_Un (instruction); break; case Code.Box: transformed = this.OnBox (instruction); break; case Code.Newarr: transformed = this.OnNewarr (instruction); break; case Code.Ldlen: transformed = this.OnLdlen (instruction); break; case Code.Ldelema: transformed = this.OnLdelema (instruction); break; case Code.Ldelem_I1: transformed = this.OnLdelem_I1 (instruction); break; case Code.Ldelem_U1: transformed = this.OnLdelem_U1 (instruction); break; case Code.Ldelem_I2: transformed = this.OnLdelem_I2 (instruction); break; case Code.Ldelem_U2: transformed = this.OnLdelem_U2 (instruction); break; case Code.Ldelem_I4: transformed = this.OnLdelem_I4 (instruction); break; case Code.Ldelem_U4: transformed = this.OnLdelem_U4 (instruction); break; case Code.Ldelem_I8: transformed = this.OnLdelem_I8 (instruction); break; case Code.Ldelem_I: transformed = this.OnLdelem_I (instruction); break; case Code.Ldelem_R4: transformed = this.OnLdelem_R4 (instruction); break; case Code.Ldelem_R8: transformed = this.OnLdelem_R8 (instruction); break; case Code.Ldelem_Ref: transformed = this.OnLdelem_Ref (instruction); break; case Code.Stelem_I: transformed = this.OnStelem_I (instruction); break; case Code.Stelem_I1: transformed = this.OnStelem_I1 (instruction); break; case Code.Stelem_I2: transformed = this.OnStelem_I2 (instruction); break; case Code.Stelem_I4: transformed = this.OnStelem_I4 (instruction); break; case Code.Stelem_I8: transformed = this.OnStelem_I8 (instruction); break; case Code.Stelem_R4: transformed = this.OnStelem_R4 (instruction); break; case Code.Stelem_R8: transformed = this.OnStelem_R8 (instruction); break; case Code.Stelem_Ref: transformed = this.OnStelem_Ref (instruction); break; case Code.Ldelem_Any: transformed = this.OnLdelem_Any (instruction); break; case Code.Stelem_Any: transformed = this.OnStelem_Any (instruction); break; case Code.Unbox_Any: transformed = this.OnUnbox_Any (instruction); break; case Code.Conv_Ovf_I1: transformed = this.OnConv_Ovf_I1 (instruction); break; case Code.Conv_Ovf_U1: transformed = this.OnConv_Ovf_U1 (instruction); break; case Code.Conv_Ovf_I2: transformed = this.OnConv_Ovf_I2 (instruction); break; case Code.Conv_Ovf_U2: transformed = this.OnConv_Ovf_U2 (instruction); break; case Code.Conv_Ovf_I4: transformed = this.OnConv_Ovf_I4 (instruction); break; case Code.Conv_Ovf_U4: transformed = this.OnConv_Ovf_U4 (instruction); break; case Code.Conv_Ovf_I8: transformed = this.OnConv_Ovf_I8 (instruction); break; case Code.Conv_Ovf_U8: transformed = this.OnConv_Ovf_U8 (instruction); break; case Code.Refanyval: transformed = this.OnRefanyval (instruction); break; case Code.Ckfinite: transformed = this.OnCkfinite (instruction); break; case Code.Mkrefany: transformed = this.OnMkrefany (instruction); break; case Code.Ldtoken: transformed = this.OnLdtoken (instruction); break; case Code.Conv_U2: transformed = this.OnConv_U2 (instruction); break; case Code.Conv_U1: transformed = this.OnConv_U1 (instruction); break; case Code.Conv_I: transformed = this.OnConv_I (instruction); break; case Code.Conv_Ovf_I: transformed = this.OnConv_Ovf_I (instruction); break; case Code.Conv_Ovf_U: transformed = this.OnConv_Ovf_U (instruction); break; case Code.Add_Ovf: transformed = this.OnAdd_Ovf (instruction); break; case Code.Add_Ovf_Un: transformed = this.OnAdd_Ovf_Un (instruction); break; case Code.Mul_Ovf: transformed = this.OnMul_Ovf (instruction); break; case Code.Mul_Ovf_Un: transformed = this.OnMul_Ovf_Un (instruction); break; case Code.Sub_Ovf: transformed = this.OnSub_Ovf (instruction); break; case Code.Sub_Ovf_Un: transformed = this.OnSub_Ovf_Un (instruction); break; case Code.Endfinally: transformed = this.OnEndfinally (instruction); break; case Code.Leave: case Code.Leave_S: transformed = this.OnLeave (instruction); break; case Code.Stind_I: transformed = this.OnStind_I (instruction); break; case Code.Conv_U: transformed = this.OnConv_U (instruction); break; case Code.Arglist: transformed = this.OnArglist (instruction); break; case Code.Ceq: transformed = this.OnCeq (instruction); break; case Code.Cgt: transformed = this.OnCgt (instruction); break; case Code.Cgt_Un: transformed = this.OnCgt_Un (instruction); break; case Code.Clt: transformed = this.OnClt (instruction); break; case Code.Clt_Un: transformed = this.OnClt_Un (instruction); break; case Code.Ldftn: transformed = this.OnLdftn (instruction); break; case Code.Ldvirtftn: transformed = this.OnLdvirtftn (instruction); break; case Code.Localloc: transformed = this.OnLocalloc (instruction); break; case Code.Endfilter: transformed = this.OnEndfilter (instruction); break; case Code.Unaligned: transformed = this.OnUnaligned (instruction); break; case Code.Volatile: transformed = this.OnVolatile (instruction); break; case Code.Tail: transformed = this.OnTail (instruction); break; case Code.Initobj: transformed = this.OnInitobj (instruction); break; case Code.Cpblk: transformed = this.OnCpblk (instruction); break; case Code.Initblk: transformed = this.OnInitblk (instruction); break; case Code.Rethrow: transformed = this.OnRethrow (instruction); break; case Code.Sizeof: transformed = this.OnSizeof (instruction); break; case Code.Refanytype: transformed = this.OnRefanytype (instruction); break; case Code.Constrained: transformed = this.OnConstrained (instruction); break; default: throw new Exception ("Unknown instruction: " + instruction); } if (transformed == null) { InstructionMap.Add (instruction, new Instruction [] { instruction }); } else { var list = transformed.ToList (); /* if (list.Count != 0 && list [0] != null && (list [0] != instruction || list.Count > 1)) { MapInstructions (method.Body, instruction, list [0], list [list.Count - 1]); } */ InstructionMap.Add (instruction, list); } } // foreach instruction } // foreach block }
public static void FormatControlFlowGraph (TextWriter writer, ControlFlowGraph cfg) { foreach (InstructionBlock block in cfg.Blocks) { writer.WriteLine ("block {0}:", block.Index); writer.WriteLine ("\tbody:"); foreach (Instruction instruction in block) { writer.Write ("\t\t"); var data = cfg.GetData (instruction); writer.Write ("[{0}:{1}] ", data.StackBefore, data.StackAfter); Formatter.WriteInstruction (writer, instruction); writer.WriteLine (); } InstructionBlock [] successors = block.Successors; if (successors.Length > 0) { writer.WriteLine ("\tsuccessors:"); foreach (InstructionBlock successor in successors) { writer.WriteLine ("\t\tblock {0}", successor.Index); } } } }
public static string ToString (ControlFlowGraph cfg) { StringWriter writer = new StringWriter (); FormatControlFlowGraph (writer, cfg); return writer.ToString (); }