Example #1
0
        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;
                    }
                }
            }
        }
Example #2
0
        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();
        }
Example #3
0
        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;
                }
            }
        }
Example #4
0
        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);
        }
Example #5
0
        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);
            }
        }
Example #6
0
        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);
        }
Example #7
0
        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();
            }
        }
Example #11
0
        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);
            }
        }
Example #12
0
 public static int FunctionBlockSorter(FunctionBlock f1, FunctionBlock f2)
 {
     return (int)f1.StartAddress - (int)f2.StartAddress;
 }
Example #13
0
        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();
        }
Example #14
0
        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();
        }
Example #15
0
 public static int FunctionBlockSorter(FunctionBlock f1, FunctionBlock f2)
 {
     return((int)f1.StartAddress - (int)f2.StartAddress);
 }
Example #16
0
        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();
        }