コード例 #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);
        }
コード例 #2
0
        private static Dictionary <AddressRange, BasicControlFlowRegion <TInstruction> > CreateEHRegions <TInstruction>(
            ControlFlowGraph <TInstruction> cfg,
            IReadOnlyList <ExceptionHandlerRange> sortedRanges)
        {
            var rangeToRegion = new Dictionary <AddressRange, BasicControlFlowRegion <TInstruction> >();

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

            for (int i = 0; i < sortedRanges.Count; i++)
            {
                var currentEHRange = sortedRanges[i];
                if (!ehRegions.TryGetValue(currentEHRange.ProtectedRange, out var ehRegion))
                {
                    // Register new EH region for the protected range.
                    ehRegion = new ExceptionHandlerRegion <TInstruction>();
                    ehRegions.Add(currentEHRange.ProtectedRange, ehRegion);
                    rangeToRegion.Add(currentEHRange.ProtectedRange, ehRegion.ProtectedRegion);

                    // Since the ranges are sorted by enclosing EHs first, we can backtrack the list of ranges to find.
                    // the parent region (if there is any).
                    BasicControlFlowRegion <TInstruction> parentRegion = null;
                    for (int j = i; j >= 0 && parentRegion is null; j--)
                    {
                        var potentialParentRange = sortedRanges[j];
                        if (potentialParentRange.ProtectedRange.Contains(currentEHRange.ProtectedRange))
                        {
                            parentRegion = rangeToRegion[potentialParentRange.ProtectedRange];
                        }
                        if (potentialParentRange.HandlerRange.Contains(currentEHRange.HandlerRange))
                        {
                            parentRegion = rangeToRegion[potentialParentRange.HandlerRange];
                        }
                    }

                    // Insert region into graph or parent region.
                    if (parentRegion is null)
                    {
                        cfg.Regions.Add(ehRegion);
                    }
                    else
                    {
                        parentRegion.Regions.Add(ehRegion);
                    }
                }

                // Register handler region.
                var handlerRegion = new BasicControlFlowRegion <TInstruction>();
                handlerRegion.Tag = currentEHRange.UserData;
                ehRegion.HandlerRegions.Add(handlerRegion);
                rangeToRegion.Add(currentEHRange.HandlerRange, handlerRegion);
            }

            return(rangeToRegion);
        }
コード例 #3
0
        private static void EnterExceptionHandlerRegion <TInstruction>(
            IndexableStack <ScopeInfo <TInstruction> > scopeStack,
            ExceptionHandlerRegion <TInstruction> ehRegion)
        {
            var ehBlock = new ExceptionHandlerBlock <TInstruction>
            {
                Tag = ehRegion.Tag
            };

            scopeStack.Peek().AddBlock(ehBlock);
            scopeStack.Push(new ScopeInfo <TInstruction>(ehRegion, ehBlock));
        }
コード例 #4
0
        private static void EnterExceptionHandlerSubRegion <TInstruction>(
            IndexableStack <ScopeInfo <TInstruction> > scopeStack,
            ExceptionHandlerRegion <TInstruction> parentRegion,
            IControlFlowRegion <TInstruction> enteredRegion)
        {
            IBlock <TInstruction>             enteredBlock;
            IControlFlowRegion <TInstruction> enteredSubRegion;

            if (!(scopeStack.Peek().Block is ExceptionHandlerBlock <TInstruction> ehBlock))
            {
                throw new InvalidOperationException("The parent scope is not an exception handler scope.");
            }

            // Did we enter the protected region, or one of the handler regions?
            if (parentRegion.ProtectedRegion == enteredRegion)
            {
                // We entered the protected region.
                enteredBlock     = ehBlock.ProtectedBlock;
                enteredSubRegion = parentRegion.ProtectedRegion;
            }
            else
            {
                // We entered a handler region.
                var handlerRegion = parentRegion.Handlers.First(r => r == enteredRegion);
                var handlerBlock  = new HandlerBlock <TInstruction>
                {
                    Tag = handlerRegion.Tag
                };

                enteredBlock     = handlerBlock;
                enteredSubRegion = handlerRegion;
                ehBlock.Handlers.Add(handlerBlock);
            }

            // Sanity check: If the entered subregion's parent is the exception handler region but the region
            // isn't a protected, prologue, epilogue nor one of the handler regions, that would mean that
            // something went *seriously* wrong.
            if (enteredSubRegion is null)
            {
                throw new InvalidOperationException(
                          "Entered subregion of exception handler doesn't belong to any of its regions!?");
            }

            // Push the entered scope.
            scopeStack.Push(new ScopeInfo <TInstruction>(enteredSubRegion, enteredBlock));
        }
コード例 #5
0
ファイル: DominatorTreeTest.cs プロジェクト: lanicon/Echo
        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]));
        }
コード例 #6
0
ファイル: AstParser.cs プロジェクト: HoLLy-HaCKeR/Echo
        private ControlFlowRegion <Statement <TInstruction> > TransformRegion(IControlFlowRegion <TInstruction> region)
        {
            switch (region)
            {
            case BasicControlFlowRegion <TInstruction> basicRegion:
                // Create new basic region.
                var newBasicRegion = new BasicControlFlowRegion <Statement <TInstruction> >();
                TransformSubRegions(basicRegion, newBasicRegion);

                // Register basic region pair.
                _context.RegionsMapping[basicRegion] = newBasicRegion;

                return(newBasicRegion);

            case ExceptionHandlerRegion <TInstruction> ehRegion:
                var newEhRegion = new ExceptionHandlerRegion <Statement <TInstruction> >();

                // ProtectedRegion is read-only, so instead we just transform all sub regions and add it to the
                // existing protected region.
                TransformSubRegions(ehRegion.ProtectedRegion, newEhRegion.ProtectedRegion);
                _context.RegionsMapping[ehRegion.ProtectedRegion] = newEhRegion.ProtectedRegion;

                // Add handler regions.
                foreach (var subRegion in ehRegion.HandlerRegions)
                {
                    newEhRegion.HandlerRegions.Add(TransformRegion(subRegion));
                }

                return(newEhRegion);

            default:
                throw new ArgumentOutOfRangeException(nameof(region));
            }

            void TransformSubRegions(
                BasicControlFlowRegion <TInstruction> originalRegion,
                BasicControlFlowRegion <Statement <TInstruction> > newRegion)
            {
                foreach (var subRegion in originalRegion.Regions)
                {
                    newRegion.Regions.Add(TransformRegion(subRegion));
                }
            }
        }
コード例 #7
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);
        }