using Dna.Extensions; using Rivers; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; namespace Dna.ControlFlow { public class ControlFlowGraph : Graph { public ulong StartAddress { get; } public ControlFlowGraph(ulong startAddress) { Name = startAddress.ToString("X"); StartAddress = startAddress; } /// /// Creates a new basic block and adds it to the control flow graph. /// /// /// public BasicBlock CreateBlock(ulong address) { var block = new BasicBlock(address); block.Address = address; block.UserData.Add(block.Address.ToString("X"), block); Nodes.Add(block); return block; } /// /// Creates a new basic block and adds it to the control flow graph. /// /// /// public BasicBlock TryCreateBlock(ulong address) { var name = address.ToString("X"); if (Nodes.Contains(name)) return (BasicBlock)Nodes[name]; var block = new BasicBlock(address); block.Address = address; block.UserData.Add(name, block); Nodes.Add(block); return block; } public IEnumerable> GetBlocks() { return Nodes.Select(x => x.GetBlock()); } public IEnumerable GetInstructions() { return Nodes.SelectMany(x => x.GetBlock().Instructions); } public bool WhileEachBlockInReversePostOrder(BasicBlock block, Func, bool> func) { return false; } public override string ToString() { return GraphFormatter.FormatGraph(this); } public static ControlFlowGraph Clone(ControlFlowGraph src) { // Create a new destination control flow graph. var dst = new ControlFlowGraph(src.StartAddress); // Create a mapping of . var blockMapping = src.GetBlocks().ToDictionary(x => x, x => dst.CreateBlock(x.Address)); foreach((BasicBlock srcBlock, BasicBlock dstBlock) in blockMapping) { // For each source outgoing edge, create a new outgoing edge which utilizes the corresponding basic blocks in the dst control flow graph. var clonedEdges = srcBlock.GetOutgoingEdges().Select(x => new BlockEdge(blockMapping[x.SourceBlock], blockMapping[x.TargetBlock])); // Add all of the newly created outgoing edges. dstBlock.AddOutgoingEdges(clonedEdges); // Copy over the instructions. dstBlock.Instructions.AddRange(srcBlock.Instructions); } return dst; } } }