Search in sources :

Example 1 with Block

use of soot.toolkits.graph.Block in project soot by Sable.

the class GroupIntPair method calculateStackHeight.

private void calculateStackHeight(Block aBlock) {
    int blockHeight = blockToStackHeight.get(aBlock).intValue();
    if (blockHeight > maxStackHeight) {
        maxStackHeight = blockHeight;
    }
    for (Unit u : aBlock) {
        Inst nInst = (Inst) u;
        blockHeight -= nInst.getInMachineCount();
        if (blockHeight < 0) {
            throw new RuntimeException("Negative Stack height has been attained in :" + aBlock.getBody().getMethod().getSignature() + " \n" + "StackHeight: " + blockHeight + "\n" + "At instruction:" + nInst + "\n" + "Block:\n" + aBlock + "\n\nMethod: " + aBlock.getBody().getMethod().getName() + "\n" + aBlock.getBody().getMethod());
        }
        blockHeight += nInst.getOutMachineCount();
        if (blockHeight > maxStackHeight) {
            maxStackHeight = blockHeight;
        }
    // logger.debug(">>> " + nInst + " " + blockHeight);
    }
    for (Block b : aBlock.getSuccs()) {
        Integer i = blockToStackHeight.get(b);
        if (i != null) {
            if (i.intValue() != blockHeight) {
                throw new RuntimeException(aBlock.getBody().getMethod().getSignature() + ": incoherent stack height at block merge point " + b + aBlock + "\ncomputed blockHeight == " + blockHeight + " recorded blockHeight = " + i.intValue());
            }
        } else {
            blockToStackHeight.put(b, new Integer(blockHeight));
            calculateStackHeight(b);
        }
    }
}
Also used : Block(soot.toolkits.graph.Block) Unit(soot.Unit)

Example 2 with Block

use of soot.toolkits.graph.Block in project soot by Sable.

the class Region method getUnits.

public List<Unit> getUnits() {
    if (this.m_units == null) {
        this.m_units = new LinkedList<Unit>();
        for (Iterator<Block> itr = this.m_blocks.iterator(); itr.hasNext(); ) {
            Block b = itr.next();
            for (Iterator<Unit> itr1 = b.iterator(); itr1.hasNext(); ) {
                Unit u = itr1.next();
                ((LinkedList<Unit>) this.m_units).addLast(u);
            }
        }
    }
    return this.m_units;
}
Also used : Block(soot.toolkits.graph.Block) Unit(soot.Unit) LinkedList(java.util.LinkedList)

Example 3 with Block

use of soot.toolkits.graph.Block in project soot by Sable.

the class RegionAnalysis method CFGtoString.

public static String CFGtoString(DirectedGraph<Block> cfg, boolean blockDetail) {
    String s = "";
    s += "Headers: " + cfg.getHeads().size() + " " + cfg.getHeads();
    for (Block node : cfg) {
        s += "Node = " + node.toShortString() + "\n";
        s += "Preds:\n";
        for (Iterator<Block> predsIt = cfg.getPredsOf(node).iterator(); predsIt.hasNext(); ) {
            s += "     ";
            s += predsIt.next().toShortString() + "\n";
        }
        s += "Succs:\n";
        for (Iterator<Block> succsIt = cfg.getSuccsOf(node).iterator(); succsIt.hasNext(); ) {
            s += "     ";
            s += succsIt.next().toShortString() + "\n";
        }
    }
    if (blockDetail) {
        s += "Blocks Detail:";
        for (Iterator<Block> it = cfg.iterator(); it.hasNext(); ) {
            Block node = it.next();
            s += node + "\n";
        }
    }
    return s;
}
Also used : Block(soot.toolkits.graph.Block)

Example 4 with Block

use of soot.toolkits.graph.Block in project soot by Sable.

the class HashMutablePDG method constructPDG.

/**
 * This is the heart of the PDG contruction. It is huge and definitely needs
 * some refactorings, but since it's been evlovong to cover some boundary cases
 * it has become hard to rafactor.
 *
 * It uses the list of weak regions, along with the dominator and post-dominator
 * trees to construct the PDG nodes.
 */
