package soot.jimple.toolkits.infoflow; import soot.*; import soot.jimple.*; import java.util.*; /** CallLocalityContext written by Richard L. Halpert 2007-03-05 * Acts as a container for the locality information collected about a call site * by one of the Local Objects Analyses. */ public class CallLocalityContext { List<Object> nodes; List<Boolean> isNodeLocal; public CallLocalityContext(List<Object> nodes) { this.nodes = new ArrayList<Object>(); this.nodes.addAll(nodes); isNodeLocal = new ArrayList<Boolean>(nodes.size()); for(int i = 0; i < nodes.size(); i++) { isNodeLocal.add(i, Boolean.FALSE); } } public void setFieldLocal(EquivalentValue fieldRef) { List ret = new ArrayList(); for(int i = 0; i < nodes.size(); i++) { if( fieldRef.equals(nodes.get(i)) ) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.TRUE); return; } } nodes.add(fieldRef); isNodeLocal.add(Boolean.TRUE); // throw new RuntimeException("Field " + fieldRef + " is not present in CallLocalityContext\n" + toString()); // return false; } public void setFieldShared(EquivalentValue fieldRef) { List ret = new ArrayList(); for(int i = 0; i < nodes.size(); i++) { if( fieldRef.equals(nodes.get(i)) ) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.FALSE); return; } } nodes.add(fieldRef); isNodeLocal.add(Boolean.FALSE); // throw new RuntimeException("Field " + fieldRef + " is not present in CallLocalityContext\n" + toString()); // return false; } public void setAllFieldsLocal() { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof InstanceFieldRef) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.TRUE); } } } public void setAllFieldsShared() { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof InstanceFieldRef) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.FALSE); } } } public void setParamLocal(int index) { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof ParameterRef) { ParameterRef pr = (ParameterRef) r; if(pr.getIndex() == index) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.TRUE); } } } } public void setParamShared(int index) { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof ParameterRef) { ParameterRef pr = (ParameterRef) r; if(pr.getIndex() == index) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.FALSE); } } } } public void setAllParamsLocal() { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof ParameterRef) { ParameterRef pr = (ParameterRef) r; if(pr.getIndex() != -1) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.TRUE); } } } } public void setAllParamsShared() { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof ParameterRef) { ParameterRef pr = (ParameterRef) r; if(pr.getIndex() != -1) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.FALSE); } } } } public void setThisLocal() { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof ThisRef) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.TRUE); } } } public void setThisShared() { for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof ThisRef) { isNodeLocal.remove(i); isNodeLocal.add(i, Boolean.FALSE); } } } public void setReturnLocal() { setParamLocal(-1); } public void setReturnShared() { setParamShared(-1); } public List<Object> getLocalRefs() { List<Object> ret = new ArrayList<Object>(); for(int i = 0; i < nodes.size(); i++) { if(isNodeLocal.get(i).booleanValue()) ret.add(nodes.get(i)); } return ret; } public List<Object> getSharedRefs() { List<Object> ret = new ArrayList<Object>(); for(int i = 0; i < nodes.size(); i++) { if(!isNodeLocal.get(i).booleanValue()) ret.add(nodes.get(i)); } return ret; } public boolean isFieldLocal(EquivalentValue fieldRef) { List ret = new ArrayList(); for(int i = 0; i < nodes.size(); i++) { if( fieldRef.equals(nodes.get(i)) ) return isNodeLocal.get(i).booleanValue(); } return false; // catches static fields that were not included in the original context // throw new RuntimeException("Field " + fieldRef + " is not present in CallLocalityContext\n" + toString()); // return false; } public boolean containsField(EquivalentValue fieldRef) { List ret = new ArrayList(); for(int i = 0; i < nodes.size(); i++) { if( fieldRef.equals(nodes.get(i)) ) return true; } return false; } // merges two contexts into one... shared fields in either context are shared in the merged context // return true if merge causes this context to change public boolean merge(CallLocalityContext other) { boolean isChanged = false; if(other.nodes.size() > nodes.size()) { isChanged = true; for(int i = nodes.size(); i < other.nodes.size(); i++) { nodes.add(other.nodes.get(i)); isNodeLocal.add(other.isNodeLocal.get(i)); } } for(int i = 0; i < other.nodes.size(); i++) { Boolean temp = new Boolean(isNodeLocal.get(i).booleanValue() && other.isNodeLocal.get(i).booleanValue()); if( !temp.equals(isNodeLocal.get(i)) ) isChanged = true; isNodeLocal.remove(i); isNodeLocal.add(i, temp); } return isChanged; } public boolean equals(Object o) { if(o instanceof CallLocalityContext) { CallLocalityContext other = (CallLocalityContext) o; return isNodeLocal.equals(other.isNodeLocal);// && nodes.equals(other.nodes); } return false; } public int hashCode() { return isNodeLocal.hashCode(); } public boolean isAllShared(boolean refsOnly) { for(int i = 0; i < nodes.size(); i++) { if( (!refsOnly) && isNodeLocal.get(i).booleanValue() ) { return false; } else if( ((EquivalentValue) nodes.get(i)).getValue().getType() instanceof RefLikeType && isNodeLocal.get(i).booleanValue() ) { return false; } } return true; } public String toString() { String fieldrefs = ""; String staticrefs = ""; String paramrefs = ""; // includes returnref String thisref = ""; if(nodes.size() == 0) return "Call Locality Context: NO NODES\n"; for(int i = 0; i < nodes.size(); i++) { Ref r = (Ref) ((EquivalentValue) nodes.get(i)).getValue(); if(r instanceof InstanceFieldRef) fieldrefs = fieldrefs + r + ": " + (isNodeLocal.get(i).booleanValue() ? "local" : "shared") + "\n"; else if(r instanceof StaticFieldRef) staticrefs = staticrefs + r + ": " + (isNodeLocal.get(i).booleanValue() ? "local" : "shared") + "\n"; else if(r instanceof ParameterRef) paramrefs = paramrefs + r + ": " + (isNodeLocal.get(i).booleanValue() ? "local" : "shared") + "\n"; else if(r instanceof ThisRef) thisref = thisref + r + ": " + (isNodeLocal.get(i).booleanValue() ? "local" : "shared") + "\n"; else return "Call Locality Context: HAS STRANGE NODE " + r + "\n"; } return "Call Locality Context: \n" + fieldrefs + paramrefs + thisref + staticrefs; } public String toShortString() { String ret = "["; for(int i = 0; i < nodes.size(); i++) { ret = ret + (isNodeLocal.get(i).booleanValue() ? "L" : "S"); } return ret + "]"; } }