private static void ConnectNodesWithExceptionHandlers(ControlFlowGraph cfg, IEnumerable <ProtectedBlock> protectedBlocks, IDictionary <string, CFGNode> leaders) { var activeProtectedBlocks = new HashSet <ProtectedBlock>(); var protectedBlocksStart = protectedBlocks.ToLookup(pb => pb.Start); var protectedBlocksEnd = protectedBlocks.ToLookup(pb => pb.End); foreach (var entry in leaders) { var label = entry.Key; var node = entry.Value; if (protectedBlocksStart.Contains(label)) { var startingProtectedBlocks = protectedBlocksStart[label]; activeProtectedBlocks.UnionWith(startingProtectedBlocks); } if (protectedBlocksEnd.Contains(label)) { var endingProtectedBlocks = protectedBlocksEnd[label]; activeProtectedBlocks.ExceptWith(endingProtectedBlocks); } // Connect each node inside a try block to the first corresponding handler block foreach (var block in activeProtectedBlocks) { var target = leaders[block.Handler.Start]; cfg.ConnectNodes(node, target); } } }
public static ControlFlowGraph GenerateNormalControlFlow(MethodBody method) { var instructions = ControlFlowGraph.FilterExceptionHandlers(method); var leaders = ControlFlowGraph.CreateNodes(instructions); var cfg = ControlFlowGraph.ConnectNodes(instructions, leaders); return(cfg); }
public static ControlFlowGraph GenerateExceptionalControlFlow(MethodBody method) { var instructions = method.Instructions; var leaders = ControlFlowGraph.CreateNodes(instructions); var cfg = ControlFlowGraph.ConnectNodes(instructions, leaders); ControlFlowGraph.ConnectNodesWithExceptionHandlers(cfg, method.ProtectedBlocks, leaders); return(cfg); }
private static ControlFlowGraph ConnectNodes(IEnumerable <Instruction> instructions, IDictionary <string, CFGNode> leaders) { var cfg = new ControlFlowGraph(); var connectWithPreviousNode = true; var current = cfg.Entry; CFGNode previous; foreach (var instruction in instructions) { if (leaders.ContainsKey(instruction.Label)) { previous = current; current = leaders[instruction.Label]; // A node cannot fallthrough itself, // unless it contains another // instruction with the same label // of the node's leader instruction if (connectWithPreviousNode && previous.Id != current.Id) { cfg.ConnectNodes(previous, current); } } connectWithPreviousNode = true; current.Instructions.Add(instruction); if (instruction is BranchInstruction) { var branch = instruction as BranchInstruction; var target = leaders[branch.Target]; cfg.ConnectNodes(current, target); if (branch is UnconditionalBranchInstruction) { connectWithPreviousNode = false; } } else if (instruction is SwitchInstruction) { var branch = instruction as SwitchInstruction; foreach (var label in branch.Targets) { var target = leaders[label]; cfg.ConnectNodes(current, target); } } else if (instruction is ReturnInstruction || instruction is ThrowInstruction) { //TODO: not always connect to exit, could exists a catch or finally block cfg.ConnectNodes(current, cfg.Exit); } } cfg.ConnectNodes(current, cfg.Exit); return(cfg); }