Example #1
0
        public void SplittingNodeShouldPreserveParentRegion()
        {
            var graph = new ControlFlowGraph <int>(IntArchitecture.Instance);
            var n1    = new ControlFlowNode <int>(0, 0, 2, 3, 4);
            var n2    = new ControlFlowNode <int>(5, 5, 6, 7, 8);

            var region = new ExceptionHandlerRegion <int>();

            graph.Regions.Add(region);

            var handler = new HandlerRegion <int>();

            region.Handlers.Add(handler);

            graph.Nodes.AddRange(new[] { n1, n2 });
            region.ProtectedRegion.Nodes.Add(n1);
            handler.Contents.Nodes.Add(n2);

            n1.ConnectWith(n2, ControlFlowEdgeType.Abnormal);
            graph.Entrypoint = n1;

            var(first, second) = n1.SplitAtIndex(2);
            Assert.Equal(first.ParentRegion, second.ParentRegion);
            Assert.Equal(first.ParentRegion, region.ProtectedRegion);
            Assert.Equal(2, region.ProtectedRegion.Nodes.Count);
        }
Example #2
0
        public void ExceptionHandler()
        {
            var cfg = new ControlFlowGraph <int>(IntArchitecture.Instance);

            for (int i = 0; i < 7; i++)
            {
                cfg.Nodes.Add(new ControlFlowNode <int>(i));
            }

            cfg.Entrypoint = cfg.Nodes[0];

            cfg.Nodes[0].ConnectWith(cfg.Nodes[1]);
            cfg.Nodes[1].ConnectWith(cfg.Nodes[2], ControlFlowEdgeType.Conditional);
            cfg.Nodes[1].ConnectWith(cfg.Nodes[3], ControlFlowEdgeType.FallThrough);
            cfg.Nodes[2].ConnectWith(cfg.Nodes[4], ControlFlowEdgeType.Unconditional);
            cfg.Nodes[3].ConnectWith(cfg.Nodes[4], ControlFlowEdgeType.FallThrough);
            cfg.Nodes[4].ConnectWith(cfg.Nodes[6], ControlFlowEdgeType.Unconditional);
            cfg.Nodes[5].ConnectWith(cfg.Nodes[6], ControlFlowEdgeType.Unconditional);

            var ehRegion = new ExceptionHandlerRegion <int>();

            cfg.Regions.Add(ehRegion);

            ehRegion.ProtectedRegion.Entrypoint = cfg.Nodes[1];
            ehRegion.ProtectedRegion.Nodes.AddRange(new[]
            {
                cfg.Nodes[1],
                cfg.Nodes[2],
                cfg.Nodes[3],
                cfg.Nodes[4],
            });

            var handler = new HandlerRegion <int>();

            ehRegion.Handlers.Add(handler);
            handler.Contents.Nodes.Add(cfg.Nodes[5]);
            handler.Contents.Entrypoint = cfg.Nodes[5];

            var tree = DominatorTree <int> .FromGraph(cfg);

            Assert.True(tree.Dominates(cfg.Nodes[1], cfg.Nodes[6]));
            Assert.False(tree.Dominates(cfg.Nodes[4], cfg.Nodes[6]));
            Assert.False(tree.Dominates(cfg.Nodes[5], cfg.Nodes[6]));
        }
Example #3
0
        private static void EnterHandlerSubRegion <TInstruction>(
            IndexableStack <ScopeInfo <TInstruction> > scopeStack,
            HandlerRegion <TInstruction> parentRegion,
            IControlFlowRegion <TInstruction> enteredRegion)
        {
            IBlock <TInstruction>             enteredBlock;
            IControlFlowRegion <TInstruction> enteredSubRegion;

            if (!(scopeStack.Peek().Block is HandlerBlock <TInstruction> handlerBlock))
            {
                throw new InvalidOperationException("The parent scope is not a handler scope.");
            }

            if (parentRegion.Prologue == enteredRegion)
            {
                // We entered the prologue.
                handlerBlock.Prologue = new ScopeBlock <TInstruction>();
                enteredBlock          = handlerBlock.Prologue;
                enteredSubRegion      = parentRegion.Prologue;
            }
            else if (parentRegion.Contents == enteredRegion)
            {
                // We entered the contents.
                enteredBlock     = handlerBlock.Contents;
                enteredSubRegion = parentRegion.Contents;
            }
            else if (parentRegion.Epilogue == enteredRegion)
            {
                // We entered the epilogue.
                handlerBlock.Epilogue = new ScopeBlock <TInstruction>();
                enteredBlock          = handlerBlock.Epilogue;
                enteredSubRegion      = parentRegion.Epilogue;
            }
            else
            {
                // Exhaustive search, this should never happen.
                throw new InvalidOperationException(
                          "Entered subregion of handler doesn't belong to any of its regions.");
            }

            // Push the entered scope.
            scopeStack.Push(new ScopeInfo <TInstruction>(enteredSubRegion, enteredBlock));
        }