protected void constructPDG() {
    Hashtable<Block, Region> block2region = this.m_regionAnalysis.getBlock2RegionMap();
    DominatorTree<Block> pdom = this.m_regionAnalysis.getPostDominatorTree();
    DominatorTree<Block> dom = this.m_regionAnalysis.getDominatorTree();
    List<Region> regions2process = new LinkedList<Region>();
    Region topLevelRegion = this.m_regionAnalysis.getTopLevelRegion();
    m_strongRegionStartID = m_weakRegions.size();
    // This becomes the top-level region (or ENTRY region node)
    PDGNode pdgnode = new PDGNode(topLevelRegion, PDGNode.Type.REGION);
    this.addNode(pdgnode);
    this.m_obj2pdgNode.put(topLevelRegion, pdgnode);
    this.m_startNode = pdgnode;
    topLevelRegion.setParent(null);
    Set<Region> processedRegions = new HashSet<Region>();
    regions2process.add(topLevelRegion);
    // while there's a (weak) region to process
    while (!regions2process.isEmpty()) {
        Region r = regions2process.remove(0);
        processedRegions.add(r);
        // get the corresponding pdgnode
        pdgnode = this.m_obj2pdgNode.get(r);
        /*
			 * For all the CFG nodes in the region, create the corresponding PDG node and edges, and
			 * process them if they are in the dependence set of other regions, i.e. other regions
			 * depend on them.
			 */
        List<Block> blocks = r.getBlocks();
        Hashtable<Region, List<Block>> toBeRemoved = new Hashtable<Region, List<Block>>();
        PDGNode prevPDGNodeInRegion = null;
        PDGNode curNodeInRegion = null;
        for (Iterator<Block> itr = blocks.iterator(); itr.hasNext(); ) {
            /*
				 * Add the PDG node corresponding to the CFG block node.
				 */
            Block a = itr.next();
            PDGNode pdgNodeOfA = null;
            if (!this.m_obj2pdgNode.containsKey(a)) {
                pdgNodeOfA = new PDGNode(a, PDGNode.Type.CFGNODE);
                this.addNode(pdgNodeOfA);
                this.m_obj2pdgNode.put(a, pdgNodeOfA);
            } else
                pdgNodeOfA = this.m_obj2pdgNode.get(a);
            this.addEdge(pdgnode, pdgNodeOfA, "dependency");
            pdgnode.addDependent(pdgNodeOfA);
            // 
            curNodeInRegion = pdgNodeOfA;
            /*
				 * For each successor B of A, if B does not post-dominate A, add all the
				 * nodes on the path from B to the L in the post-dominator tree, where L is the least
				 * common ancestor of A and B in the post-dominator tree (L will be either A itself or 
				 * the parent of A.).
				 */
            List<Block> bs = this.m_blockCFG.getSuccsOf(a);
            for (Iterator<Block> bItr = bs.iterator(); bItr.hasNext(); ) {
                List<Block> dependents = new ArrayList<Block>();
                Block b = bItr.next();
                if (b.equals(a))
                    throw new RuntimeException("PDG construction: A and B are not supposed to be the same node!");
                DominatorNode<Block> aDode = pdom.getDode(a);
                DominatorNode<Block> bDode = pdom.getDode(b);
                // If B post-dominates A, go to the next successor.
                if (pdom.isDominatorOf(bDode, aDode))
                    continue;
                // FIXME: what if the parent is null?!!
                DominatorNode<Block> aParentDode = aDode.getParent();
                DominatorNode<Block> dode = bDode;
                while (dode != aParentDode) {
                    dependents.add((Block) dode.getGode());
                    // This occurs if the CFG is multi-tailed and therefore the pdom is a forest.
                    if (dode.getParent() == null)
                        // throw new RuntimeException("parent dode in pdom is null: dode is " + aDode);
                        break;
                    dode = dode.getParent();
                }
                // first make A's pdg node be a conditional (predicate) pdgnode, if it's not already.
                if (pdgNodeOfA.getAttrib() != PDGNode.Attribute.CONDHEADER) {
                    PDGNode oldA = pdgNodeOfA;
                    pdgNodeOfA = new ConditionalPDGNode(pdgNodeOfA);
                    this.replaceInGraph(pdgNodeOfA, oldA);
                    pdgnode.removeDependent(oldA);
                    this.m_obj2pdgNode.put(a, pdgNodeOfA);
                    pdgnode.addDependent(pdgNodeOfA);
                    pdgNodeOfA.setAttrib(PDGNode.Attribute.CONDHEADER);
                    curNodeInRegion = pdgNodeOfA;
                }
                List<Block> copyOfDependents = new ArrayList<Block>();
                copyOfDependents.addAll(dependents);
                // First, add the dependency for B and its corresponding region.
                Region regionOfB = block2region.get(b);
                PDGNode pdgnodeOfBRegion = null;
                if (!this.m_obj2pdgNode.containsKey(regionOfB)) {
                    pdgnodeOfBRegion = new PDGNode(regionOfB, PDGNode.Type.REGION);
                    this.addNode(pdgnodeOfBRegion);
                    this.m_obj2pdgNode.put(regionOfB, pdgnodeOfBRegion);
                } else
                    pdgnodeOfBRegion = this.m_obj2pdgNode.get(regionOfB);
                // set the region hierarchy
                regionOfB.setParent(r);
                r.addChildRegion(regionOfB);
                // add the dependency edges
                this.addEdge(pdgNodeOfA, pdgnodeOfBRegion, "dependency");
                pdgNodeOfA.addDependent(pdgnodeOfBRegion);
                if (!processedRegions.contains(regionOfB)) {
                    regions2process.add(regionOfB);
                }
                // now remove b and all the nodes in the same weak region from the list of dependents
                copyOfDependents.remove(b);
                copyOfDependents.removeAll(regionOfB.getBlocks());
                while (!copyOfDependents.isEmpty()) {
                    Block depB = copyOfDependents.remove(0);
                    Region rdepB = block2region.get(depB);
                    /* 
						 * Actually, there are cases when depB is not the header of a loop and therefore would not dominate the current node
						 * (A) and therefore might not have been created yet. This has happened when an inner loop breaks out of the outer 
						 * loop but could have other cases too.
						 */
                    PDGNode depBPDGNode = this.m_obj2pdgNode.get(depB);
                    if (depBPDGNode == null) {
                        // First, add the dependency for depB and its corresponding region.
                        PDGNode pdgnodeOfdepBRegion = null;
                        if (!this.m_obj2pdgNode.containsKey(rdepB)) {
                            pdgnodeOfdepBRegion = new PDGNode(rdepB, PDGNode.Type.REGION);
                            this.addNode(pdgnodeOfdepBRegion);
                            this.m_obj2pdgNode.put(rdepB, pdgnodeOfdepBRegion);
                        } else
                            pdgnodeOfdepBRegion = this.m_obj2pdgNode.get(rdepB);
                        // set the region hierarchy
                        rdepB.setParent(regionOfB);
                        regionOfB.addChildRegion(rdepB);
                        // add the dependency edges
                        this.addEdge(pdgnodeOfBRegion, pdgnodeOfdepBRegion, "dependency");
                        pdgnodeOfBRegion.addDependent(pdgnodeOfdepBRegion);
                        if (!processedRegions.contains(rdepB)) {
                            regions2process.add(rdepB);
                        }
                        // now remove all the nodes in the same weak region from the list of dependents
                        copyOfDependents.removeAll(rdepB.getBlocks());
                        continue;
                    }
                    /**
                     * If all the nodes in the weak region of depB are dependent on A, then add
                     * an edge from the region of B to the region of depB.
                     *
                     * else, a new region has to be created to contain the dependences of depB, if
                     * not already created.
                     */
                    if (dependents.containsAll(rdepB.getBlocks())) {
                        /*
							 * Just add an edge to the pdg node of the existing depB region.
							 * 
							 */
                        // add the dependency edges
                        // First, add the dependency for depB and its corresponding region.
                        PDGNode pdgnodeOfdepBRegion = null;
                        if (!this.m_obj2pdgNode.containsKey(rdepB)) {
                            pdgnodeOfdepBRegion = new PDGNode(rdepB, PDGNode.Type.REGION);
                            this.addNode(pdgnodeOfdepBRegion);
                            this.m_obj2pdgNode.put(rdepB, pdgnodeOfdepBRegion);
                        } else
                            pdgnodeOfdepBRegion = this.m_obj2pdgNode.get(rdepB);
                        // set the region hierarchy
                        // Do not set this because the region was created before so must have the
                        // proper parent already.
                        // rdepB.setParent(regionOfB);
                        // regionOfB.addChildRegion(rdepB);
                        this.addEdge(pdgnodeOfBRegion, pdgnodeOfdepBRegion, "dependency");
                        pdgnodeOfBRegion.addDependent(pdgnodeOfdepBRegion);
                        if (!processedRegions.contains(rdepB)) {
                            regions2process.add(rdepB);
                        }
                        // now remove all the nodes in the same weak region from the list of dependents
                        copyOfDependents.removeAll(rdepB.getBlocks());
                        continue;
                    } else {
                        PDGNode predPDGofdepB = (PDGNode) this.getPredsOf(depBPDGNode).get(0);
                        assert (this.m_obj2pdgNode.containsKey(rdepB));
                        PDGNode pdgnodeOfdepBRegion = this.m_obj2pdgNode.get(rdepB);
                        // If the loop header has not been separated from its weak region yet
                        if (predPDGofdepB == pdgnodeOfdepBRegion) {
                            /*
								 * Create a new region to represent the whole loop. In fact, this is a strong
								 * region as opposed to the weak regions that were created in the RegionAnalysis.
								 * This strong region only contains the header of the loop, A, and is dependent 
								 * on it. Also, A is dependent on this strong region as well.
								 */
                            Region newRegion = new Region(this.m_strongRegionStartID++, topLevelRegion.getSootMethod(), topLevelRegion.getSootClass(), this.m_cfg);
                            newRegion.add(depB);
                            this.m_strongRegions.add(newRegion);
                            // toBeRemoved.add(depB);
                            List<Block> blocks2BRemoved;
                            if (toBeRemoved.contains(predPDGofdepB))
                                blocks2BRemoved = toBeRemoved.get(predPDGofdepB);
                            else {
                                blocks2BRemoved = new ArrayList<Block>();
                                toBeRemoved.put(rdepB, blocks2BRemoved);
                            }
                            blocks2BRemoved.add(depB);
                            PDGNode newpdgnode = new LoopedPDGNode(newRegion, PDGNode.Type.REGION, depBPDGNode);
                            this.addNode(newpdgnode);
                            this.m_obj2pdgNode.put(newRegion, newpdgnode);
                            newpdgnode.setAttrib(PDGNode.Attribute.LOOPHEADER);
                            depBPDGNode.setAttrib(PDGNode.Attribute.LOOPHEADER);
                            this.removeEdge(pdgnodeOfdepBRegion, depBPDGNode, "dependency");
                            pdgnodeOfdepBRegion.removeDependent(depBPDGNode);
                            this.addEdge(pdgnodeOfdepBRegion, newpdgnode, "dependency");
                            this.addEdge(newpdgnode, depBPDGNode, "dependency");
                            pdgnodeOfdepBRegion.addDependent(newpdgnode);
                            newpdgnode.addDependent(depBPDGNode);
                            // If a is dependent on itself (simple loop)
                            if (depB == a) {
                                PDGNode loopBodyPDGNode = (PDGNode) this.getSuccsOf(depBPDGNode).get(0);
                                this.addEdge(depBPDGNode, newpdgnode, "dependency-back");
                                ((LoopedPDGNode) newpdgnode).setBody(loopBodyPDGNode);
                                depBPDGNode.addBackDependent(newpdgnode);
                                // This is needed to correctly adjust the prev/next pointers for the new loop node. We should not need
                                // to adjust the old loop header node because the prev/next should not have been set previously for it.
                                curNodeInRegion = newpdgnode;
                            } else {
                                // this is a back-dependency
                                pdgnodeOfBRegion.addBackDependent(newpdgnode);
                                this.addEdge(pdgnodeOfBRegion, newpdgnode, "dependency-back");
                                // DEtermine which dependent of the loop header is actually the loop body region
                                PDGNode loopBodyPDGNode = null;
                                List<PDGNode> successors = this.getSuccsOf(depBPDGNode);
                                Iterator<PDGNode> succItr = successors.iterator();
                                while (succItr.hasNext()) {
                                    PDGNode succRPDGNode = succItr.next();
                                    assert (succRPDGNode.getType() == PDGNode.Type.REGION);
                                    Region succR = (Region) succRPDGNode.getNode();
                                    Block h = succR.getBlocks().get(0);
                                    DominatorNode<Block> hdode = dom.getDode(h);
                                    DominatorNode<Block> adode = dom.getDode(a);
                                    if (dom.isDominatorOf(hdode, adode)) {
                                        loopBodyPDGNode = succRPDGNode;
                                        break;
                                    }
                                }
                                assert (loopBodyPDGNode != null);
                                ((LoopedPDGNode) newpdgnode).setBody(loopBodyPDGNode);
                                PDGNode prev = depBPDGNode.getPrev();
                                if (prev != null) {
                                    this.removeEdge(prev, depBPDGNode, "controlflow");
                                    this.addEdge(prev, newpdgnode, "controlflow");
                                    prev.setNext(newpdgnode);
                                    newpdgnode.setPrev(prev);
                                    depBPDGNode.setPrev(null);
                                }
                                PDGNode next = depBPDGNode.getNext();
                                if (next != null) {
                                    this.removeEdge(depBPDGNode, next, "controlflow");
                                    this.addEdge(newpdgnode, next, "controlflow");
                                    newpdgnode.setNext(next);
                                    next.setPrev(newpdgnode);
                                    depBPDGNode.setNext(null);
                                }
                            }
                        } else {
                            /*
								 * The strong region for the header has already been created and its 
								 * corresponding PDGNode exist. Just add the dependency edge.
								 */
                            this.addEdge(pdgnodeOfBRegion, predPDGofdepB, "dependency-back");
                            // this is a back-dependency
                            pdgnodeOfBRegion.addBackDependent(predPDGofdepB);
                        }
                    }
                }
            }
            /* If there is a previous node in this region, add a control flow edge to indicate the
				 * the correct direction of control flow in the region.
				 */
            if (prevPDGNodeInRegion != null) {
                this.addEdge(prevPDGNodeInRegion, curNodeInRegion, "controlflow");
                prevPDGNodeInRegion.setNext(curNodeInRegion);
                curNodeInRegion.setPrev(prevPDGNodeInRegion);
            }
            prevPDGNodeInRegion = curNodeInRegion;
        }
        // remove all the blocks marked to be removed from the region (to change a weak region
        // to a strong region.)
        Enumeration<Region> itr1 = toBeRemoved.keys();
        while (itr1.hasMoreElements()) {
            Region region = itr1.nextElement();
            Iterator<Block> blockItr = toBeRemoved.get(region).iterator();
            while (blockItr.hasNext()) region.remove(blockItr.next());
        }
    }
}
Also used : Hashtable(java.util.Hashtable) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Block(soot.toolkits.graph.Block) IRegion(soot.toolkits.graph.pdg.IRegion) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet)

