private void StructureBreakContinue(CStatement container, FunctionBlock continueBlock, FunctionBlock breakBlock) { foreach (CStatement stmt in container.InnerBlock) { switch (stmt.Kind) { case CStatement.Kinds.Goto: if (continueBlock != null && stmt.BranchDestinationAddr == continueBlock.StartAddress) { stmt.Kind = CStatement.Kinds.Continue; } else if (stmt.BranchDestinationAddr == breakBlock.StartAddress) { stmt.Kind = CStatement.Kinds.Break; } break; case CStatement.Kinds.Conditional: /* Recursion to subscopes */ StructureBreakContinue(stmt, continueBlock, breakBlock);; break; default: /* Do not recurse to do/while, while and for, since they have their own continue and break blocks! */ break; } } }
private void DecompileFunction(object sender, RoutedEventArgs e) { ListViewFunction item = (ListViewFunction)FunctionsView.SelectedItem; Function f = item.Details; if (f.Size == 0xFFFFFFFF || f.Blocks == null) { f.FindSize(); FindDominators(f.Blocks); } f.Loops = FindLoops(f.Blocks); DecompileEasy(f); ComputeUseDefs(f.Blocks); // PropagateExpressions(f.Blocks); // NiceConditions(f.Blocks); // LoopPhase2(f.Blocks, f.Loops); // IfElse(f.Blocks); List <CStatement> statements = new List <CStatement>(); foreach (FunctionBlock b in f.Blocks) { CStatement label = new CStatement(CStatement.Kinds.Label); label.LabelName = "L" + b.StartAddress.ToString("X8"); statements.Add(label); statements.AddRange(b.Statements); } string csource = "void " + f.Name + "()\n{\n"; foreach (CStatement stat in statements) { if (stat.Kind != CStatement.Kinds.Label) { csource += "\t"; } csource += stat.ToString(1); if (stat.Kind != CStatement.Kinds.Conditional && stat.Kind != CStatement.Kinds.Label) { csource += ";\n"; } else { csource += "\n"; } } csource += "}"; CSource src = new CSource(csource); src.Show(); }
private CStatement FindLastCondition(List <CStatement> stats) { CStatement If = stats[stats.Count - 1]; if (If.Kind != CStatement.Kinds.Conditional) { throw new Exception("Whatever..."); } return(If.Condition); }
private void NiceConditions(List <FunctionBlock> blocks) { foreach (FunctionBlock b in blocks) { for (int i = 0; i < b.Statements.Count; i++) { if (b.Statements[i].Kind != CStatement.Kinds.Conditional) { continue; } CStatement If = b.Statements[i]; CStatement cond = If.Condition; String cr = cond.Op1.Name; /* Simplify "a - 0 op 0" => "a op 0", and "a - b op 0" => "a op b" */ if (If.Condition.Op1.Kind == CStatement.OperandKinds.Expression) { if (If.Condition.Op1.Expr.Kind == CStatement.Kinds.Subtraction) { if (If.Condition.Op1.Expr.Op2.Kind == CStatement.OperandKinds.Constant && If.Condition.Op1.Expr.Op2.Value == 0) { If.Condition.Op1 = If.Condition.Op1.Expr.Op1; } else { If.Condition.Op2 = If.Condition.Op1.Expr.Op2; If.Condition.Op1 = If.Condition.Op1.Expr.Op1; } } } } } }
public COperand(CStatement expression) { Kind = OperandKinds.Expression; Expr = expression; }
public CStatement(Kinds k, CStatement op1, ulong op2) { this.Kind = k; this.Op1 = new COperand(op1); this.Op2 = new COperand(op2); }
public CStatement(Kinds k, String var1, CStatement expr2) { this.Kind = k; this.Op1 = new COperand(var1); this.Op2 = new COperand(expr2); }
void ComputeUseDefs(List <FunctionBlock> blocks) { foreach (FunctionBlock b in blocks) { foreach (CStatement stat in b.Statements) { stat.FindUsesAndDefines(); } } foreach (FunctionBlock b in blocks) { b.Uses = new List <String>(); b.Defines = new List <String>(); for (int i = b.Statements.Count - 1; i >= 0; i--) { CStatement s = b.Statements[i]; s.LiveOut = s.Uses; s.Dead = s.Defines; foreach (String lo in s.LiveOut) { s.Dead.Remove(lo); } foreach (String lo in s.LiveOut) { b.Defines.Remove(lo); } foreach (String lo in s.Dead) { b.Uses.Remove(lo); } b.Uses.AddRange(s.LiveOut); b.Defines.AddRange(s.Dead); b.Uses = b.Uses.Distinct().ToList(); b.Defines = b.Defines.Distinct().ToList(); } } /* bool changed; * do * { * changed = false; * foreach (FunctionBlock b in blocks) * { * List<String> output = new List<String>(b.Defines); * foreach (FunctionBlock succ in b.Successors) * { * if (succ.Input != null) * output.AddRange(succ.Input); * } * output = output.Distinct().ToList(); * * List<String> input = new List<String>(output); * foreach (String d in b.Defines) * input.Remove(d); * input.AddRange(b.Uses); * input = input.Distinct().ToList(); * * bool inputChanged, outputChanged; * if (b.Input != null) * inputChanged = (input.Count == b.Input.Count) && input.Except(b.Input).Any(); * else * inputChanged = true; * * if (b.Output != null) * outputChanged = (input.Count == b.Output.Count) && input.Except(b.Output).Any(); * else * outputChanged = true; * * if (inputChanged || outputChanged) * { * changed = true; * b.Input = input; * b.Output = output; * } * } * } while (changed == true); * * foreach (FunctionBlock b in blocks) * { * List<String> live = new List<String>(); * foreach (FunctionBlock succ in b.Successors) * live.AddRange(succ.Input); * live = live.Distinct().ToList(); * * for (int i = b.Statements.Count - 1; i >= 0; i--) * { * CStatement stat = b.Statements[i]; * List<String> newLive = new List<String>(live); * foreach (String d in stat.Dead) * newLive.Remove(d); * newLive.AddRange(stat.LiveOut); * newLive = newLive.Distinct().ToList(); * * stat.LiveOut = live; * live = newLive; * } * }*/ }
private void LoopPhase2(List <FunctionBlock> blocks, List <Loop> loops) { /* Take loops in reverse order (inner loops are processed before outer loops */ loops.Sort(LoopSortDesc); foreach (Loop loop in loops) { FunctionBlock lastBlock = loop.Blocks[loop.Blocks.Count - 1]; CStatement doWhile = new CStatement(); doWhile.Kind = CStatement.Kinds.DoWhile; doWhile.Condition = FindLastCondition(lastBlock.Statements); doWhile.SubBlocks = loop.Blocks; doWhile.BreakBlock = blocks[lastBlock.Id + 1]; doWhile.ContinueBlock = lastBlock; doWhile.ExpandBlocks(); if (doWhile.ContinueBlock.Statements.Count != 1) { doWhile.ContinueBlock = null; } else { CStatement stat = doWhile.ContinueBlock.Statements[0]; if (stat.Kind != CStatement.Kinds.Conditional) { doWhile.ContinueBlock = null; } else { if (stat.InnerBlock[0].BranchDestinationAddr != loop.Blocks[0].StartAddress) { doWhile.ContinueBlock = null; } } } /* Remove all blocks in the loop from the main block list. It is replaced by a single while block */ int firstIndex = blocks.IndexOf(loop.Blocks[0]); FunctionBlock firstBlock = blocks[firstIndex]; foreach (FunctionBlock b in loop.Blocks) { blocks.Remove(b); } FunctionBlock fake = new FunctionBlock(); fake.StartAddress = firstBlock.StartAddress; fake.InstrCount = 0; fake.Statements.Add(doWhile); loop.LoopBlock = fake; blocks.Insert(firstIndex, fake); StructureBreakContinue(doWhile, doWhile.ContinueBlock, doWhile.BreakBlock); } foreach (Loop loop in loops) { FunctionBlock precBlock = blocks.Find(delegate(FunctionBlock b) { return(b.Id == loop.Blocks[0].Id - 1); }); uint precedingBlockStart = precBlock.StartAddress; uint lastInstruction = precedingBlockStart + (precBlock.InstrCount - 1) * 4; uint offset = state.Pe.Rva2Offset(lastInstruction - (uint)state.Pe.optHdr.ImageBase); uint instruction = state.Pe.ReadInstruction(offset); XenonInstructions.OpCodeInfo info = state.Instructions.GetInfo(instruction); if (info.Id == XenonInstructions.Mnemonics.PPC_OP_B) { uint bDest = (instruction & 0xFFFFFF) + lastInstruction; if (bDest == loop.Header.StartAddress) { loop.LoopBlock.Statements[0].Kind = CStatement.Kinds.While; precBlock.InstrCount--; precBlock.Statements.RemoveAt(precBlock.Statements.Count - 1); } } } foreach (Loop loop in loops) { int cnt = loop.LoopBlock.Statements[0].SubBlocks.Count; FunctionBlock last = loop.LoopBlock.Statements[0].SubBlocks[cnt - 1]; loop.LoopBlock.Statements[0].SubBlocks.RemoveAt(cnt - 1); last.Statements.RemoveAt(0); if (last.Statements.Count != 0) { blocks.Add(last); blocks.Sort(Function.FunctionBlockSorter); } /* This will have removed some statements, reexpand the blocks */ loop.LoopBlock.Statements[0].ExpandBlocks(); } }