Example #1
0
        private static void PropagatePushOp(Dictionary <ulong, Block> blocks, Block currBlock, int pushOpIndex)
        {
            OpCodePush pushOp = currBlock.PushOpCodes[pushOpIndex];

            Stack <PathBlockState> workQueue = new Stack <PathBlockState>();

            HashSet <Block> visited = new HashSet <Block>();

            Stack <ulong> branchStack = new Stack <ulong>();

            void Push(PathBlockState pbs)
            {
                // When block is null, this means we are pushing a restore operation.
                // Restore operations are used to undo the work done inside a block
                // when we return from it, for example it pops addresses pushed by
                // SSY/PBK instructions inside the block, and pushes addresses poped
                // by SYNC/BRK.
                // For blocks, if it's already visited, we just ignore to avoid going
                // around in circles and getting stuck here.
                if (pbs.Block == null || !visited.Contains(pbs.Block))
                {
                    workQueue.Push(pbs);
                }
            }

            Push(new PathBlockState(currBlock));

            while (workQueue.TryPop(out PathBlockState pbs))
            {
                if (pbs.ReturningFromVisit)
                {
                    pbs.RestoreStackState(branchStack);

                    continue;
                }

                Block current = pbs.Block;

                // If the block was already processed, we just ignore it, otherwise
                // we would push the same child blocks of an already processed block,
                // and go around in circles until memory is exhausted.
                if (!visited.Add(current))
                {
                    continue;
                }

                int pushOpsCount = current.PushOpCodes.Count;

                if (pushOpsCount != 0)
                {
                    Push(new PathBlockState(branchStack.Count));

                    for (int index = pushOpIndex; index < pushOpsCount; index++)
                    {
                        branchStack.Push(current.PushOpCodes[index].GetAbsoluteAddress());
                    }
                }

                pushOpIndex = 0;

                if (current.Next != null)
                {
                    Push(new PathBlockState(current.Next));
                }

                if (current.Branch != null)
                {
                    Push(new PathBlockState(current.Branch));
                }
                else if (current.GetLastOp() is OpCodeBranchIndir brIndir)
                {
                    // By adding them in descending order (sorted by address), we process the blocks
                    // in order (of ascending address), since we work with a LIFO.
                    foreach (Block possibleTarget in brIndir.PossibleTargets.OrderByDescending(x => x.Address))
                    {
                        Push(new PathBlockState(possibleTarget));
                    }
                }
                else if (current.GetLastOp() is OpCodeBranchPop op)
                {
                    ulong targetAddress = branchStack.Pop();

                    if (branchStack.Count == 0)
                    {
                        branchStack.Push(targetAddress);

                        op.Targets.Add(pushOp, op.Targets.Count);

                        pushOp.PopOps.TryAdd(op, Local());
                    }
                    else
                    {
                        // First we push the target address (this will be used to push the
                        // address back into the SSY/PBK stack when we return from that block),
                        // then we push the block itself into the work "queue" (well, it's a stack)
                        // for processing.
                        Push(new PathBlockState(targetAddress));
                        Push(new PathBlockState(blocks[targetAddress]));
                    }
                }
            }
        }
Example #2
0
        private static void PropagatePushOp(Dictionary <ulong, Block> blocks, Block currBlock, int pushOpIndex)
        {
            OpCodePush pushOp = currBlock.PushOpCodes[pushOpIndex];

            Stack <PathBlockState> workQueue = new Stack <PathBlockState>();

            HashSet <Block> visited = new HashSet <Block>();

            Stack <ulong> branchStack = new Stack <ulong>();

            void Push(PathBlockState pbs)
            {
                if (pbs.Block == null || visited.Add(pbs.Block))
                {
                    workQueue.Push(pbs);
                }
            }

            Push(new PathBlockState(currBlock));

            while (workQueue.TryPop(out PathBlockState pbs))
            {
                if (pbs.ReturningFromVisit)
                {
                    pbs.RestoreStackState(branchStack);

                    continue;
                }

                Block current = pbs.Block;

                int pushOpsCount = current.PushOpCodes.Count;

                if (pushOpsCount != 0)
                {
                    Push(new PathBlockState(branchStack.Count));

                    for (int index = pushOpIndex; index < pushOpsCount; index++)
                    {
                        branchStack.Push(current.PushOpCodes[index].GetAbsoluteAddress());
                    }
                }

                pushOpIndex = 0;

                if (current.Next != null)
                {
                    Push(new PathBlockState(current.Next));
                }

                if (current.Branch != null)
                {
                    Push(new PathBlockState(current.Branch));
                }
                else if (current.GetLastOp() is OpCodeBranchIndir brIndir)
                {
                    foreach (Block possibleTarget in brIndir.PossibleTargets)
                    {
                        Push(new PathBlockState(possibleTarget));
                    }
                }
                else if (current.GetLastOp() is OpCodeBranchPop op)
                {
                    ulong targetAddress = branchStack.Pop();

                    if (branchStack.Count == 0)
                    {
                        branchStack.Push(targetAddress);

                        op.Targets.Add(pushOp, op.Targets.Count);

                        pushOp.PopOps.TryAdd(op, Local());
                    }
                    else
                    {
                        Push(new PathBlockState(targetAddress));
                        Push(new PathBlockState(blocks[targetAddress]));
                    }
                }
            }
        }