예제 #1
0
        public void Dump(string caption)
        {
            return;     // This is horribly verbose, so only use it when debugging unit tests.

            Debug.Print("== {0} =====================", caption);
            Debug.Print("{0} nodes", G.Nodes.Count);
            foreach (var block in G.Nodes.OrderBy(n => n))
            {
                Debug.Print("{0}:  //  pred: {1}",
                            block,
                            string.Join(" ", G.Successors(block)
                                        .OrderBy(n => n)));
                RtlInstructionCluster cluster;
                if (!sr.Instructions.TryGetValue(block, out cluster))
                {
                    Debug.Print("  *****");
                }
                else
                {
                    Debug.Print("  {0}", cluster);
                    foreach (var instr in cluster.Instructions)
                    {
                        Debug.Print("    {0}", instr);
                    }
                }
                Debug.Print("  // succ: {0}", string.Join(" ", G.Predecessors(block)
                                                          .OrderBy(n => n)));
            }
        }
예제 #2
0
        public (DirectedGraph <Region>, Region) Build()
        {
            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock ||
                    b == proc.ExitBlock)
                {
                    continue;
                }
                var reg = regionFactory.Create(b);
                btor.Add(b, reg);
                graph.AddNode(reg);
            }

            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (btor.TryGetValue(b, out var reg) &&
                    reg.Type == RegionType.IncSwitch)
                {
                    MakeSwitchPads(b);
                }
            }

            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock)
                {
                    continue;
                }
                btor.TryGetValue(b, out var from);
                foreach (var s in b.Succ)
                {
                    if (s == proc.ExitBlock)
                    {
                        continue;
                    }
                    var to = Destination(b, s);
                    graph.AddEdge(from, to);
                }
                if (from != null)
                {
                    if (graph.Successors(from).Count == 0)
                    {
                        from.Type = RegionType.Tail;
                    }
                }
            }

            foreach (var reg in graph.Nodes.ToList())
            {
                if (graph.Predecessors(reg).Count == 0 && reg != btor[proc.EntryBlock])
                {
                    graph.Nodes.Remove(reg);
                }
            }
            return(graph, btor[proc.EntryBlock]);
예제 #3
0
        /// <summary>
        /// Build Shingle blocks from the graph. An instruction can only be
        /// in one block at a time, so at each point in the graph where the
        /// successors > 1 or the predecessors > 1, we create a new node.
        /// </summary>
        /// <param name="g"></param>
        /// <param name="instructions"></param>
        /// <returns></returns>
        public SortedList <Address, ShingleBlock> BuildBlocks(
            DiGraph <Address> g,
            SortedList <Address, MachineInstruction> instructions)
        {
            // Remember, the graph is backwards!
            var activeBlocks = new List <ShingleBlock>();
            var allBlocks    = new SortedList <Address, ShingleBlock>();
            var wl           = instructions.Keys.ToSortedSet();

            while (wl.Count > 0)
            {
                var addr = wl.First();
                wl.Remove(addr);
                var instr = instructions[addr];
                var block = new ShingleBlock {
                    BaseAddress = addr
                };
                allBlocks.Add(addr, block);
                bool terminateNow      = false;
                bool terminateDeferred = false;
                for (;;)
                {
                    var addrInstrEnd = instr.Address + instr.Length;
                    if ((instr.InstructionClass & InstructionClass.Transfer) != 0)
                    {
                        if ((instr.InstructionClass & DT) == DT)
                        {
                            terminateDeferred = true;
                        }
                        else
                        {
                            terminateNow = true;
                        }
                    }
                    else
                    {
                        terminateNow = terminateDeferred;
                    }
                    if (terminateNow ||
                        !wl.Contains(addrInstrEnd) ||
                        !g.Nodes.Contains(addrInstrEnd) ||
                        g.Successors(addrInstrEnd).Count != 1)
                    {
                        block.EndAddress = addrInstrEnd;
                        break;
                    }

                    wl.Remove(addrInstrEnd);
                    instr        = instructions[addrInstrEnd];
                    terminateNow = terminateDeferred;
                }
            }
            return(allBlocks);
        }
