Ejemplo n.º 1
0
        public static Block[] Decode(IMemoryManager memory, ulong address, ExecutionMode mode, bool highCq, DecoderMode dMode)
        {
            List <Block> blocks = new List <Block>();

            Queue <Block> workQueue = new Queue <Block>();

            Dictionary <ulong, Block> visited = new Dictionary <ulong, Block>();

            Debug.Assert(MaxInstsPerFunctionLowCq <= MaxInstsPerFunction);

            int opsCount = 0;

            int instructionLimit = highCq ? MaxInstsPerFunction : MaxInstsPerFunctionLowCq;

            Block GetBlock(ulong blkAddress)
            {
                if (!visited.TryGetValue(blkAddress, out Block block))
                {
                    block = new Block(blkAddress);

                    if ((dMode != DecoderMode.MultipleBlocks && visited.Count >= 1) || opsCount > instructionLimit || !memory.IsMapped(blkAddress))
                    {
                        block.Exit       = true;
                        block.EndAddress = blkAddress;
                    }

                    workQueue.Enqueue(block);

                    visited.Add(blkAddress, block);
                }

                return(block);
            }

            GetBlock(address);

            while (workQueue.TryDequeue(out Block currBlock))
            {
                // Check if the current block is inside another block.
                if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex))
                {
                    Block nBlock = blocks[nBlkIndex];

                    if (nBlock.Address == currBlock.Address)
                    {
                        throw new InvalidOperationException("Found duplicate block address on the list.");
                    }

                    currBlock.Exit = false;

                    nBlock.Split(currBlock);

                    blocks.Insert(nBlkIndex + 1, currBlock);

                    continue;
                }

                if (!currBlock.Exit)
                {
                    // If we have a block after the current one, set the limit address.
                    ulong limitAddress = ulong.MaxValue;

                    if (nBlkIndex != blocks.Count)
                    {
                        Block nBlock = blocks[nBlkIndex];

                        int nextIndex = nBlkIndex + 1;

                        if (nBlock.Address < currBlock.Address && nextIndex < blocks.Count)
                        {
                            limitAddress = blocks[nextIndex].Address;
                        }
                        else if (nBlock.Address > currBlock.Address)
                        {
                            limitAddress = blocks[nBlkIndex].Address;
                        }
                    }

                    if (dMode == DecoderMode.SingleInstruction)
                    {
                        // Only read at most one instruction
                        limitAddress = currBlock.Address + 1;
                    }

                    FillBlock(memory, mode, currBlock, limitAddress);

                    opsCount += currBlock.OpCodes.Count;

                    if (currBlock.OpCodes.Count != 0)
                    {
                        // 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.
                        OpCode lastOp = currBlock.GetLastOp();

                        bool isCall = IsCall(lastOp);

                        if (lastOp is IOpCodeBImm op && !isCall)
                        {
                            currBlock.Branch = GetBlock((ulong)op.Immediate);
                        }

                        if (isCall || !(IsUnconditionalBranch(lastOp) || IsTrap(lastOp)))
                        {
                            currBlock.Next = GetBlock(currBlock.EndAddress);
                        }
                    }
                }

                // Insert the new block on the list (sorted by address).
                if (blocks.Count != 0)
                {
                    Block nBlock = blocks[nBlkIndex];

                    blocks.Insert(nBlkIndex + (nBlock.Address < currBlock.Address ? 1 : 0), currBlock);
                }
                else
                {
                    blocks.Add(currBlock);
                }
            }

            if (blocks.Count == 1 && blocks[0].OpCodes.Count == 0)
            {
                Debug.Assert(blocks[0].Exit);
                Debug.Assert(blocks[0].Address == blocks[0].EndAddress);

                throw new InvalidOperationException($"Decoded a single empty exit block. Entry point = 0x{address:X}.");
            }

            if (dMode == DecoderMode.MultipleBlocks)
            {
                return(TailCallRemover.RunPass(address, blocks));
            }
            else
            {
                return(blocks.ToArray());
            }
        }
Ejemplo n.º 2
0
 public static extern ZyanStatus EnableMode(ref Decoder decoder, DecoderMode decoderMode,
                                            [MarshalAs(UnmanagedType.I1)] bool enabled);