package jqian.sootex.ptsto;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import soot.PointsToSet;
import soot.jimple.AnyNewExpr;
import soot.jimple.spark.pag.AllocDotField;
import soot.jimple.spark.pag.AllocNode;
import soot.jimple.spark.pag.Node;
import soot.jimple.spark.pag.PAG;
import soot.jimple.spark.pag.SparkField;
import soot.jimple.spark.sets.P2SetVisitor;
import soot.jimple.spark.sets.PointsToSetInternal;
import soot.jimple.toolkits.pointer.Union;
import soot.util.ArrayNumberer;
/**
* Helper class for PAG (Spark) points-to analysis
*/
public class PAGHelper {
private static class MyVisitor extends P2SetVisitor {
private final Set<AllocNode> _objs;
public MyVisitor(Set<AllocNode> objects){
this._objs = objects;
}
public void visit(Node n) {
if (n instanceof AllocNode) {
AllocNode aNode = (AllocNode)n;
_objs.add(aNode);
}
}
public boolean getReturnValue() {
return true;
}
}
public static void toAllocNodeSet(PointsToSet ptSt, Set<AllocNode> result) {
if (ptSt instanceof PointsToSetInternal) {
PointsToSetInternal ptStInternal = (PointsToSetInternal) ptSt;
MyVisitor visitor = new MyVisitor((Set<AllocNode>)result);
ptStInternal.forall(visitor);
}
else if (ptSt instanceof Union) {
}
}
public static AnyNewExpr allocNodeToNewExpr(AllocNode node){
Object expr = node.getNewExpr();
//out.println(expr.getClass());
if(expr instanceof AnyNewExpr){
return (AnyNewExpr)expr;
}
else{// if (expr instanceof Value || expr instanceof String) {
return null;
}
//else {throw new RuntimeException("Unacceptable node type: "+node);}
}
public static Set<AnyNewExpr> pointsToSetToNewExprs(PointsToSet ptSt){
Set<AllocNode> nodes = new HashSet<AllocNode>();
Set<AnyNewExpr> objects = new HashSet<AnyNewExpr>();
toAllocNodeSet(ptSt, nodes);
for(AllocNode n: nodes){
AnyNewExpr obj = allocNodeToNewExpr(n);
if(obj!=null)
objects.add(obj);
}
return objects;
}
static Map<Object,AllocNode> buildNewExprToAllocNodeMap(PAG pag){
ArrayNumberer numberer = pag.getAllocNodeNumberer();
int allocNum = pag.getNumAllocNodes();
Map<Object,AllocNode> newExpr2allocNode = new HashMap<Object, AllocNode>(allocNum * 2);
for (int i = 1; i <= allocNum; i++) {// 0 - null pointer
AllocNode node = (AllocNode) numberer.get(i);
Object expr = node.getNewExpr();
newExpr2allocNode.put(expr, node);
}
return newExpr2allocNode;
}
public static PointsToSet getFieldPointsTo(AllocNode node, SparkField f){
try {
AllocDotField field = node.dot(f);
return field.getP2Set();
}
catch (NullPointerException e) {
return null;
}
}
public static Set<AllocNode> reachingObjectsOfAllFields(AllocNode n){
Set<AllocNode> result = new HashSet<AllocNode>();
Collection<?> fieldRefs = n.getAllFieldRefs();
for (Iterator<?> it = fieldRefs.iterator(); it.hasNext();) {
AllocDotField field = (AllocDotField) it.next();
try {
PointsToSet p2St = field.getP2Set();
toAllocNodeSet(p2St, result);
} catch (NullPointerException e) {
}
}
return result;
}
}