예제 #4
0
        /// <summary>
        /// Builds a graph of regions based on the basic blocks of the code.
        /// </summary>
        /// <param name="proc"></param>
        /// <returns></returns>
        public Tuple<DirectedGraph<Region>, Region> BuildRegionGraph(Procedure proc)
        {
            var btor = new Dictionary<Block, Region>();
            var regs = new DiGraph<Region>();
            var regionFactory = new RegionFactory();
            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock ||
            
                            b == proc.ExitBlock)
                    continue;
                var reg = regionFactory.Create(b);
                btor.Add(b, reg);
                regs.AddNode(reg);
            }
            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock)
                    continue;
                Region from;
                btor.TryGetValue(b, out from);
                foreach (var s in b.Succ)
                {
                    if (s == proc.ExitBlock)
                        continue;
                    var to = btor[s];
                    regs.AddEdge(from, to);
                }
                if (from != null)
                {
                    if (regs.Successors(from).Count == 0)
                        from.Type = RegionType.Tail;
                }
            }

            foreach (var reg in regs.Nodes.ToList())
            {
                if (regs.Predecessors(reg).Count == 0 && reg != btor[proc.EntryBlock])
                {
                    regs.Nodes.Remove(reg);
                }
            }
            return new Tuple<DirectedGraph<Region>, Region>(regs, btor[proc.EntryBlock]);
        }
예제 #5
0
        public void Dump(string caption = "Dump")
        {
            //BreakOnWatchedAddress(ICFG.Nodes.Select(n => n.Address));

            return;     // This is horribly verbose, so only use it when debugging unit tests.

#if VERBOSE
            Debug.Print("== {0} =====================", caption);
            Debug.Print("{0} nodes", ICFG.Nodes.Count);
            foreach (var block in ICFG.Nodes.OrderBy(n => n.Address))
            {
                var addrEnd = block.GetEndAddress();
                if (KnownProcedures.Contains(block.Address))
                {
                    Debug.WriteLine("");
                    Debug.Print("-- {0}: known procedure ----------", block.Address);
                }
                else if (DirectlyCalledAddresses.ContainsKey(block.Address))
                {
                    Debug.WriteLine("");
                    Debug.Print("-- {0}: possible procedure, called {1} time(s) ----------",
                                block.Address,
                                DirectlyCalledAddresses[block.Address]);
                }
                Debug.Print("{0}:  //  pred: {1}",
                            block.Name,
                            string.Join(" ", ICFG.Predecessors(block)
                                        .OrderBy(n => n.Address)
                                        .Select(n => n.Address)));
                foreach (var cluster in block.Instructions)
                {
                    Debug.Print("  {0}", cluster);
                    foreach (var instr in cluster.Instructions)
                    {
                        Debug.Print("    {0}", instr);
                    }
                }
                Debug.Print("  // succ: {0}", string.Join(" ", ICFG.Successors(block)
                                                          .OrderBy(n => n.Address)
                                                          .Select(n => n.Address)));
            }
#endif
        }
