package jqian.sootex.util; import java.util.*; import soot.*; import soot.toolkits.graph.*; /** * FIX 2008-07-12 An error occurred in handling exceptional flows */ public class HammockCFG extends UnitGraph{ protected Collection<Unit> _units; //valid units, may be a part of unitChain protected List<Unit> _heads; protected List<Unit> _tails; @SuppressWarnings("unchecked") public HammockCFG(Body body) { super(body); int size = unitChain.size(); unitToSuccs = new HashMap<Unit,List<Unit>>(size * 2 + 1, 0.7f); unitToPreds = new HashMap<Unit,List<Unit>>(size * 2 + 1, 0.7f); //Get the unique entry Unit entryPoint = unitChain.getFirst(); List<Unit> nonExceptionalEntries = new ArrayList<Unit>(1); nonExceptionalEntries.add(entryPoint); //set entry links Unit entry = CFGEntry.v(); _heads = new ArrayList<Unit>(1); _heads.add(entry); unitToPreds.put(entry,Collections.EMPTY_LIST); unitToSuccs.put(entry,nonExceptionalEntries); for (Unit s: nonExceptionalEntries) { List<Unit> preds = new ArrayList<Unit>(1); preds.add(entry); unitToPreds.put(s, preds); } //tailor graph List<Unit> ends = new LinkedList<Unit>(); Set<Unit> processed = new HashSet<Unit>(); Stack<Unit> stack = new Stack<Unit>(); stack.addAll(nonExceptionalEntries); while (!stack.isEmpty()) { Unit s = (Unit) stack.pop(); if (!processed.add(s)) { continue; } //set successors List<Unit> succs = findSuccsOf(s); unitToSuccs.put(s,succs); if(succs.size()==0){ ends.add(s); } for (Unit next: succs) { List<Unit> preds = assurePredsList(next); preds.add(s); if (!processed.contains(next)) { stack.add(next); } } } //set exit links Unit exit = CFGExit.v(); unitToPreds.put(exit, ends); unitToSuccs.put(exit, Collections.EMPTY_LIST); for (Unit s: ends) { List<Unit> succs = new ArrayList<Unit>(1); succs.add(exit); unitToSuccs.put(s,succs); } _tails = new ArrayList<Unit>(1); _tails.add(exit); _units = unitToSuccs.keySet(); } private List<Unit> findSuccsOf(Unit unit) { List<Unit> successors = new ArrayList<Unit>(); if (unit.fallsThrough()) { Unit next = unitChain.getSuccOf(unit); if (next != null) { successors.add(next); } } if (unit.branches()) { for (Iterator<UnitBox> targetIt = unit.getUnitBoxes().iterator(); targetIt.hasNext();) { Unit target = targetIt.next().getUnit(); // Arbitrary bytecode can branch to the same // target it falls through to, so we screen for duplicates: if (!successors.contains(target)) { successors.add(target); } } } return successors; } private List<Unit> assurePredsList(Unit s){ List<Unit> preds = unitToPreds.get(s); if(preds==null){ preds = new ArrayList<Unit>(); unitToPreds.put(s,preds); } return preds; } /** Return a single entry CFGEntry.v(). */ public List<Unit> getHeads() { return _heads; } public List<Unit> getTails() { return _tails; } public List<Unit> getPredsOf(Unit s) { return unitToPreds.get(s); } public List<Unit> getSuccsOf(Unit s) { return unitToSuccs.get(s); } public Iterator<Unit> iterator() { return _units.iterator(); } public int size() { return _units.size(); } ////////////////////////////////////////////////// public List<Unit> getExtendedBasicBlockPathBetween(Unit from, Unit to){ return null; } public String toString() { StringBuffer buf = new StringBuffer(); for(Unit u: _units) { buf.append("// preds: " + getPredsOf(u) + "\n"); buf.append(u.toString() + '\n'); buf.append("// succs " + getSuccsOf(u) + "\n"); } return buf.toString(); } public Object clone(){ return new HammockCFG(this.method.getActiveBody()); } }