Ejemplo n.º 1
0
        private void AddAbnormalEdges(ControlFlowGraph graph)
        {
            if (graph.SubGraphs.Count == 0)
            {
                return;
            }

            // Since exception handlers make it possible to transfer control to the handler block
            // at any time, we have these "abnormal edges" from each node in the try block
            // to the first node in the handler block (or filter block).

            // First, add the initial abnormal handler edges from every try-start to the handler-start (or filter start).
            // This allows us to do some more dominator-magic, where we can just infer the handler body based
            // on the nodes dominated by the handler node.
            foreach (var subGraph in graph.SubGraphs.OrderBy(x => x.Nodes.Count))
            {
                var ehFrame = (EHFrame)subGraph.UserData[EHFrame.EHFrameProperty];

                // Find the try entry node.
                var tryEntry = GetNode(graph, (long)ehFrame.TryStart);
                tryEntry.UserData[ControlFlowGraph.TryStartProperty] = ehFrame;

                // Find the handler entry node.
                var handlerEntry = GetNode(graph, (long)ehFrame.HandlerAddress);
                handlerEntry.UserData[ControlFlowGraph.HandlerStartProperty] = ehFrame;

                // Add initial abnormal edge.
                if (ehFrame.Type != EHType.FILTER)
                {
                    // Jump straight to the handler entry.
                    AddAbnormalEdge(graph, tryEntry, ehFrame, handlerEntry);
                }
                else
                {
                    // Jump to the filter entry.
                    var filterEntry = GetNode(graph, (long)ehFrame.FilterAddress);
                    filterEntry.UserData[ControlFlowGraph.FilterStartProperty] = ehFrame;
                    AddAbnormalEdge(graph, tryEntry, ehFrame, filterEntry);

                    // Connect all terminators of the filter block to the handler entry.
                    foreach (var terminator in FindReachableReturnNodes(filterEntry))
                    {
                        AddAbnormalEdge(graph, terminator, ehFrame, handlerEntry);
                    }
                }
            }

            // Obtain dominator info.
            var dominatorInfo = new DominatorInfo(graph.Entrypoint);

            // Add all handler nodes to the cluster, and add abnormal edges for each try node to the handler start node.
            var handlerExits = new Dictionary <EHFrame, ICollection <Node> >();

            foreach (var subGraph in graph.SubGraphs.OrderBy(x => x.Nodes.Count))
            {
                var ehFrame      = (EHFrame)subGraph.UserData[EHFrame.EHFrameProperty];
                var tryEntry     = GetNode(graph, (long)ehFrame.TryStart);
                var handlerEntry = GetNode(graph, (long)ehFrame.HandlerAddress);

                // Determine the handler exits.
                var handlerBody = CollectHandlerNodes(handlerEntry, dominatorInfo.GetDominatedNodes(handlerEntry));
                foreach (var handlerNode in handlerBody)
                {
                    subGraph.Nodes.Add(handlerNode);
                }

                handlerExits.Add(ehFrame, new HashSet <Node>(handlerBody.Where(x => x.OutgoingEdges.Count == 0)));

                // Add for each node in the try block an abnormal edge.
                var tryBody = new HashSet <Node>(subGraph.Nodes.Except(handlerBody));
                foreach (var node in tryBody.Where(n =>
                                                   !n.UserData.ContainsKey(ControlFlowGraph.TopMostEHProperty) && n != tryEntry))
                {
                    AddAbnormalEdge(graph, node, ehFrame, handlerEntry);
                }

                // Register EH boundaries in the sub graph.
                subGraph.UserData[ControlFlowGraph.TryBlockProperty]     = tryBody;
                subGraph.UserData[ControlFlowGraph.HandlerBlockProperty] = handlerBody;

                if (ehFrame.Type == EHType.FILTER)
                {
                    var filterEntry = GetNode(graph, (long)ehFrame.FilterAddress);
                    subGraph.UserData[ControlFlowGraph.FilterStartProperty] = filterEntry;
                }
            }

            // Since a LEAVE instruction might not directly transfer control to the referenced instruction,
            // but rather transfer control to a finally block first,  we have to add edges to these nodes
            // as well.

            foreach (var node in graph.Nodes)
            {
                if (node.SubGraphs.Count > 0)
                {
                    // Check if the node ends with a LEAVE.
                    var block = GetUserData <ILBasicBlock>(node, ILBasicBlock.BasicBlockProperty);
                    if (block == null)
                    {
                        continue;
                    }

                    var last = block.Instructions[block.Instructions.Count - 1];
                    if (last.OpCode.Code == ILCode.LEAVE)
                    {
                        // Find the frame we're jumping out of.
                        var ehFrame = last.ProgramState.EHStack.Peek();

                        // Add for each handler exit an edge to the referenced instruction.
                        foreach (var exit in handlerExits[ehFrame])
                        {
                            var edge = CreateEdge(exit, node.OutgoingEdges.First().Target, ControlFlowGraph.EndFinallyConditionLabel);
                            exit.UserData[ControlFlowGraph.TopMostEHProperty] = ehFrame;
                            graph.Edges.Add(edge);
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
 private void AddFallThroughEdge(ControlFlowGraph graph, Node node, long nextOffset)
 {
     node.OutgoingEdges.Add(GetNode(graph, nextOffset));
 }