Beispiel #1
0
        public static ABlock DecodeBasicBlock(AThreadState State, AMemory Memory, long Start)
        {
            ABlock Block = new ABlock(Start);

            FillBlock(State, Memory, Block);

            return(Block);
        }
Beispiel #2
0
        public static ABlock DecodeBasicBlock(
            ATranslator Translator,
            AMemory Memory,
            long Start)
        {
            ABlock Block = new ABlock(Start);

            FillBlock(Memory, Block);

            return(Block);
        }
Beispiel #3
0
        private static void FillBlock(AMemory Memory, ABlock Block)
        {
            long Position = Block.Position;

            AOpCode OpCode;

            do
            {
                OpCode = DecodeOpCode(Memory, Position);

                Block.OpCodes.Add(OpCode);

                Position += 4;
            }while (!(IsBranch(OpCode) || IsException(OpCode)));

            Block.EndPosition = Position;
        }
Beispiel #4
0
        private static void FillBlock(AThreadState State, AMemory Memory, ABlock Block)
        {
            long Position = Block.Position;

            AOpCode OpCode;

            do
            {
                //TODO: This needs to be changed to support both AArch32 and AArch64,
                //once JIT support is introduced on AArch32 aswell.
                OpCode = DecodeOpCode(State, Memory, Position);

                Block.OpCodes.Add(OpCode);

                Position += 4;
            }while (!(IsBranch(OpCode) || IsException(OpCode)));

            Block.EndPosition = Position;
        }
Beispiel #5
0
        public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(ATranslator Translator, long Start)
        {
            Dictionary <long, ABlock> Visited    = new Dictionary <long, ABlock>();
            Dictionary <long, ABlock> VisitedEnd = new Dictionary <long, ABlock>();

            Queue <ABlock> Blocks = new Queue <ABlock>();

            ABlock Enqueue(long Position)
            {
                if (!Visited.TryGetValue(Position, out ABlock Output))
                {
                    Output = new ABlock(Position);

                    Blocks.Enqueue(Output);

                    Visited.Add(Position, Output);
                }

                return(Output);
            }

            ABlock Root = Enqueue(Start);

            while (Blocks.Count > 0)
            {
                ABlock Current = Blocks.Dequeue();

                FillBlock(Translator.Thread.Memory, Current);

                //Set child blocks. "Branch" is the block the branch instruction
                //points to (when taken), "Next" is the block at the next address,
                //executed when the branch is not taken. For Unconditional Branches
                //(except BL/BLR that are sub calls) or end of executable, Next is null.
                if (Current.OpCodes.Count > 0)
                {
                    bool HasCachedSub = false;

                    AOpCode LastOp = Current.GetLastOp();

                    if (LastOp is AOpCodeBImm Op)
                    {
                        if (Op.Emitter == AInstEmit.Bl)
                        {
                            HasCachedSub = Translator.HasCachedSub(Op.Imm);
                        }
                        else
                        {
                            Current.Branch = Enqueue(Op.Imm);
                        }
                    }

                    if ((!(LastOp is AOpCodeBImmAl) &&
                         !(LastOp is AOpCodeBReg)) || HasCachedSub)
                    {
                        Current.Next = Enqueue(Current.EndPosition);
                    }
                }

                //If we have on the tree two blocks with the same end position,
                //then we need to split the bigger block and have two small blocks,
                //the end position of the bigger "Current" block should then be == to
                //the position of the "Smaller" block.
                while (VisitedEnd.TryGetValue(Current.EndPosition, out ABlock Smaller))
                {
                    if (Current.Position > Smaller.Position)
                    {
                        ABlock Temp = Smaller;

                        Smaller = Current;
                        Current = Temp;
                    }

                    Current.EndPosition = Smaller.Position;
                    Current.Next        = Smaller;
                    Current.Branch      = null;

                    Current.OpCodes.RemoveRange(
                        Current.OpCodes.Count - Smaller.OpCodes.Count,
                        Smaller.OpCodes.Count);

                    VisitedEnd[Smaller.EndPosition] = Smaller;
                }

                VisitedEnd.Add(Current.EndPosition, Current);
            }

            //Make and sort Graph blocks array by position.
            ABlock[] Graph = new ABlock[Visited.Count];

            while (Visited.Count > 0)
            {
                ulong FirstPos = ulong.MaxValue;

                foreach (ABlock Block in Visited.Values)
                {
                    if (FirstPos > (ulong)Block.Position)
                    {
                        FirstPos = (ulong)Block.Position;
                    }
                }

                ABlock Current = Visited[(long)FirstPos];

                do
                {
                    Graph[Graph.Length - Visited.Count] = Current;

                    Visited.Remove(Current.Position);

                    Current = Current.Next;
                }while (Current != null);
            }

            return(Graph, Root);
        }