package jqian.sootex.location; import jqian.sootex.util.*; import jqian.util.CollectionUtils; import jqian.*; import java.util.*; import soot.*; import soot.jimple.*; import soot.util.*; /** * <immutable> * Represent abstract locations. An unified interface for Locals, SootFields, and etc, * used for the sake of clearness and easy type checking. */ public abstract class Location implements Numberable{ private static int COUNT; private static Location[] _FIELD2LOC; private static MethodRet[] _METHOD2RET; private static Map<Value,Location> _VALUE2LOC; private static HeapLocation[] _TYPE2LOC; //-------------------- Static Methods -----------------------// protected static void reset(){ COUNT = 0; Scene scene = Scene.v(); _METHOD2RET = new MethodRet[SootUtils.getMethodCount()]; _FIELD2LOC = new Location[scene.getFieldNumberer().size() + 1]; _TYPE2LOC = new HeapLocation[scene.getTypeNumberer().size() + 1]; _VALUE2LOC = new WeakHashMap<Value,Location>(CollectionUtils.getHashSetInitCapacity(scene.getLocalNumberer().size())); } static{ reset(); Global.v().regesiterResetableGlobals(Location.class); } /** Force releasing locations relevant to a given method. */ public static void release(SootMethod m){ if(!m.hasActiveBody()) return; Body body = m.getActiveBody(); Set<Local> interfaceLocals = new HashSet<Local>(); int count = m.getParameterCount(); for(int i=0; i<count;i++){ interfaceLocals.add(body.getParameterLocal(i)); } if(!m.isStatic()){ interfaceLocals.add(body.getThisLocal()); } for(Local local: body.getLocals()){ if(!interfaceLocals.contains(local)){ _VALUE2LOC.remove(local); } } } /** * Construct the Location from an immediate: constant or local. * @param value Should be of the type Constant or Local */ public static Location valueToLocation(Value value){ Location loc = _VALUE2LOC.get(value); if (loc == null) { if(value instanceof Local){ loc = new StackLocation(value); } else if(value instanceof NullConstant){ //loc = null; loc = NullConstLocation.v(); } else if(value instanceof ClassConstant){ //loc = null; loc = new ConstLocation(value); } else if(value instanceof StringConstant){ loc = new ConstLocation(value); } else if(value instanceof NumericConstant){ loc = new ConstLocation(value); } else{ throw new RuntimeException("Bad usage: input "+value.getClass()); } _VALUE2LOC.put(value, loc); } return loc; } /** Get the unique return location of a method. */ public static Location methodToRet(SootMethod m){ int mId = m.getNumber(); MethodRet loc = _METHOD2RET[mId]; if (loc == null) { loc = new MethodRet(m); _METHOD2RET[mId] = loc; } return loc; } public static Location getThisPointer(SootMethod method){ return valueToLocation(method.getActiveBody().getThisLocal()); } public static GlobalLocation getGlobalLocation(SootField field) { int fId = field.getNumber(); GlobalLocation p = (GlobalLocation)_FIELD2LOC[fId]; if (null == p) { p = new GlobalLocation(field); _FIELD2LOC[fId] = p; } return p; } /** Used for field-based analysis. Do not distinguish instance objects. */ public static HeapField getHeapFieldLocation(SootField field) { int fId = field.getNumber(); HeapField p = (HeapField)_FIELD2LOC[fId]; if (null == p) { p = new HeapField(null, field); _FIELD2LOC[fId] = p; } return p; } /** A single heap field to model all instance fields. */ public static HeapField getUnknownHeapField(){ return UnknownInstObject.v().getField(); } /** A single array element to model all runtime array elements*/ public static ArrayElmt getUnknownArrayElmt(){ return UnknownArraySpace.v().getElement(); } public static class TypeLocation extends HeapLocation{ Type _type; public TypeLocation(Type t){ this._type = t; } public InstanceObject getWrapperObject(){ return null; } public Type getObjectType(){ return _type; } @Override public Type getType() { return Scene.v().getObjectType(); } public String toString(){ return _type.toString() + ".*"; } } /** A single abstract location to model all heap memory of a given type. */ public static HeapLocation getLocationForType(Type t){ int tId = t.getNumber(); HeapLocation p = _TYPE2LOC[tId]; if (null == p) { p = new TypeLocation(t); _TYPE2LOC[tId] = p; } return p; } //------------------ Instance Methods ------------------------// private int _id; protected Location(){ this._id = COUNT; COUNT++; } public boolean isPointer(){ return getType() instanceof RefLikeType; } public int getNumber(){ return _id; } public void setNumber(int id){ } public int hashCode(){ return _id; } public abstract Type getType(); }