Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* Soot - a J*va Optimization Framework
* Copyright (C) 1999-2010 Hossein Sadat-Mohtasham
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package soot.toolkits.graph.pdg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import soot.Body;
import soot.G;
import soot.SootClass;
import soot.SootMethod;
import soot.Unit;
import soot.options.Options;
import soot.toolkits.graph.Block;
import soot.toolkits.graph.BlockGraph;
import soot.toolkits.graph.BriefBlockGraph;
import soot.toolkits.graph.BriefUnitGraph;
import soot.toolkits.graph.DirectedGraph;
import soot.toolkits.graph.DominatorNode;
import soot.toolkits.graph.DominatorTree;
import soot.toolkits.graph.ExceptionalBlockGraph;
import soot.toolkits.graph.ExceptionalUnitGraph;
import soot.toolkits.graph.MHGDominatorsFinder;
import soot.toolkits.graph.MHGPostDominatorsFinder;
import soot.toolkits.graph.UnitGraph;
/**
* This class computes the set of weak regions for a given method. It is based on the
* algorithm given in the following paper:
*
* Ball, T. 1993. What's in a region?: or computing control dependence regions in near-linear
* time for reducible control flow. ACM Lett. Program. Lang. Syst. 2, 1-4 (Mar. 1993),
* 1-16. DOI= http://doi.acm.org/10.1145/176454.176456
*
* @author Hossein Sadat-Mohtasham
* Jan 2009
*/
@SuppressWarnings("unchecked")
public class RegionAnalysis{
protected SootClass m_class = null;
protected SootMethod m_method = null;
protected Body m_methodBody;
protected UnitGraph m_cfg;
protected UnitGraph m_reverseCFG;
protected BlockGraph m_blockCFG;
protected BlockGraph m_reverseBlockCFG;
protected Hashtable m_regions = new Hashtable();
protected List m_regionsList = null;
private int m_regCount = 0;
private MHGDominatorTree m_dom;
//this would actually be the postdominator tree in the original CFG
private MHGDominatorTree m_pdom;
protected Region m_topLevelRegion = null;
protected Hashtable m_block2region = null;
public RegionAnalysis(UnitGraph cfg, SootMethod m, SootClass c)
{
this.m_methodBody = cfg.getBody();
this.m_cfg = cfg;
this.m_method = m;
this.m_class = c;
if(Options.v().verbose())
G.v().out.println("[RegionAnalysis]~~~~~~~~~~~~~~~ Begin Region Analsis for method: " + m.getName() +" ~~~~~~~~~~~~~~~~~~~~");
this.findWeakRegions();
if(Options.v().verbose())
G.v().out.println("[RegionAnalysis]~~~~~~~~~~~~~~~ End:" + m.getName() +" ~~~~~~~~~~~~~~~~~~~~");
}
private void findWeakRegions()
{
/*
* Check to see what kind of CFG has been passed in and create
* the appropriate block CFG. Note that almost all of the processing
* is done on the block CFG.
*/
if(this.m_cfg instanceof ExceptionalUnitGraph)
this.m_blockCFG = new ExceptionalBlockGraph((ExceptionalUnitGraph)this.m_cfg);
else if(this.m_cfg instanceof EnhancedUnitGraph)
this.m_blockCFG = new EnhancedBlockGraph((EnhancedUnitGraph)this.m_cfg);
else if(this.m_cfg instanceof BriefUnitGraph)
this.m_blockCFG = new BriefBlockGraph((BriefUnitGraph)this.m_cfg);
else
throw new RuntimeException("Unsupported CFG passed into the RegionAnalyis constructor!");
this.m_dom = new MHGDominatorTree(new MHGDominatorsFinder(this.m_blockCFG));
String s = dominatorTreeToString(this.m_dom, this.m_dom.getHead());
if(Options.v().verbose())
G.v().out.println("[RegionAnalysis] Dominator tree: " + s);
try{
this.m_pdom = new MHGDominatorTree(new MHGPostDominatorsFinder(m_blockCFG));
if(Options.v().verbose())
G.v().out.println("[RegionAnalysis] PostDominator tree: ");
List heads = this.m_pdom.getHeads();
for(Iterator headItr = heads.iterator(); headItr.hasNext(); )
{
s = dominatorTreeToString(this.m_pdom, (DominatorNode) headItr.next());
if(Options.v().verbose())
G.v().out.println(s);
}
this.m_regCount = -1;
/*
* If a Brief graph or Exceptional graph is used, the CFG might be multi-headed and/or
* multi-tailed, which in turn, could result in a post-dominator forest instead of tree.
* If the post-dominator tree has multiple heads, the weakRegionDFS does not work correctly
* because it is designed based on the assumption that there is an auxiliary STOP node in the
* CFG that post-dominates all other nodes. In fact, most of the CFG algorithms augment
* the control flow graph with two nodes: ENTRY and EXIT (or START and STOP) nodes. We have
* not added these nodes since the CFG here is created from the Jimple code and to be
* consistent we'd have to transform the code to reflect these nodes. Instead, we implemted
* the EnhancedUnitGraph (EnhancedBlockGraph) which is guaranteed to be single-headed single-tailed.
* But note that EnhancedUnitGraph represents exceptional flow differently.
*
*
*/
if(this.m_blockCFG.getHeads().size() == 1)
{
this.m_regCount++;
this.m_regions.put(new Integer(this.m_regCount), this.createRegion(this.m_regCount));
this.weakRegionDFS2((Block)this.m_blockCFG.getHeads().get(0), this.m_regCount);
}
else if(this.m_blockCFG.getTails().size() == 1)
{
this.m_regCount++;
this.m_regions.put(new Integer(this.m_regCount), this.createRegion(this.m_regCount));
this.weakRegionDFS((Block)this.m_blockCFG.getTails().get(0), this.m_regCount);
}
else
{
if(Options.v().verbose())
G.v().out.println("WARNING: RegionAnalysis: the CFG is multi-headed and tailed, so, the results of this analysis might not be reliable!");
for(int i = 0; i < this.m_blockCFG.getTails().size(); i++)
{
this.m_regCount++;
this.m_regions.put(new Integer(this.m_regCount), this.createRegion(this.m_regCount));
this.weakRegionDFS((Block)this.m_blockCFG.getTails().get(i), this.m_regCount);
}
//throw new RuntimeException("RegionAnalysis: cannot properly deal with multi-headed and tailed CFG!");
}
}
catch(RuntimeException e)
{
G.v().out.println("[RegionAnalysis] Exception in findWeakRegions: " + e);
}
}
/**
* This algorithms assumes that the first time it's called with a tail of the CFG. Then for each
* child node w of v in the post-dominator tree, it compares the parent of v in the dominator tree
* with w and if they are the same, that means w belongs to the same region as v, so weakRegionDFS
* is recursively called with w and the same region id as v.
* If the comparison fails, then a new region is created and weakRegionDFS is called recursively with
* w but this time with the newly created region id.
*
* @param v
* @param r
*/
private void weakRegionDFS(Block v, int r)
{
try{
//System.out.println("##entered weakRegionDFS for region " + r);
this.m_regions.get(new Integer(r)).add(v);
DominatorNode parentOfV = this.m_dom.getParentOf(this.m_dom.getDode(v));
Block u2 = (parentOfV == null) ? null : (Block)parentOfV.getGode();
List children = this.m_pdom.getChildrenOf(this.m_pdom.getDode(v));
for(int i = 0; i < children.size(); i++)
{
DominatorNode w = (DominatorNode)children.get(i);
Block u1 = (Block)w.getGode();
if(u2 != null && u1.equals(u2))
{
this.weakRegionDFS((Block)w.getGode(), r);
}
else
{
this.m_regCount++;
this.m_regions.put(new Integer(this.m_regCount), this.createRegion(this.m_regCount));
this.weakRegionDFS((Block)w.getGode(), this.m_regCount);
}
}
}
catch(RuntimeException e)
{
G.v().out.println("[RegionAnalysis] Exception in weakRegionDFS: " + e);
G.v().out.println("v is " + v.toShortString() + " in region " + r);
G.v().out.flush();
}
}
/**
* This algorithm starts from a head node in the CFG and is exactly the same as the above
* with the difference that post dominator and dominator trees switch positions.
* @param v
* @param r
*/
private void weakRegionDFS2(Block v, int r)
{
//regions keep an implicit order of the contained blocks so it matters where blocks are added
//below.
this.m_regions.get(new Integer(r)).add2Back(v);
DominatorNode parentOfV = this.m_pdom.getParentOf(this.m_pdom.getDode(v));
Block u2 = (parentOfV == null) ? null : (Block)parentOfV.getGode();
List children = this.m_dom.getChildrenOf(this.m_dom.getDode(v));
for(int i = 0; i < children.size(); i++)
{
DominatorNode w = (DominatorNode)children.get(i);
Block u1 = (Block)w.getGode();
if(u2 != null && u1.equals(u2))
{
this.weakRegionDFS2((Block)w.getGode(), r);
}
else
{
this.m_regCount++;
this.m_regions.put(new Integer(this.m_regCount), this.createRegion(this.m_regCount));
this.weakRegionDFS2((Block)w.getGode(), this.m_regCount);
}
}
}
public List getRegions()
{
if(this.m_regionsList == null)
{
this.m_regionsList = new ArrayList();
Collection values = this.m_regions.values();
for(Iterator itr = values.iterator(); itr.hasNext();)
{
Region region = (Region) itr.next();
this.m_regionsList.add(region);
}
}
return this.m_regionsList;
}
public Hashtable getUnit2RegionMap()
{
Hashtable unit2region = new Hashtable();
List regions = this.getRegions();
for(Iterator itr = regions.iterator(); itr.hasNext();)
{
Region r = itr.next();
List units = r.getUnits();
for (Iterator itr1 = units.iterator(); itr1.hasNext();)
{
Unit u = itr1.next();
unit2region.put(u, r);
}
}
return unit2region;
}
public Hashtable getBlock2RegionMap()
{
if(this.m_block2region == null)
{
this.m_block2region = new Hashtable();
List regions = this.getRegions();
for(Iterator itr = regions.iterator(); itr.hasNext();)
{
Region r = itr.next();
List blocks = r.getBlocks();
for (Iterator itr1 = blocks.iterator(); itr1.hasNext();)
{
Block u = itr1.next();
m_block2region.put(u, r);
}
}
}
return this.m_block2region;
}
public BlockGraph getBlockCFG()
{
return this.m_blockCFG;
}
public DominatorTree getPostDominatorTree()
{
return this.m_pdom;
}
public DominatorTree getDominatorTree()
{
return this.m_dom;
}
public void reset()
{
this.m_regions.clear();
this.m_regionsList.clear();
this.m_regionsList = null;
this.m_block2region.clear();
this.m_block2region = null;
m_regCount = 0;
}
/**
* Create a region
*/
protected Region createRegion(int id)
{
Region region = new Region(id, this.m_method, this.m_class, this.m_cfg);
if(id == 0)
this.m_topLevelRegion = region;
return region;
}
public Region getTopLevelRegion()
{
return this.m_topLevelRegion;
}
public String CFGtoString(DirectedGraph cfg, boolean blockDetail)
{
String s = new String("");
s += "Headers: " + cfg.getHeads().size() + " " + cfg.getHeads();
for (Iterator it = cfg.iterator(); it.hasNext(); )
{
Block node = it.next();
s += "Node = " + node.toShortString() + "\n";
s += "Preds:\n";
for (Iterator predsIt = cfg.getPredsOf(node).iterator(); predsIt.hasNext(); )
{
s += " ";
s += predsIt.next().toShortString() + "\n";
}
s += "Succs:\n";
for (Iterator succsIt = cfg.getSuccsOf(node).iterator(); succsIt.hasNext(); )
{
s += " ";
s += succsIt.next().toShortString() + "\n";
}
}
if(blockDetail)
{
s += "Blocks Detail:";
for (Iterator it = cfg.iterator(); it.hasNext(); )
{
Block node = it.next();
s += node + "\n";
}
}
return s;
}
private String dominatorTreeToString(DominatorTree dom, DominatorNode root)
{
String s = new String();
s += "\n Begin " + ((Block)root.getGode()).toShortString() + " ( ";
List children = dom.getChildrenOf(root);
for(int i = 0; i < children.size(); i++)
{
s += dominatorTreeToString(dom, (DominatorNode) children.get(i));
}
s += " ) end of " + ((Block)root.getGode()).toShortString();
return s;
}
}