public ProcessingEntity(MethodUniqueSignature signature, ICallGraphNode node, bool virtCallRequired = false) { Signature = signature; Node = node; VirtCallRequired = virtCallRequired; }
private IEnumerable <ICallGraphNode> TraverseNodes( ICallGraphNode rootNode, ICallGraphNode levelOneNode) { lastTraversalEntryPoints.Clear(); var nodes = new HashSet <ICallGraphNode>(Nodes.Count); nodes.Add(rootNode); yield return(rootNode); var queue = new Queue <ICallGraphNode>(); queue.Enqueue(levelOneNode); while (queue.Count > 0) { var node = queue.Dequeue(); if (!nodes.Add(node)) { continue; } yield return(node); if (node.InNodes.Count == 0) { lastTraversalEntryPoints.Add(node); } else { foreach (var inNode in node.InNodes) { queue.Enqueue(inNode); } } } }
/// <summary> /// Remove redundancies and add in-edge information /// </summary> private void Optimize(SortedList <ushort, CallGraphNode> nodes) { // Remove redundant jumps directly to the next block that is not rechable from any other for (int i = 0; i < nodes.Count; i++) { CallGraphNode node = nodes.Values[i]; if ((node.NodeType == NodeType.OneBranch) && (node.OutEdges.Count == 1) && (node.OutEdges[0].InEdges.Count == 1)) { ICallGraphNode targetNode = (ICallGraphNode)node.OutEdges[0]; // Remove the jump instruction at the end of this node node.Instructions.RemoveAt(node.Instructions.Count - 1); // Add all the instructions in the next node node.EndIP = targetNode.EndIP; foreach (IInstruction instruction in targetNode.Instructions) { node.Instructions.Add(instruction); } // Remove the target node nodes.Remove(targetNode.StartIP); node.OutEdges.Clear(); ((List <IGraphNode>)node.OutEdges).AddRange(targetNode.OutEdges); foreach (CallGraphNode n in targetNode.OutEdges) { n.InEdges.Remove(targetNode); n.InEdges.Add(node); } // This node now becomes the type of the target node node.NodeType = targetNode.NodeType; } } // First pass over block list removes redundant jumps of the form // (Un)Conditional-> Unconditional jump foreach (CallGraphNode node in nodes.Values) { if ((node.OutEdges.Count == 0) && ((node.NodeType == NodeType.OneBranch) || (node.NodeType == NodeType.TwoBranch))) { for (int i = 0; i < node.OutEdges.Count; i++) { CallGraphNode newTargetNode = RemoveJump((CallGraphNode)node.OutEdges[i]); node.OutEdges[i] = newTargetNode; newTargetNode.InEdges.Add(node); } } } // Next is a depth-first traversal merging any FallThrough node or // OneBranch node that fall through to a node with that as their only in-edge. MergeFallThrough(); // Remove redundant nodes created by the optimizations }
private void GetVertexAttributes(ICallGraphNode node, out string shape, out string style, out string color, out string fontcolor) { // https://www.graphviz.org/doc/info/colors.html // https://www.graphviz.org/doc/info/shapes.html // if (!String.IsNullOrEmpty(node.PriorColor)) { shape = "box"; style = "filled"; color = node.PriorColor; fontcolor = ""; } else if (node.OutNodes.Count == 0) { shape = "box"; style = "filled"; color = "brown1"; fontcolor = ""; } else if (node.InNodes.Count == 0) { shape = "box"; style = "filled, rounded"; if (node.IsPublic) { color = "darkgreen"; fontcolor = "white"; } else { color = "darkgoldenrod1"; fontcolor = ""; } } else { shape = "box"; if (node.IsPublic) { style = "filled"; color = "green2"; } else { style = ""; color = ""; } fontcolor = ""; } }
/// <summary> /// Structures if statements /// </summary> private void StructureIfs() { List <ICallGraphNode> unresolved = new List <ICallGraphNode>(); // List of unresolved if nodes // Linear scan of nodes in reverse depth first search order for (int curr = _depthFirstSearchLast.Length - 1; curr >= 0; curr--) { List <ICallGraphNode> domDesc = new List <ICallGraphNode>(); // List of nodes dominated by curr ICallGraphNode currNode = _depthFirstSearchLast[curr]; if (currNode.NodeType == NodeType.TwoBranch) { int followInEdges = 0; int follow = 0; // Find all nodes that have this node as immediate dominator for (int desc = curr + 1; desc < _nodes.Count; desc++) { if (_depthFirstSearchLast[desc].ImmediateDominatorNumber == curr) { domDesc.Add(_depthFirstSearchLast[desc]); ICallGraphNode pbb = _depthFirstSearchLast[desc]; if ((pbb.InEdges.Count - pbb.BackEdges.Count) > followInEdges) { follow = desc; followInEdges = pbb.InEdges.Count - pbb.BackEdges.Count; } } } // Determine follow according to number of descendants // immediately dominated by this node if ((follow != 0) && (followInEdges > 1)) { currNode.IfFollow = _depthFirstSearchLast[follow]; // Flags all nodes in the list l as having follow node f, and deletes all // nodes from the list. foreach (ICallGraphNode node in unresolved) { node.IfFollow = _depthFirstSearchLast[follow]; } unresolved.Clear(); } else { unresolved.Add(currNode); } } } }
private void RemoveUnavailableNodesFrom(ICallGraphNode node) { Debug.Assert(node.InNodes.Count == 0); Nodes.Remove(node.MethodSignature); for (var i = 0; i < node.OutNodes.Count; i++) { var outNode = node.OutNodes[i]; outNode.InNodes.Remove(node); if (outNode.InNodes.Count == 0) { RemoveUnavailableNodesFrom(outNode); } } }
private void SaveVertex(ulong id, ICallGraphNode node, TextWriter writer) { GetVertexAttributes(node, out var shape, out var style, out var color, out var fontcolor); writer.Write(id); writer.Write(" ["); var isFirst = true; WriteAttribute(writer, "label", node.MethodSignature.ToShortString(), ref isFirst); WriteAttribute(writer, "shape", shape, ref isFirst); WriteAttribute(writer, "style", style, ref isFirst); WriteAttribute(writer, "fillcolor", color, ref isFirst); WriteAttribute(writer, "color", color, ref isFirst); WriteAttribute(writer, "fontcolor", fontcolor, ref isFirst); writer.WriteLine("];"); }
/// <summary> /// Structures case statements /// </summary> private void StructureCases() { // Linear scan of nodes in reverse depth first search last order, searching // for case nodes for (int i = _depthFirstSearchLast.Length - 1; i >= 0; i--) { // A case node is a node where the last instruction is a Switch opcode ICallGraphNode caseHeader = _depthFirstSearchLast[i]; if ((caseHeader.Instructions.Count > 0) && (caseHeader.Instructions[caseHeader.Instructions.Count - 1].OpCode != OpCodeTable.Switch)) { continue; } // Find descendant node which has as immediate preseccessor // the current header node ICallGraphNode exitNode = null; for (int j = i + 2; j < _depthFirstSearchLast.Length; j++) { if (_depthFirstSearchLast[j].ImmediateDominatorNumber == i) { if ((exitNode == null) || (exitNode.InEdges.Count < _depthFirstSearchLast[j].InEdges.Count)) { exitNode = _depthFirstSearchLast[j]; } } } caseHeader.CaseTail = exitNode; // Tag nodes that belong to the case by recording the header field // with caseHeader caseHeader.CaseHead = caseHeader; List <IGraphNode> caseNodes = new List <IGraphNode>(); caseNodes.Add(caseHeader); foreach (CallGraphNode childNode in caseHeader.OutEdges) { TagNodesInCase(childNode, caseNodes, caseHeader, exitNode); } if (exitNode != null) { exitNode.CaseHead = caseHeader; } } }
private void RemoveUnavailableNodesTo(ICallGraphNode node) { Debug.Assert(node.OutNodes.Count == 0); Nodes.Remove(node.MethodSignature); if (node.InNodes.Count == 0) { EntryNodes.Remove(node.MethodSignature); } for (var i = 0; i < node.InNodes.Count; i++) { var inNode = node.InNodes[i]; inNode.OutNodes.Remove(node); if (inNode.OutNodes.Count == 0) { RemoveUnavailableNodesTo(inNode); } } }
private Box LayoutSubNode(Grid grid, IGraphNode node, Dictionary <IGraphNode, Box> visited) { Box box; if (visited.TryGetValue(node, out box)) { return(box); } ICallGraphNode callGraphNode = (ICallGraphNode)node; box = new Box(String.Format("{0}\r\nDFS# x{1:x4}\r\nDom# x{2:x4}\r\nInt# {3:x4}\r\nIP x{4:x4} - x{5:x4}", callGraphNode.NodeType, node.DepthFirstSearchLastNumber, node.ImmediateDominatorNumber, 0, callGraphNode.StartIP, callGraphNode.EndIP)); visited.Add(node, box); if (node.OutEdges.Count > 0) { _lines.Add(new Line(box, LayoutSubNode(grid, node.OutEdges[0], visited))); } for (int i = 1; i < node.OutEdges.Count; i++) { if (grid[0, 0] != null) { grid.InsertColumn(0); grid.InsertRow(0); } _lines.Add(new Line(box, LayoutSubNode(grid, node.OutEdges[i], visited))); } if (grid[0, 0] != null) { grid.InsertRow(0); } grid[0, 0] = box; _boxes.Add(box); return(box); }
/// <summary> /// Recursive procedure to tag nodes that belong to the case described by /// the list l, head and tail (dfsLast index to first and exit node of the /// case). /// </summary> /// <param name="node"></param> /// <param name="l"></param> /// <param name="head"></param> /// <param name="tail"></param> private static void TagNodesInCase(CallGraphNode node, ICollection <IGraphNode> l, ICallGraphNode head, IGraphNode tail) { node.Traversed = true; if ((node != tail) && (node.Instructions.Count > 0) && (node.Instructions[node.Instructions.Count - 1].OpCode != OpCodeTable.Switch) && l.Contains(node)) { l.Add(node); node.CaseHead = head; for (int i = 0; i < node.OutEdges.Count; i++) { if (!((CallGraphNode)node.OutEdges[i]).Traversed) { TagNodesInCase((CallGraphNode)node.OutEdges[i], l, head, tail); } } } }
/// <summary> /// Loop structuring /// </summary> private void StructureLoops() { int level = 0; // Derived Sequence Level // For all derived sequences of Gi foreach (List <IGraphNode> derivedSequence in _derivedSequence) { level++; // For all intervals Ii of Gi foreach (IntervalNode interval in derivedSequence) { ICallGraphNode latchNode = null; // Find the interval head (original block node in G1) and create // list of nodes of interval Ii. IntervalNode initInt = interval; for (int i = 1; i < level; i++) { initInt = (IntervalNode)initInt.Nodes[0]; } ICallGraphNode intervalHead = (ICallGraphNode)initInt.Nodes[0]; // Find nodes that belong to the interval (nodes from G1) List <IGraphNode> intervalNodes = FindNodesInInterval(level, interval); // Find the greatest enclosing back edge (if any) for (int i = 0; i < intervalHead.InEdges.Count; i++) { ICallGraphNode pred = (ICallGraphNode)intervalHead.InEdges[i]; if (intervalNodes.Contains(pred) && (pred.DepthFirstSearchLastNumber >= intervalHead.DepthFirstSearchLastNumber)) { if (latchNode == null) { latchNode = pred; } else { if (pred.DepthFirstSearchLastNumber > latchNode.DepthFirstSearchLastNumber) { latchNode = pred; } } } } // Find nodes in the loop and the type of loop if (latchNode != null) { // Check latching node is at the same nesting level of case // statements (if any) and that the node doesnt belong to // another loop. if ((latchNode.CaseHead == intervalHead.CaseHead) && (latchNode.LoopHead == null)) { intervalHead.LatchNode = latchNode; FindNodesInLoop(latchNode, intervalHead, intervalNodes); } } } } }
/// <summary> /// Flag nodes that belong to the loop determined by (latchNode, head) and determines the type of loop /// </summary> /// <param name="latchNode"></param> /// <param name="intervalHead"></param> /// <param name="intervalNodes"></param> private void FindNodesInLoop(ICallGraphNode latchNode, ICallGraphNode intervalHead, ICollection <IGraphNode> intervalNodes) { const int Then = 0; const int Else = 1; List <int> loopNodes = new List <int>(); int headDfsNumber = intervalHead.DepthFirstSearchLastNumber; intervalHead.LoopHead = intervalHead; loopNodes.Add(headDfsNumber); for (int i = headDfsNumber + 1; i < latchNode.DepthFirstSearchLastNumber; i++) { int immediateDominator = _depthFirstSearchLast[i].ImmediateDominatorNumber; if (loopNodes.Contains(immediateDominator) && intervalNodes.Contains(_depthFirstSearchLast[i])) { loopNodes.Add(i); if (_depthFirstSearchLast[i].LoopHead == null) { _depthFirstSearchLast[i].LoopHead = _depthFirstSearchLast[headDfsNumber]; } } } latchNode.LoopHead = _depthFirstSearchLast[headDfsNumber]; if (latchNode != intervalHead) { loopNodes.Add(latchNode.DepthFirstSearchLastNumber); } // Determine type of loop and follow node NodeType intNodeType = intervalHead.NodeType; if (latchNode.NodeType == NodeType.TwoBranch) { if ((intNodeType == NodeType.TwoBranch) || (latchNode == intervalHead)) { if ((latchNode == intervalHead) || loopNodes.Contains(intervalHead.OutEdges[Then].DepthFirstSearchLastNumber) && loopNodes.Contains(intervalHead.OutEdges[Else].DepthFirstSearchLastNumber)) { intervalHead.LoopType = LoopType.Do; if (latchNode.OutEdges[0] == intervalHead) { intervalHead.LoopFollow = (ICallGraphNode)latchNode.OutEdges[Else]; } else { intervalHead.LoopFollow = (ICallGraphNode)latchNode.OutEdges[Then]; } } else { intervalHead.LoopType = LoopType.While; if (loopNodes.Contains(intervalHead.OutEdges[Then].DepthFirstSearchLastNumber)) { intervalHead.LoopFollow = (ICallGraphNode)intervalHead.OutEdges[Else]; } else { intervalHead.LoopFollow = (ICallGraphNode)intervalHead.OutEdges[Then]; } } } else { intervalHead.LoopType = LoopType.Do; if (loopNodes.Contains(intervalHead.OutEdges[Then].DepthFirstSearchLastNumber)) { intervalHead.LoopFollow = (ICallGraphNode)intervalHead.OutEdges[Else]; } else { intervalHead.LoopFollow = (ICallGraphNode)intervalHead.OutEdges[Then]; } } } else if (latchNode.NodeType == NodeType.OneBranch) { intervalHead.LoopType = LoopType.Do; intervalHead.LoopFollow = (ICallGraphNode)latchNode.OutEdges[0]; } else if (intNodeType == NodeType.TwoBranch) { intervalHead.LoopType = LoopType.While; ICallGraphNode pbb = latchNode; int thenDfs = intervalHead.OutEdges[Then].DepthFirstSearchLastNumber; int elseDfs = intervalHead.OutEdges[Else].DepthFirstSearchLastNumber; while (true) { if (pbb.DepthFirstSearchLastNumber == thenDfs) { intervalHead.LoopFollow = _depthFirstSearchLast[elseDfs]; break; } if (pbb.DepthFirstSearchLastNumber == elseDfs) { intervalHead.LoopFollow = _depthFirstSearchLast[thenDfs]; break; } // Check if couldn't find it, then its a stragenly formed // loop, so it is safer to consider it an endless loop if (pbb.DepthFirstSearchLastNumber <= intervalHead.DepthFirstSearchLastNumber) { intervalHead.LoopType = LoopType.Endless; break; } pbb = _depthFirstSearchLast[pbb.ImmediateDominatorNumber]; } if (pbb.DepthFirstSearchLastNumber > intervalHead.DepthFirstSearchLastNumber) { intervalHead.LoopFollow.LoopHead = null; } } else { intervalHead.LoopType = LoopType.Endless; } }
private void Link(ICallGraphNode from, ICallGraphNode to) { from.OutNodes.Add(to); to.InNodes.Add(from); }
public ShadowNode(ICallGraphNode node) { this.node = node; }