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))); } }
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]);
/// <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); }
/// <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]); }
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 }
/// <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, }); }
/// <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; }