Example #4
0
        private HandlerRegion <Statement <TInstruction> > TransformHandlerRegion(HandlerRegion <TInstruction> handlerRegion)
        {
            var result = new HandlerRegion <Statement <TInstruction> >();

            if (handlerRegion.Prologue != null)
            {
                result.Prologue = (ScopeRegion <Statement <TInstruction> >)TransformRegion(handlerRegion.Prologue);
            }

            if (handlerRegion.Epilogue != null)
            {
                result.Epilogue = (ScopeRegion <Statement <TInstruction> >)TransformRegion(handlerRegion.Epilogue);
            }

            // Contents is read-only, so instead we just transform all sub regions and add it to the
            // existing protected region.
            TransformSubRegions(handlerRegion.Contents, result.Contents);
            _regionsMapping[handlerRegion.Contents] = result.Contents;

            return(result);
        }
Example #5
0
        private static Dictionary <AddressRange, ScopeRegion <TInstruction> > CreateEHRegions <TInstruction>(
            ControlFlowGraph <TInstruction> cfg,
            IReadOnlyList <ExceptionHandlerRange> sortedRanges)
        {
            var result = new Dictionary <AddressRange, ScopeRegion <TInstruction> >();

            var ehRegions = new Dictionary <AddressRange, ExceptionHandlerRegion <TInstruction> >();

            for (int i = 0; i < sortedRanges.Count; i++)
            {
                var currentEHRange = sortedRanges[i];

                // We want to merge exception handlers that have the exact same protected region.
                // This allows for exception handler constructs that have multiple handler blocks.

                // Check if we have already created the EH region in an earlier iteration:
                if (!ehRegions.TryGetValue(currentEHRange.ProtectedRange, out var ehRegion))
                {
                    // If not, create and register a new EH region for the protected range.
                    ehRegion = new ExceptionHandlerRegion <TInstruction>();
                    ehRegions.Add(currentEHRange.ProtectedRange, ehRegion);
                    result.Add(currentEHRange.ProtectedRange, ehRegion.ProtectedRegion);

                    // We need to add the EH region to a parent region. This can either be the CFG itself, or a
                    // sub region that was previously added.
                    var parentRegion = FindParentRegion(result, sortedRanges, i);
                    if (parentRegion is null)
                    {
                        cfg.Regions.Add(ehRegion);
                    }
                    else
                    {
                        parentRegion.Regions.Add(ehRegion);
                    }
                }

                // Create and add new handler region from the range.
                var handlerRegion = new HandlerRegion <TInstruction>();
                handlerRegion.Tag = currentEHRange.UserData;
                ehRegion.Handlers.Add(handlerRegion);
                result.Add(currentEHRange.HandlerRange, handlerRegion.Contents);

                // Do we need to add a prologue block?
                if (currentEHRange.PrologueRange != AddressRange.NilRange)
                {
                    handlerRegion.Prologue = new ScopeRegion <TInstruction>();
                    ehRegions.Add(currentEHRange.PrologueRange, ehRegion);
                    result.Add(currentEHRange.PrologueRange, handlerRegion.Prologue);
                }

                // Do we need to add an epilogue block?
                if (currentEHRange.EpilogueRange != AddressRange.NilRange)
                {
                    handlerRegion.Epilogue = new ScopeRegion <TInstruction>();
                    ehRegions.Add(currentEHRange.EpilogueRange, ehRegion);
                    result.Add(currentEHRange.EpilogueRange, handlerRegion.Epilogue);
                }
            }

            return(result);
        }