예제 #6
0
        /// <summary>
        /// Build Shingle blocks from the graph. An instruction can only be
        /// in one block at a time, so at each point in the graph where the
        /// successors > 1 or the predecessors > 1, we create a new node.
        /// </summary>
        /// <param name="instructions"></param>
        /// <returns></returns>
        public IcfgBuilder BuildBlocks(DiGraph <Address> graph)
        {
            // Remember, the graph is backwards!
            var activeBlocks = new List <RtlBlock>();
            var allBlocks    = new DiGraph <RtlBlock>();
            var edges        = new List <Tuple <RtlBlock, Address> >();
            var mpBlocks     = new Dictionary <Address, RtlBlock>();
            var wl           = sr.Instructions.Keys.ToSortedSet();

            while (wl.Count > 0)
            {
                var addr = wl.First();
                wl.Remove(addr);

                var instr = sr.Instructions[addr];
                var label = program.NamingPolicy.BlockName(addr);
                var block = new RtlBlock(addr, label);
                block.Instructions.Add(instr);
                allBlocks.AddNode(block);
                mpBlocks.Add(addr, block);
                bool endBlockNow                = false;
                bool terminateDeferred          = false;
                bool addFallthroughEdge         = false;
                bool addFallthroughEdgeDeferred = false;
                for (;;)
                {
                    var addrInstrEnd = instr.Address + instr.Length;
                    if ((instr.Class & DT) != 0)
                    {
                        if (MayFallThrough(instr))
                        {
                            addFallthroughEdge         = (instr.Class & DT) == T;
                            addFallthroughEdgeDeferred = (instr.Class & DT) == DT;
                        }
                        var addrDst = DestinationAddress(instr);
                        if (addrDst != null && (instr.Class & InstrClass.Call) == 0)
                        {
                            edges.Add(Tuple.Create(block, addrDst));
                        }

                        if ((instr.Class & DT) == DT)
                        {
                            terminateDeferred = true;
                        }
                        else
                        {
                            endBlockNow = true;
                        }
                    }
                    else if (instr.Class == InstrClass.Terminates)
                    {
                        endBlockNow        = true;
                        addFallthroughEdge = false;
                        addFallthroughEdge = false;
                    }
                    else
                    {
                        endBlockNow                = terminateDeferred;
                        addFallthroughEdge         = addFallthroughEdgeDeferred;
                        addFallthroughEdgeDeferred = false;
                    }

                    if (sr.DirectlyCalledAddresses.Keys.Contains(addrInstrEnd) ||
                        sr.KnownProcedures.Contains(addrInstrEnd))
                    {
                        // If control falls into what looks like a procedure, don't
                        // add an edge.
                        addFallthroughEdge = false;
                        endBlockNow        = true;
                    }
                    if (addFallthroughEdge)
                    {
                        edges.Add(Tuple.Create(block, addrInstrEnd));
                    }

                    if (endBlockNow ||
                        !wl.Contains(addrInstrEnd) ||
                        !graph.Nodes.Contains(addrInstrEnd) ||
                        graph.Successors(addrInstrEnd).Count != 1)
                    {
                        //Debug.Print("addr: {0}, end {1}, term: {2}, wl: {3}, nodes: {4}, succ: {5}",
                        //    addr,
                        //    addrInstrEnd,
                        //    endBlockNow,
                        //    !wl.Contains(addrInstrEnd),
                        //    !graph.Nodes.Contains(addrInstrEnd),
                        //    graph.Nodes.Contains(addrInstrEnd)
                        //        ? graph.Successors(addrInstrEnd).Count
                        //        : 0);

                        if (!endBlockNow && !addFallthroughEdge)
                        {
                            edges.Add(Tuple.Create(block, addrInstrEnd));
                        }
                        break;
                    }

                    wl.Remove(addrInstrEnd);
                    instr = sr.Instructions[addrInstrEnd];
                    block.Instructions.Add(instr);
                    endBlockNow = terminateDeferred;
                }
            }
            return(new IcfgBuilder
            {
                Edges = edges,
                AddrToBlock = mpBlocks,
                Blocks = allBlocks,
            });
        }
예제 #7
0
        /// <summary>
        /// Build Shingle blocks from the graph. An instruction can only be 
        /// in one block at a time, so at each point in the graph where the 
        /// successors > 1 or the predecessors > 1, we create a new node.
        /// </summary>
        /// <param name="g"></param>
        /// <param name="instructions"></param>
        /// <returns></returns>
        public SortedList<Address,ShingleBlock> BuildBlocks(
            DiGraph<Address> g,
            SortedList<Address,MachineInstruction> instructions)
        {
            // Remember, the graph is backwards!
            var activeBlocks = new List<ShingleBlock>();
            var allBlocks = new SortedList<Address, ShingleBlock>();
            var wl = instructions.Keys.ToSortedSet();
            while (wl.Count > 0)
            {
                var addr = wl.First();
                wl.Remove(addr);
                var instr = instructions[addr];
                var block = new ShingleBlock { BaseAddress = addr };
                allBlocks.Add(addr, block);
                bool terminateNow = false;
                bool terminateDeferred = false;
                for (;;)
                {
                    var addrInstrEnd = instr.Address + instr.Length;
                    if ((instr.InstructionClass & InstructionClass.Transfer) != 0)
                    {
                        if ((instr.InstructionClass & DT) == DT)
                        {
                            terminateDeferred = true;
                        }
                        else
                        {
                            terminateNow = true;
                        }
                    }
                    else
                    {
                        terminateNow = terminateDeferred;
                    }
                    if (terminateNow || 
                        !wl.Contains(addrInstrEnd) ||
                        !g.Nodes.Contains(addrInstrEnd) || 
                        g.Successors(addrInstrEnd).Count != 1)
                    {
                        block.EndAddress = addrInstrEnd;
                        break;
                    }

                    wl.Remove(addrInstrEnd);
                    instr = instructions[addrInstrEnd];
                    terminateNow = terminateDeferred;
                }
            }
            return allBlocks;
        }