示例#1
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;
                }
            }
        }
示例#2
0
        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();
        }
示例#3
0
        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);
        }
示例#4
0
        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;
                            }
                        }
                    }
                }
            }
        }
示例#5
0
 public COperand(CStatement expression)
 {
     Kind = OperandKinds.Expression;
     Expr = expression;
 }
示例#6
0
 public CStatement(Kinds k, CStatement op1, ulong op2)
 {
     this.Kind = k;
     this.Op1  = new COperand(op1);
     this.Op2  = new COperand(op2);
 }
示例#7
0
 public CStatement(Kinds k, String var1, CStatement expr2)
 {
     this.Kind = k;
     this.Op1  = new COperand(var1);
     this.Op2  = new COperand(expr2);
 }
示例#8
0
        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;
 *              }
 *          }*/
        }
示例#9
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();
            }
        }