private void DisassembleFunction(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); } _InstrCollection.Clear(); foreach (FunctionBlock block in f.Blocks) { uint offset = state.Pe.Rva2Offset(block.StartAddress - (uint)state.Pe.optHdr.ImageBase); for (uint i = 0; i < block.InstrCount; i++) { uint instruction = state.Pe.ReadInstruction(offset + i * 4); XenonInstructions.OpCodeInfo info = state.Instructions.GetInfo(instruction); ListViewInstr instr = new ListViewInstr("0x" + (block.StartAddress + i * 4).ToString("X8"), info.Name, ""); _InstrCollection.Add(instr); } } }
void AddLazyCalls() { for (int i = 0; i < Blocks.Count - 1; i++) { uint lastInstructionAddr = Blocks[i].StartAddress + (Blocks[i].InstrCount - 1) * 4; uint rva = lastInstructionAddr - (uint)decompiler.Pe.GetImageBase(); uint offset = decompiler.Pe.Rva2Offset(rva); uint instruction = decompiler.Pe.ReadInstruction(offset); XenonInstructions.OpCodeInfo info = decompiler.Instructions.GetInfo(instruction); switch (info.Id) { case XenonInstructions.Mnemonics.PPC_OP_B: case XenonInstructions.Mnemonics.PPC_OP_BC: case XenonInstructions.Mnemonics.PPC_OP_BCCTR: case XenonInstructions.Mnemonics.PPC_OP_BCLR: break; default: Blocks[i].Successors.Add(Blocks[i + 1]); Blocks[i + 1].Predecessors.Add(Blocks[i]); break; } } }
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 DecompileEasy(Function f) { foreach (FunctionBlock block in f.Blocks) { uint offset = state.Pe.Rva2Offset(block.StartAddress - (uint)state.Pe.optHdr.ImageBase); for (uint i = 0; i < block.InstrCount; i++) { uint instruction = state.Pe.ReadInstruction(offset + i * 4); XenonInstructions.OpCodeInfo info = state.Instructions.GetInfo(instruction); if (info.CEquivalent != null) { List <CStatement> cEquiv = info.CEquivalent(block.StartAddress + i * 4, instruction); block.Statements.AddRange(cEquiv); } else { MessageBox.Show("Can't translate instruction " + info.Name); } } } }
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 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(); }