private void IfElse(List <FunctionBlock> blocks) { foreach (FunctionBlock b in blocks) { if (b.Statements[b.Statements.Count - 1].Kind == CStatement.Kinds.Conditional) { if (b.Successors.Count != 2) { continue; } FunctionBlock tb = b.Successors[0]; FunctionBlock fb = b.Successors[1]; if (tb.Successors.Count != 1 || fb.Successors.Count != 1) { continue; } if (tb.Successors[0] != fb.Successors[0]) { continue; } } } }
void BuildCallTree(uint address, uint maxLen) { Blocks = new List <FunctionBlock>(); FunctionBlock f1 = new FunctionBlock(); f1.StartAddress = address; f1.InstrCount = maxLen / 4; Blocks.Add(f1); while (true) { int toAnalyze = -1; for (int i = 0; i < Blocks.Count; i++) { if (!Blocks[i].Analyzed) { toAnalyze = i; break; } } if (toAnalyze == -1) { break; } AnalyzeBlock(Blocks[toAnalyze], address, address + maxLen); } AddLazyCalls(); }
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 Loop NaturalLoopForEdge(FunctionBlock header, FunctionBlock tail) { Stack <FunctionBlock> workList = new Stack <FunctionBlock>(); Loop loop; loop = new Loop(); loop.Header = header; loop.Blocks.Add(header); if (header != tail) { loop.Blocks.Add(tail); workList.Push(tail); } while (workList.Count != 0) { FunctionBlock b = workList.Pop(); foreach (FunctionBlock pred in b.Predecessors) { if (loop.Blocks.IndexOf(pred) < 0) { loop.Blocks.Add(pred); workList.Push(pred); } } } loop.Blocks.Sort(Function.FunctionBlockSorter); return(loop); }
void AddBlock(FunctionBlock callerBlock, uint npc, uint minFunctionAddr, uint maxFunctionAddr) { if (npc >= minFunctionAddr && npc < maxFunctionAddr) { /* This is an internal branch. Need to add this block if it's not already present */ foreach (FunctionBlock b in Blocks) { if (b.StartAddress == npc) { callerBlock.Successors.Add(b); b.Predecessors.Add(callerBlock); return; } } /* Not present. Create a new block and append to list. */ FunctionBlock fb = new FunctionBlock(); fb.StartAddress = npc; fb.Analyzed = false; if (npc < callerBlock.StartAddress) { fb.InstrCount = (callerBlock.StartAddress - npc) / 4; } else { fb.InstrCount = (maxFunctionAddr - npc) / 4; } Blocks.Add(fb); callerBlock.Successors.Add(fb); fb.Predecessors.Add(callerBlock); } }
public uint FindSize() { /* Functions can't cross each other, so the maximum size is on the next function boundary */ uint addr = Address - (uint)decompiler.Pe.GetImageBase(); uint diff; int index = decompiler.Functions.IndexOf(this); if (index != decompiler.Functions.Count - 1) { diff = decompiler.Functions[index + 1].Address - Address; } else { diff = decompiler.Pe.Rva2SectionEnd(addr) - addr; } diff = (uint)(diff & (~3)); /* Check that all instructions are valid, and stop at the first invalid instruction (if any) */ uint i = 0; uint offset = decompiler.Pe.Rva2Offset(addr); for (; i < diff / 4; i++) { uint instruction = decompiler.Pe.ReadInstruction(offset + i * 4); XenonInstructions.OpCodeInfo info = decompiler.Instructions.GetInfo(instruction); if (info.Id == XenonInstructions.Mnemonics.PPC_OP_INVALID) { break; } } diff = i * 4; /* Build a call tree and find the maximum address */ BuildCallTree(Address, diff); FunctionBlock lastBlock = Blocks[Blocks.Count - 1]; uint maxAddr = lastBlock.StartAddress + lastBlock.InstrCount * 4; return(maxAddr - Address); }
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(); } }
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 Loop NaturalLoopForEdge(FunctionBlock header, FunctionBlock tail) { Stack<FunctionBlock> workList = new Stack<FunctionBlock>(); Loop loop; loop = new Loop(); loop.Header = header; loop.Blocks.Add(header); if (header != tail) { loop.Blocks.Add(tail); workList.Push(tail); } while (workList.Count != 0) { FunctionBlock b = workList.Pop(); foreach (FunctionBlock pred in b.Predecessors) { if (loop.Blocks.IndexOf(pred) < 0) { loop.Blocks.Add(pred); workList.Push(pred); } } } loop.Blocks.Sort(Function.FunctionBlockSorter); return loop; }
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(); } }
void AddBlock(FunctionBlock callerBlock, uint npc, uint minFunctionAddr, uint maxFunctionAddr) { if (npc >= minFunctionAddr && npc < maxFunctionAddr) { /* This is an internal branch. Need to add this block if it's not already present */ foreach (FunctionBlock b in Blocks) { if (b.StartAddress == npc) { callerBlock.Successors.Add(b); b.Predecessors.Add(callerBlock); return; } } /* Not present. Create a new block and append to list. */ FunctionBlock fb = new FunctionBlock(); fb.StartAddress = npc; fb.Analyzed = false; if (npc < callerBlock.StartAddress) fb.InstrCount = (callerBlock.StartAddress - npc) / 4; else fb.InstrCount = (maxFunctionAddr - npc) / 4; Blocks.Add(fb); callerBlock.Successors.Add(fb); fb.Predecessors.Add(callerBlock); } }
public static int FunctionBlockSorter(FunctionBlock f1, FunctionBlock f2) { return (int)f1.StartAddress - (int)f2.StartAddress; }
void BuildCallTree(uint address, uint maxLen) { Blocks = new List<FunctionBlock>(); FunctionBlock f1 = new FunctionBlock(); f1.StartAddress = address; f1.InstrCount = maxLen / 4; Blocks.Add(f1); while (true) { int toAnalyze = -1; for (int i = 0; i < Blocks.Count; i++) { if (!Blocks[i].Analyzed) { toAnalyze = i; break; } } if (toAnalyze == -1) break; AnalyzeBlock(Blocks[toAnalyze], address, address + maxLen); } AddLazyCalls(); }
void AnalyzeBlock(FunctionBlock block, uint minFunctionAddr, uint maxFunctionAddr) { block.Analyzed = true; uint rva = block.StartAddress - (uint)decompiler.Pe.GetImageBase(); uint offset = decompiler.Pe.Rva2Offset(rva); bool cont = true; for (uint i = 0; i < block.InstrCount && cont; i++) { uint instruction = decompiler.Pe.ReadInstruction(offset + i * 4); XenonInstructions.OpCodeInfo info = decompiler.Instructions.GetInfo(instruction); XenonInstructions.Instruction instr = new XenonInstructions.Instruction(instruction); /* A branch signals end of block. However a branch with link is just a call, and it doesn't end a block */ uint pc = block.StartAddress + i * 4; if (instr.LK()) continue; switch (info.Id) { case XenonInstructions.Mnemonics.PPC_OP_B: { uint npc = (uint)SignExtend26(instr.LI() << 2); if (!instr.AA()) npc += pc; AddBlock(block, npc, minFunctionAddr, maxFunctionAddr); block.InstrCount = i + 1; cont = false; break; } case XenonInstructions.Mnemonics.PPC_OP_BC: { uint npc = (uint)(int)(short) (instr.BD() << 2); if (!instr.AA()) npc += pc; AddBlock(block, npc, minFunctionAddr, maxFunctionAddr); AddBlock(block, pc + 4, minFunctionAddr, maxFunctionAddr); block.InstrCount = i + 1; cont = false; break; } case XenonInstructions.Mnemonics.PPC_OP_BCCTR: case XenonInstructions.Mnemonics.PPC_OP_BCLR: { if (instr.BO() != 20) AddBlock(block, pc + 4, minFunctionAddr, maxFunctionAddr); block.InstrCount = i + 1; cont = false; break; } } } CleanupBlockList(); }
public static int FunctionBlockSorter(FunctionBlock f1, FunctionBlock f2) { return((int)f1.StartAddress - (int)f2.StartAddress); }
void AnalyzeBlock(FunctionBlock block, uint minFunctionAddr, uint maxFunctionAddr) { block.Analyzed = true; uint rva = block.StartAddress - (uint)decompiler.Pe.GetImageBase(); uint offset = decompiler.Pe.Rva2Offset(rva); bool cont = true; for (uint i = 0; i < block.InstrCount && cont; i++) { uint instruction = decompiler.Pe.ReadInstruction(offset + i * 4); XenonInstructions.OpCodeInfo info = decompiler.Instructions.GetInfo(instruction); XenonInstructions.Instruction instr = new XenonInstructions.Instruction(instruction); /* A branch signals end of block. However a branch with link is just a call, and it doesn't end a block */ uint pc = block.StartAddress + i * 4; if (instr.LK()) { continue; } switch (info.Id) { case XenonInstructions.Mnemonics.PPC_OP_B: { uint npc = (uint)SignExtend26(instr.LI() << 2); if (!instr.AA()) { npc += pc; } AddBlock(block, npc, minFunctionAddr, maxFunctionAddr); block.InstrCount = i + 1; cont = false; break; } case XenonInstructions.Mnemonics.PPC_OP_BC: { uint npc = (uint)(int)(short)(instr.BD() << 2); if (!instr.AA()) { npc += pc; } AddBlock(block, npc, minFunctionAddr, maxFunctionAddr); AddBlock(block, pc + 4, minFunctionAddr, maxFunctionAddr); block.InstrCount = i + 1; cont = false; break; } case XenonInstructions.Mnemonics.PPC_OP_BCCTR: case XenonInstructions.Mnemonics.PPC_OP_BCLR: { if (instr.BO() != 20) { AddBlock(block, pc + 4, minFunctionAddr, maxFunctionAddr); } block.InstrCount = i + 1; cont = false; break; } } } CleanupBlockList(); }