package jqian.sootex.ptsto; import java.util.*; import soot.*; import soot.jimple.spark.pag.*; import soot.jimple.spark.sets.*; import soot.jimple.toolkits.pointer.Union; import soot.jimple.*; import soot.util.ArrayNumberer; import soot.util.Numberable; import soot.util.Numberer; /** * @author bruteforce * */ public class PtsToAdapter { private final PointsToAnalysis _pta; private Map<Object,AllocNode> _obj2node; public PtsToAdapter(PointsToAnalysis pa){ _pta = pa; } public PointsToAnalysis getPointsToAnalysis(){ return _pta; } private PointsToSet pagReachingObject(AnyNewExpr obj,SparkField f){ if (_obj2node == null) { _obj2node = PAGHelper.buildNewExprToAllocNodeMap((PAG)_pta); } AllocNode node = _obj2node.get(obj); return PAGHelper.getFieldPointsTo(node, f); } public PointsToSet reachingObjects(AnyNewExpr obj,SootField f){ if(!(f.getType() instanceof RefLikeType)){ return null; } if(f.isStatic()){ return _pta.reachingObjects(f); } if(_pta instanceof PAG){ return pagReachingObject(obj, f); } else if(_pta instanceof TypeBasedPointsToAnalysis){ TypeBasedPointsToAnalysis tpta = (TypeBasedPointsToAnalysis)_pta; return tpta.reachingObjects(f); } return null; } public PointsToSet reachingObjectsOfArrayElement(AnyNewExpr arrayObject){ if(_pta instanceof PAG){ return pagReachingObject(arrayObject, ArrayElement.v()); } else if(_pta instanceof TypeBasedPointsToAnalysis){ ArrayType type = (ArrayType)arrayObject.getType(); Type elementType = type.getArrayElementType(); TypeBasedPointsToAnalysis tpta = (TypeBasedPointsToAnalysis)_pta; return tpta.reachingObjects(elementType); } return null; } @SuppressWarnings({ "rawtypes", "unchecked" }) public static Set<Numberable> toHeapNodeSet(PointsToSet ptSt) { Set result = null; if (ptSt instanceof PointsToSetInternal || ptSt instanceof Union) { result = new HashSet(); toHeapNodeSet(ptSt, result); } else if(ptSt instanceof TypeBasedPointsToSet){ result = (TypeBasedPointsToSet)ptSt; } return result; } @SuppressWarnings({ "rawtypes", "unchecked" }) public static void toHeapNodeSet(PointsToSet ptSt, Set<Numberable> result) { if (ptSt instanceof PointsToSetInternal || ptSt instanceof Union) { Set out = result; PAGHelper.toAllocNodeSet(ptSt, out); } else if(ptSt instanceof TypeBasedPointsToSet){ TypeBasedPointsToSet set = (TypeBasedPointsToSet)ptSt; result.addAll(set); } } public Set<Numberable> reachingObjects(Local local){ PointsToSet pset = _pta.reachingObjects(local); return toHeapNodeSet(pset); } public void reachingObjects(Local local, Set<Numberable> result){ PointsToSet pset = _pta.reachingObjects(local); toHeapNodeSet(pset, result); } public Set<Numberable> reachingObjects(Local v, SootField f){ PointsToSet pset = _pta.reachingObjects(v,f); return toHeapNodeSet(pset); } /** Override this method to define your own collection. */ public static class AtomicFilter{ public boolean isAtomic(Type type){ return false; } } public void reachingClosure(Local local,Set<Numberable> out){ Set<Numberable> starts = reachingObjects(local); reachingClosure(starts,out, null); } public Type getAbstractObjectType(Numberable object){ if(object instanceof Type){ return (Type)object; } else if(object instanceof AllocNode){ return ((AllocNode)object).getType(); } return null; } public Numberer getObjectNumberable(){ ArrayNumberer numberer = null; if(_pta instanceof PAG){ PAG pag = (PAG)_pta; numberer = pag.getAllocNodeNumberer(); } else if(_pta instanceof TypeBasedPointsToAnalysis){ numberer = Scene.v().getTypeNumberer(); } else{ } return numberer; } /** * @param object assuming the passed in parameter is an abstract object */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Set<Numberable> reachingObjectOfAllFields(Numberable object){ Set result = null; if(_pta instanceof PAG){ result = PAGHelper.reachingObjectsOfAllFields((AllocNode)object); } else if(_pta instanceof TypeBasedPointsToAnalysis){ TypeBasedPointsToAnalysis tpta = (TypeBasedPointsToAnalysis)_pta; result = tpta.reachingObjectsOfAllFields((Type)object); } return result; } private void reachingClosure(Set<Numberable> starts,Set<Numberable> out, AtomicFilter filter){ Stack<Numberable> stack = new Stack<Numberable>(); stack.addAll(starts); while(!stack.isEmpty()){ Numberable n = stack.pop(); out.add(n); //if is atomic type which can not be expanded if(filter!=null && filter.isAtomic(getAbstractObjectType(n))){ continue; } Set<Numberable> reach = reachingObjectOfAllFields(n); for(Numberable tgt: reach){ if(!out.contains(tgt)){ stack.push(tgt); } } } } }