예제 #1
0
        void Executor_ImplementationEntered(object sender, Symbooglix.Executor.EnterImplementationEventArgs e)
        {
            // Handle the case where we enter a new implementation and the first block
            // is a loop header. This is the only case we don't get notified of a basic block
            // change.
            var state    = Executor.CurrentState; // FIXME: The state should be part of the event arg
            var sf       = state.Mem.Stack.Last();
            var loopInfo = ProgramLoopInfo.GetLoopInfoForHeader(sf.CurrentBlock);

            if (loopInfo == null)
            {
                return; // Not a loop. Nothing to do.
            }
            var executionStateSingleLoopInfo = new ExecutionStateSingleLoopInfo(sf, loopInfo);

            StateToCurrentLoops[state].NestedLoops.Push(executionStateSingleLoopInfo);
        }
예제 #2
0
        public ExecutionStateNestedLoopInfo Clone(ExecutionState newState)
        {
            var other = (ExecutionStateNestedLoopInfo)this.MemberwiseClone();

            other.State       = newState;
            other.NestedLoops = new Stack <ExecutionStateSingleLoopInfo>(NestedLoops.Count);

            // Traverse in reverse order (i.e. start at bottom of the stack)
            // so we can push elements on to the new stack in the right order
            foreach (var sli in NestedLoops.Reverse())
            {
                StackFrame stackFrameInNewState     = GetCorrespondingStackFrame(newState, sli.Stack);
                ExecutionStateSingleLoopInfo newSli = sli.Clone(stackFrameInNewState);
                other.NestedLoops.Push(newSli);
            }
            Debug.Assert(other.NestedLoops.Count == NestedLoops.Count);
            return(other);
        }
예제 #3
0
        void Executor_BasicBlockChanged(object sender, Symbooglix.Executor.TransferToBlockEventArgs eventArgs)
        {
            // Control flow has transferred to a different basic block
            var state = eventArgs.State;
            var sf    = state.Mem.Stack.Last();
            var executionStateNestedLoopInfo = StateToCurrentLoops[state];
            // Cases:
            // * No existing loops, enter loop header
            // * No existing loops, do not enter loop header
            // * Existing loop, stackframe doesn't match (i.e. a call must have happenend), enter loop header
            // * Existing loop, stackframe doesn't match (i.e. a call must have happenend), do not enter loop header
            // * Existing loop, stackframe matches, enter loop header (must increment counter)
            // * Existing loop, stackframe matches, leave loop via exit basic block (we are leaving the current loop)
            // * Existing loop, stackframe matches, enter nested loop header (must push new loop on to stack)
            // * Existing loop, stackframe matches, stay in current loop (nothing to do)

            bool stackframeMatches = false;

            if (executionStateNestedLoopInfo.NestedLoops.Count > 0)
            {
                stackframeMatches = object.ReferenceEquals(executionStateNestedLoopInfo.NestedLoops.Peek().Stack,
                                                           sf);
            }

            ExecutionStateSingleLoopInfo executionStateSingleLoopInfo = null;

            if (!stackframeMatches)
            {
                // This handles the case that there are no existing loops on the stack or
                // there are existing loops but they are in another stackframe (i.e. we were in a loop
                // and then called into another implementation).
                var loopInfo = ProgramLoopInfo.GetLoopInfoForHeader(eventArgs.NewBlock);
                if (loopInfo == null)
                {
                    // The block we've entered is not a loop header and there are no
                    // existing loops we are in that we can enter/exit so there is nothing
                    // left to do
                    return;
                }
                // We've enterred a new loop push it on to the loop stack
                executionStateSingleLoopInfo = new ExecutionStateSingleLoopInfo(sf, loopInfo);
                executionStateNestedLoopInfo.NestedLoops.Push(executionStateSingleLoopInfo);
                return;
            }

            // We are currently inside a loop and are still in the context of that loop's stackframe on the
            // call stack.
            executionStateSingleLoopInfo = executionStateNestedLoopInfo.NestedLoops.Peek();
            if (object.ReferenceEquals(executionStateSingleLoopInfo.LInfo.Header, eventArgs.NewBlock))
            {
                // We are going to the loop header so we must have just completed one iteration
                // of the loop. Increment the counter.
                executionStateSingleLoopInfo.IncrementCounter();

                // Don't check bound here. The executor will misbehave (see goto look ahead)
                // if we try to terminate state here.
                return;
            }
            else if (executionStateSingleLoopInfo.LInfo.EscapingBlocks.Contains(eventArgs.NewBlock))
            {
                // We are in a loop but are about to jump to a basic block that escapes from the loop.
                // So pop this loop from the stack.
                executionStateNestedLoopInfo.NestedLoops.Pop();
                return;
            }
            var newLoopInfo = ProgramLoopInfo.GetLoopInfoForHeader(eventArgs.NewBlock);

            if (newLoopInfo == null)
            {
                // We are in a loop but we are jumping to a basic block that
                // * does not escape the current loop
                // * does not go to the loop head
                // * does not enter a nested loop (i.e. another loop head)
                // So there is nothing left to do.
                return;
            }

            // We are entering a nested loop. Push this loop onto the stack.
            var newExecutionStateSingleLoopInfo = new ExecutionStateSingleLoopInfo(sf, newLoopInfo);

            executionStateNestedLoopInfo.NestedLoops.Push(newExecutionStateSingleLoopInfo);
            return;
        }