/// <summary> /// Collects weakly connected components from the ICFG and gathers /// them into Clusters. /// </summary> public List <Cluster> FindClusters() { var nodesLeft = new HashSet <RtlBlock>(sr.ICFG.Nodes); var clusters = new List <Cluster>(); int totalCount = nodesLeft.Count; if (totalCount > 0) { listener.ShowProgress("Finding procedure candidates", 0, totalCount); var wl = WorkList.Create(nodesLeft); while (wl.TryGetWorkItem(out var node)) { if (listener.IsCanceled()) { break; } var cluster = new Cluster(); clusters.Add(cluster); BuildWCC(node, cluster, wl); sr.BreakOnWatchedAddress(cluster.Blocks.Select(b => b.Address)); listener.ShowProgress("Finding procedure candidates", totalCount - nodesLeft.Count, totalCount); } } return(clusters); }
/// <summary> /// As far as possible, try fusing consecutive linear blocks in the /// cluster. /// </summary> /// <param name="cluster"></param> public void FuseLinearBlocks(Cluster cluster) { var wl = WorkList.Create(cluster.Blocks); while (wl.TryGetWorkItem(out var block)) { if (sr.ICFG.Successors(block).Count != 1) { continue; } var succ = sr.ICFG.Successors(block).First(); if (sr.ICFG.Predecessors(succ).Count != 1) { continue; } Debug.Assert(sr.ICFG.Predecessors(succ).First() == block, "Inconsistent graph"); if (!(block.Instructions.Last().Instructions.Last() is RtlAssignment)) { continue; } // Move all instructions into predecessor. block.Instructions.AddRange(succ.Instructions); sr.ICFG.RemoveEdge(block, succ); var succSuccs = sr.ICFG.Successors(succ).ToList(); foreach (var ss in succSuccs) { sr.ICFG.RemoveEdge(succ, ss); sr.ICFG.AddEdge(block, ss); } cluster.Blocks.Remove(succ); // May be more blocks. wl.Add(block); } }
public override Dictionary <string, IDictionary <Address, IAddressable> > GetObjectPlacements(string fileExtension, DecompilerEventListener listener) { this.defaultFile = Path.ChangeExtension(program.Name, fileExtension); this.defaultDataFile = Path.ChangeExtension(program.Name, "globals" + fileExtension); // Find the segment for each procedure var result = new Dictionary <string, IDictionary <Address, IAddressable> >(); foreach (var proc in program.Procedures.Values) { PlaceObject(proc, defaultFile, result); } // Place all global objects. var wl = WorkList.Create( MakeGlobalWorkItems() .Concat(MakeSegmentWorkitems())); var objectTracer = new GlobalObjectTracer(program, wl, listener); while (wl.TryGetWorkItem(out var item)) { var(field, addr) = item; var globalVar = new GlobalVariable(addr, field.DataType, program.NamingPolicy.GlobalName(field)); PlaceObject(globalVar, defaultDataFile, result); objectTracer.TraceObject(field.DataType, addr); } return(result); }
public void Transform() { var wl = WorkList.Create(ssa.Procedure.Statements); while (wl.TryGetWorkItem(out var stm)) { var prjf = new ProjectionFilter(ssa, stm, sac); var instr = stm.Instruction.Accept(prjf); stm.Instruction = instr; wl.AddRange(prjf.NewStatements); } }
/// <summary> /// For each procedure/SSA state, compute the variables that are live-out /// (and which bit ranges are live-out) and store them in the procedure flow. /// </summary> private void CollectLiveOutStorages() { var wl = WorkList.Create(ssaStates); while (wl.TryGetWorkItem(out SsaState ssa)) { var liveOut = CollectLiveOutStorages(ssa.Procedure); var flow = dataFlow.ProcedureFlows[ssa.Procedure]; var changed = MergeLiveOut(flow, liveOut); if (changed) { wl.AddRange(program.CallGraph.Callees(ssa.Procedure).Select(p => procToSsa[p])); } } }
public DataType BuildOverlappedStructure(List <StructureField> fields) { List <StructureType> types = new List <StructureType>(); int commonOffset = CommonOffset(fields); var worklist = WorkList.Create(fields); while (worklist.TryGetWorkItem(out StructureField field)) { StructureType?s = FindStructureToFitIn(field, commonOffset, types); if (s == null) { s = new StructureType(); types.Add(s); } s.Fields.Add(new StructureField(field.Offset - commonOffset, field.DataType)); } return(Normalize(types)); }
public void Transform() { var wl = WorkList.Create(proc.ControlGraph.Blocks); while (wl.TryGetWorkItem(out Block block)) { if (listener.IsCanceled()) { return; } var c = DetermineCandidate(block); if (c == null) { continue; } FuseIntoPredecessor(c); // We may need to mutate the predecessor again. wl.Add(c.Predecessor !); } }
static void MergeChildNodes(XElement dst, XElement src) { var dstNodes = WorkList.Create(dst); var srcNodes = WorkList.Create(src); // First skip all _identical_ nodes // (doesn't actually merge anything, just removes identical nodes from work list) MergeNodesBothDirections( dstNodes, srcNodes, DeepEquals); // First merge all where name matches MergeNodesBothDirections( dstNodes, srcNodes, (dstNode, srcNode) => { if (dstNode.NodeType != srcNode.NodeType) { return(false); } if (dstNode.NodeType == XmlNodeType.Element) { if (((XElement)dstNode).Name != ((XElement)srcNode).Name) { return(false); } } Merge(dstNode, srcNode); return(true); }); // Then merge all where only node type matches MergeNodesBothDirections( dstNodes, srcNodes, (dstNode, srcNode) => { if (dstNode.NodeType != srcNode.NodeType) { return(false); } Merge(dstNode, srcNode); return(true); }); while (!dstNodes.IsEmpty) { var node = dstNodes.Pop(Position.Tail); node.Remove(); } XNode dstInsertPoint = null; while (!srcNodes.IsEmpty) { // We need to know where to insert this. var srcNode = srcNodes.Pop(Position.Head); var dstNode = CloneNode(srcNode); if (dstInsertPoint == null) { var srcIndex = srcNode.NodeIndex(); if (srcIndex == 0) { dst.AddFirst(dstNode); } else { dstInsertPoint = dst.FirstNode; // Insert point will be element before srcNode index for (int dstIndex = 0; dstIndex < (srcIndex - 1); dstIndex++) { dstInsertPoint = dstInsertPoint.NextNode; } dstInsertPoint.AddAfterSelf(dstNode); } } else { dstInsertPoint.AddAfterSelf(dstNode); } dstInsertPoint = dstNode; } }
static void MergeChildNodes(IUxContainerInternals dst, IUxContainerInternals src) { var dstNodes = WorkList.Create(dst); var srcNodes = WorkList.Create(src); // First skip all _identical_ nodes // (doesn't actually merge anything, just removes identical nodes from work list) MergeNodesBothDirections( dstNodes, srcNodes, DeepEquals); // First merge all where name matches MergeNodesBothDirections( dstNodes, srcNodes, (dstNode, srcNode) => { if (dstNode.NodeType != srcNode.NodeType) { return(false); } if (dstNode.NodeType == XmlNodeType.Element) { if (((UxElement)dstNode).Name != ((UxElement)srcNode).Name) { return(false); } } Merge(dstNode, srcNode); return(true); }); // Then merge all where only node type matches MergeNodesBothDirections( dstNodes, srcNodes, (dstNode, srcNode) => { if (dstNode.NodeType != srcNode.NodeType) { return(false); } Merge(dstNode, srcNode); return(true); }); while (!dstNodes.IsEmpty) { var node = dstNodes.Pop(Position.Tail); node.Remove(); } while (!srcNodes.IsEmpty) { // We need to know where to insert this. var srcNode = srcNodes.Pop(Position.Head); var dstNode = CloneNode(srcNode); dst.Nodes.Insert(srcNode.NodeIndex, dstNode); } }