コード例 #1
0
        private bool CheckForChangesInFooter(
            ControlFlowGraphEditTransaction <TInstruction> transaction,
            ControlFlowNode <TInstruction> node)
        {
            bool hasChanges = false;

            // Most instructions will have <= 2 successors.
            // - Immediate fallthrough successor or unconditional branch target.
            // - A single conditional branch target.

            // The only exception will be switch-like instructions.
            // Therefore we start off by renting a buffer of at least two elements.
            var arrayPool = ArrayPool <SuccessorInfo> .Shared;

            // Verify that our buffer has enough elements.
            int successorCount   = SuccessorResolver.GetSuccessorsCount(node.Contents.Footer);
            var successorsBuffer = arrayPool.Rent(successorCount);

            try
            {
                // Get new successors.
                var successorBufferSlice = new Span <SuccessorInfo>(successorsBuffer, 0, successorCount);
                int actualSuccessorCount = SuccessorResolver.GetSuccessors(node.Contents.Footer, successorBufferSlice);
                if (actualSuccessorCount > successorCount)
                {
                    throw new InvalidOperationException();
                }

                // Group successors by type:
                long?fallthroughSuccessor  = null;
                var  conditionalSuccessors = new List <long>();
                var  abnormalSuccessors    = new List <long>();

                for (int i = 0; i < actualSuccessorCount; i++)
                {
                    var successor = successorsBuffer[i];
                    switch (successor.EdgeType)
                    {
                    case ControlFlowEdgeType.FallThrough:
                        if (fallthroughSuccessor.HasValue)
                        {
                            throw new ArgumentException("Instruction has multiple fallthrough successors.");
                        }
                        else
                        {
                            fallthroughSuccessor = successor.DestinationAddress;
                        }
                        break;

                    case ControlFlowEdgeType.Conditional:
                        conditionalSuccessors.Add(successor.DestinationAddress);
                        break;

                    case ControlFlowEdgeType.Abnormal:
                        abnormalSuccessors.Add(successor.DestinationAddress);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                // Check if there are any changes to the outgoing edges.
                hasChanges |= CheckIfFallThroughChanged(transaction, node, fallthroughSuccessor);
                hasChanges |= CheckIfAdjacencyListChanged(transaction, node.ConditionalEdges, conditionalSuccessors);
                hasChanges |= CheckIfAdjacencyListChanged(transaction, node.AbnormalEdges, abnormalSuccessors);
            }
            finally
            {
                arrayPool.Return(successorsBuffer);
            }

            return(hasChanges);
        }
コード例 #2
0
        private bool CheckForChangesInBasicBlock(ControlFlowGraphEditTransaction <TInstruction> transaction, ControlFlowNode <TInstruction> node)
        {
            bool hasChanges = false;

            // Most instructions will have <= 2 successors.
            // - Immediate fallthrough successor or unconditional branch target.
            // - A single conditional branch target.

            // The only exception will be switch-like instructions.
            // Therefore we start off by renting a buffer of at least two elements.
            var arrayPool        = ArrayPool <SuccessorInfo> .Shared;
            var successorsBuffer = arrayPool.Rent(2);

            try
            {
                var architecture = ControlFlowGraph.Architecture;

                // Skip last instruction (footer), since it is processed somewhere else.
                for (int i = 0; i < node.Contents.Instructions.Count - 1; i++)
                {
                    // Optimization: we assume the architecture has a faster implementation for categorizing instructions
                    // as instructions that influence the basic block (i.e. branches) than the successor resolver itself.
                    var instruction = node.Contents.Instructions[i];
                    var flowControl = architecture.GetFlowControl(instruction);
                    if (SplitsBasicBlock(flowControl))
                    {
                        long offset = architecture.GetOffset(instruction);

                        // Split the node after the instruction.
                        var splitAction = new SplitNodeAction <TInstruction>(offset + architecture.GetSize(instruction));
                        transaction.EnqueueAction(splitAction);

                        // Remove the fallthrough edge generated by ControlFlowNode<T>.SplitAtIndex.
                        transaction.EnqueueAction(new UpdateFallThroughAction <TInstruction>(offset, null));

                        // Verify that our buffer has enough elements.
                        int successorCount = SuccessorResolver.GetSuccessorsCount(instruction);
                        if (successorsBuffer.Length < successorCount)
                        {
                            arrayPool.Return(successorsBuffer);
                            successorsBuffer = arrayPool.Rent(successorCount);
                        }

                        // Get new successors.
                        var successorBufferSlice = new Span <SuccessorInfo>(successorsBuffer, 0, successorCount);
                        int actualSuccessorCount = SuccessorResolver.GetSuccessors(instruction, successorBufferSlice);
                        if (actualSuccessorCount > successorCount)
                        {
                            throw new InvalidOperationException();
                        }

                        for (int j = 0; j < actualSuccessorCount; j++)
                        {
                            var successor = successorsBuffer[j];

                            IControlFlowGraphEditAction <TInstruction> action;
                            if (successor.EdgeType == ControlFlowEdgeType.FallThrough)
                            {
                                action = new UpdateFallThroughAction <TInstruction>(
                                    offset,
                                    successor.DestinationAddress);
                            }
                            else
                            {
                                action = new AddEdgeAction <TInstruction>(
                                    offset,
                                    successor.DestinationAddress,
                                    successor.EdgeType);
                            }

                            transaction.EnqueueAction(action);
                        }

                        hasChanges = true;
                    }
                }
            }
            finally
            {
                arrayPool.Return(successorsBuffer);
            }

            return(hasChanges);
        }