Example 5 with Block

use of soot.toolkits.graph.Block in project soot by Sable.

the class PDGRegion method getUnits.

public List<Unit> getUnits() {
    if (this.m_units == null) {
        this.m_units = new LinkedList<Unit>();
        this.m_unit2pdgnode = new LinkedHashMap<Unit, PDGNode>();
        for (Iterator<PDGNode> itr = this.iterator(); itr.hasNext(); ) {
            PDGNode node = itr.next();
            if (node.getType() == PDGNode.Type.REGION) {
                // if(node.getAttrib() == PDGNode.Attribute.LOOPHEADER)
                if (node instanceof LoopedPDGNode) {
                    LoopedPDGNode n = (LoopedPDGNode) node;
                    PDGNode header = n.getHeader();
                    Block headerBlock = (Block) header.getNode();
                    for (Iterator<Unit> itr1 = headerBlock.iterator(); itr1.hasNext(); ) {
                        Unit u = itr1.next();
                        ((LinkedList<Unit>) this.m_units).addLast(u);
                        this.m_unit2pdgnode.put(u, header);
                    }
                }
            } else if (node.getType() == PDGNode.Type.CFGNODE) {
                Block b = (Block) node.getNode();
                for (Iterator<Unit> itr1 = b.iterator(); itr1.hasNext(); ) {
                    Unit u = itr1.next();
                    ((LinkedList<Unit>) this.m_units).addLast(u);
                    this.m_unit2pdgnode.put(u, node);
                }
            } else
                throw new RuntimeException("Exception in PDGRegion.getUnits: PDGNode's type is undefined!");
        }
    }
    return this.m_units;
}
Also used : Iterator(java.util.Iterator) Block(soot.toolkits.graph.Block) Unit(soot.Unit) LinkedList(java.util.LinkedList)

Aggregations

Block (soot.toolkits.graph.Block)11 Unit (soot.Unit)5 LinkedList (java.util.LinkedList)3 DominatorNode (soot.toolkits.graph.DominatorNode)3 HashSet (java.util.HashSet)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Hashtable (java.util.Hashtable)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Set (java.util.Set)1 Body (soot.Body)1 Local (soot.Local)1 Trap (soot.Trap)1 UnitBox (soot.UnitBox)1 JasminAttribute (soot.tagkit.JasminAttribute)1 LineNumberTag (soot.tagkit.LineNumberTag)1 Tag (soot.tagkit.Tag)1 BlockGraph (soot.toolkits.graph.BlockGraph)1 BriefBlockGraph (soot.toolkits.graph.BriefBlockGraph)1