package jqian.sootex.sideeffect; import java.util.*; import jqian.sootex.AtomicTypes; import jqian.sootex.Cache; import jqian.sootex.location.AccessPath; import jqian.sootex.location.GlobalLocation; import jqian.sootex.location.Location; import jqian.sootex.util.NumberableComparator; import jqian.sootex.util.callgraph.CallGraphEdgeFilter; import jqian.sootex.util.callgraph.CallGraphHelper; import jqian.sootex.util.callgraph.CallGraphNodeFilter; import jqian.sootex.util.callgraph.Callees; import jqian.sootex.util.callgraph.DirectedCallGraph; import jqian.util.SortedArraySet; import soot.*; import soot.jimple.AnyNewExpr; import soot.jimple.ArrayRef; import soot.jimple.InstanceFieldRef; import soot.jimple.NewArrayExpr; import soot.jimple.NewExpr; import soot.jimple.NewMultiArrayExpr; import soot.jimple.StaticFieldRef; import soot.jimple.toolkits.callgraph.*; import soot.toolkits.graph.DirectedGraph; import soot.toolkits.graph.StronglyConnectedComponents; @SuppressWarnings({ "rawtypes", "unchecked" }) public class SideEffectHelper { static Set compact(Collection s) { if (s == null){ return null; } if (s.isEmpty()) { return Collections.EMPTY_SET; } else { return new SortedArraySet(s, NumberableComparator.v()); } } static void mergeCallees(SootMethod m, Set<SootMethod> mergeSources, Set<Location>[] method2Writes, Set<Location>[] method2Reads) { int id = m.getNumber(); Set<Location> defs = method2Writes[id]; Set<Location> uses = method2Reads[id]; for (SootMethod tgt : mergeSources) { int tgtId = tgt.getNumber(); Set tgtDef = method2Writes[tgtId]; Set tgtUse = method2Reads[tgtId]; assert (tgtDef != null && tgtUse != null); defs.addAll(tgtDef); uses.addAll(tgtUse); } } static void collectComponentCallees( Collection<SootMethod> component, CallGraph cg, Collection<SootMethod> out) { for (SootMethod m : component) { Callees callees = new Callees(cg, m); Set<SootMethod> threads = callees.threads(); for (SootMethod tgt : callees.all()) { if (!component.contains(tgt) && !threads.contains(tgt)) { out.add(tgt); } } } } static boolean isRefTgtLocal(ILocalityQuery localityQuery, SootMethod m, Value ap){ if (localityQuery != null) { Local root = null; if (ap instanceof InstanceFieldRef) { root = (Local) ((InstanceFieldRef) ap).getBase(); } else { root = (Local) ((ArrayRef) ap).getBase(); } boolean isLocal = localityQuery.isRefTgtLocal(m, root); if (isLocal) { return true; } } return false; } static void collectRWAccessPaths(SootMethod m, ILocalityQuery locality, Set<AccessPath> mod, Set<AccessPath> use){ if (!m.isConcrete()) return; for (Unit stmt : m.getActiveBody().getUnits()) { for (ValueBox box : stmt.getDefBoxes()) { Value v = box.getValue(); if(v instanceof InstanceFieldRef || v instanceof ArrayRef){ if(!isRefTgtLocal(locality, m, v)){ AccessPath ap = AccessPath.valueToAccessPath(m, stmt, v); mod.add(ap); } } } List<ValueBox> useBoxes = stmt.getUseBoxes(); if (useBoxes == null) continue; for (ValueBox useBox : useBoxes) { Value u = useBox.getValue(); if(u instanceof InstanceFieldRef || u instanceof ArrayRef){ if(!isRefTgtLocal(locality, m, u)){ AccessPath ap = AccessPath.valueToAccessPath(m, stmt, u); use.add(ap); } } else if (u instanceof AnyNewExpr) { // XXX: new instructions have initialization effects Value lhs = stmt.getDefBoxes().get(0).getValue(); if (locality!=null && locality.isRefTgtLocal(m, (Local)lhs)) { continue; } AccessPath left = AccessPath.valueToAccessPath(m, stmt, lhs); if (u instanceof NewExpr) { RefType type = (RefType) u.getType(); SootClass cls = type.getSootClass(); if (!AtomicTypes.isAtomicType(cls)) { Collection<SootField> fields = Cache.v().getAllInstanceFields(cls); for (SootField f : fields) { AccessPath ap = left.appendFieldRef(f); mod.add(ap); } } } else if (u instanceof NewArrayExpr || u instanceof NewMultiArrayExpr) { AccessPath ap = left.appendArrayRef(); mod.add(ap); } } } } } static void collectRWStaticFields(SootMethod m, Set mod, Set use) { if (!m.isConcrete()) return; for (Unit stmt : m.getActiveBody().getUnits()) { List<ValueBox> defBoxes = stmt.getDefBoxes(); for (ValueBox box : defBoxes) { Value v = box.getValue(); if (v instanceof StaticFieldRef) { StaticFieldRef ref = (StaticFieldRef) v; GlobalLocation loc = Location.getGlobalLocation(ref.getField()); mod.add(loc); } } List<ValueBox> useBoxes = stmt.getUseBoxes(); if (useBoxes != null) { for (ValueBox useBox : useBoxes) { Value v = useBox.getValue(); if (v instanceof StaticFieldRef) { StaticFieldRef ref = (StaticFieldRef) v; SootField f = ref.getField(); //XXX: Treat static final fields as constants if(!f.isFinal()){ GlobalLocation loc = Location.getGlobalLocation(f); use.add(loc); } } } } } } }