1 19 20 25 26 27 28 29 30 31 package soot.toolkits.graph; 32 33 import soot.*; 34 import soot.util.*; 35 import java.util.*; 36 import soot.options.Options; 37 import soot.toolkits.exceptions.ThrowAnalysis; 38 import soot.toolkits.exceptions.UnitThrowAnalysis; 39 import soot.toolkits.exceptions.ThrowableSet; 40 import soot.baf.Inst; 41 import soot.baf.NewInst; 42 import soot.baf.StaticPutInst; 43 import soot.baf.StaticGetInst; 44 import soot.baf.ThrowInst; 45 import soot.jimple.Stmt; 46 import soot.jimple.ThrowStmt; 47 import soot.jimple.StaticFieldRef; 48 import soot.jimple.InvokeExpr; 49 import soot.jimple.NewExpr; 50 51 52 86 public class ExceptionalUnitGraph extends UnitGraph implements ExceptionalGraph 87 { 88 protected Map unitToUnexceptionalSuccs; protected Map unitToUnexceptionalPreds; 93 protected Map unitToExceptionalSuccs; 94 protected Map unitToExceptionalPreds; 95 protected Map unitToExceptionDests; 96 97 protected ThrowAnalysis throwAnalysis; 104 105 145 public ExceptionalUnitGraph(Body body, ThrowAnalysis throwAnalysis, 146 boolean omitExceptingUnitEdges) { 147 super(body); 148 initialize(throwAnalysis, omitExceptingUnitEdges); 149 } 150 151 152 164 public ExceptionalUnitGraph(Body body, ThrowAnalysis throwAnalysis) { 165 this(body, throwAnalysis, Options.v().omit_excepting_unit_edges()); 166 } 167 168 169 179 public ExceptionalUnitGraph(Body body) { 180 this(body, Scene.v().getDefaultThrowAnalysis(), 181 Options.v().omit_excepting_unit_edges()); 182 } 183 184 185 215 protected ExceptionalUnitGraph(Body body, boolean ignoredBogusParameter) { 216 super(body); 217 } 218 219 220 236 protected void initialize(ThrowAnalysis throwAnalysis, 237 boolean omitExceptingUnitEdges) { 238 int size = unitChain.size(); 239 Set trapsThatAreHeads = Collections.EMPTY_SET; 240 241 if(Options.v().time()) 242 Timers.v().graphTimer.start(); 243 244 unitToUnexceptionalSuccs = new HashMap(size * 2 + 1, 0.7f); 245 unitToUnexceptionalPreds = new HashMap(size * 2 + 1, 0.7f); 246 buildUnexceptionalEdges(unitToUnexceptionalSuccs, 247 unitToUnexceptionalPreds); 248 makeMappedListsUnmodifiable(unitToUnexceptionalSuccs); 249 makeMappedListsUnmodifiable(unitToUnexceptionalPreds); 250 this.throwAnalysis = throwAnalysis; 251 252 if (body.getTraps().size() == 0) { 253 unitToExceptionDests = Collections.EMPTY_MAP; 256 unitToExceptionalSuccs = Collections.EMPTY_MAP; 257 unitToExceptionalPreds = Collections.EMPTY_MAP; 258 unitToSuccs = unitToUnexceptionalSuccs; 259 unitToPreds = unitToUnexceptionalPreds; 260 261 } else { 262 unitToExceptionDests = buildExceptionDests(throwAnalysis); 263 unitToExceptionalSuccs = 264 new HashMap(unitToExceptionDests.size() * 2 + 1, 0.7f); 265 unitToExceptionalPreds = 266 new HashMap(body.getTraps().size() * 2 + 1, 0.7f); 267 trapsThatAreHeads = buildExceptionalEdges(throwAnalysis, 268 unitToExceptionDests, 269 unitToExceptionalSuccs, 270 unitToExceptionalPreds, 271 omitExceptingUnitEdges); 272 makeMappedListsUnmodifiable(unitToExceptionalSuccs); 273 makeMappedListsUnmodifiable(unitToExceptionalPreds); 274 275 unitToSuccs = combineMapValues(unitToUnexceptionalSuccs, 278 unitToExceptionalSuccs); 279 unitToPreds = combineMapValues(unitToUnexceptionalPreds, 280 unitToExceptionalPreds); 281 } 282 283 buildHeadsAndTails(trapsThatAreHeads); 284 285 if(Options.v().time()) 286 Timers.v().graphTimer.end(); 287 288 soot.util.PhaseDumper.v().dumpGraph(this); 289 } 290 291 292 326 protected Map buildExceptionDests(ThrowAnalysis throwAnalysis) { 327 Chain units = body.getUnits(); 328 Map unitToUncaughtThrowables = new HashMap(units.size()); 329 Map result = null; 330 FastHierarchy hier = Scene.v().getOrMakeFastHierarchy(); 331 332 for (Iterator trapIt = body.getTraps().iterator(); trapIt.hasNext(); ) { 334 Trap trap = (Trap) trapIt.next(); 335 RefType catcher = trap.getException().getType(); 336 for (Iterator unitIt = units.iterator(trap.getBeginUnit(), 337 units.getPredOf(trap.getEndUnit())); 338 unitIt.hasNext(); ) { 339 Unit unit = (Unit) unitIt.next(); 340 ThrowableSet thrownSet = (ThrowableSet) unitToUncaughtThrowables.get(unit); 341 if (thrownSet == null) { 342 thrownSet = throwAnalysis.mightThrow(unit); 343 } 344 ThrowableSet.Pair catchableAs = thrownSet.whichCatchableAs(catcher); 345 if (catchableAs.getCaught() != ThrowableSet.Manager.v().EMPTY) { 346 result = addDestToMap(result, unit, trap, catchableAs.getCaught()); 347 unitToUncaughtThrowables.put(unit, catchableAs.getUncaught()); 348 } else { 349 if (thrownSet != catchableAs.getUncaught()) { 351 throw new IllegalStateException ("ExceptionalUnitGraph.buildExceptionDests(): catchableAs.caught == EMPTY, but catchableAs.uncaught != thrownSet" 352 + System.getProperty("line.separator") + body.getMethod().getSubSignature() + " Unit: " + unit.toString() 353 + System.getProperty("line.separator") + " catchableAs.getUncaught() == " + catchableAs.getUncaught().toString() 354 + System.getProperty("line.separator") + " thrownSet == " + thrownSet.toString()); 355 } 356 } 357 } 358 } 359 360 for (Iterator entryIt = unitToUncaughtThrowables.entrySet().iterator(); 364 entryIt.hasNext(); ) { 365 Map.Entry entry = (Map.Entry) entryIt.next(); 366 Unit unit = (Unit) entry.getKey(); 367 ThrowableSet escaping = (ThrowableSet) entry.getValue(); 368 if (escaping != ThrowableSet.Manager.v().EMPTY) { 369 result = addDestToMap(result, unit, null, escaping); 370 } 371 } 372 if (result == null) { 373 result = Collections.EMPTY_MAP; 374 } 375 return result; 376 } 377 378 379 402 private Map addDestToMap(Map map, Unit u, Trap t, ThrowableSet caught) { 403 Collection dests = (map == null ? null : (Collection) map.get(u)); 404 if (dests == null) { 405 if (t == null) { 406 return map; 408 } else { 409 if (map == null) { 410 map = new HashMap(unitChain.size() * 2 + 1); 411 } 412 dests = new ArrayList(3); 413 map.put(u, dests); 414 } 415 } 416 dests.add(new ExceptionDest(t, caught)); 417 return map; 418 } 419 420 421 468 protected Set buildExceptionalEdges(ThrowAnalysis throwAnalysis, 469 Map unitToDests, 470 Map unitToSuccs, Map unitToPreds, 471 boolean omitExceptingUnitEdges) { 472 Set trapsThatAreHeads = new ArraySet(); 473 Unit entryPoint = (Unit) unitChain.getFirst(); 474 475 for (Iterator it = unitToDests.entrySet().iterator(); 476 it.hasNext(); ) { 477 Map.Entry entry = (Map.Entry) it.next(); 478 Unit thrower = (Unit) entry.getKey(); 479 List throwersPreds = getUnexceptionalPredsOf(thrower); 480 Collection dests = (Collection) entry.getValue(); 481 482 515 boolean alwaysAddSelfEdges = ((! omitExceptingUnitEdges) || 516 mightHaveSideEffects(thrower)); 517 ThrowableSet predThrowables = null; 518 ThrowableSet selfThrowables = null; 519 if (thrower instanceof ThrowInst) { 520 ThrowInst throwInst = (ThrowInst) thrower; 521 predThrowables = throwAnalysis.mightThrowImplicitly(throwInst); 522 selfThrowables = throwAnalysis.mightThrowExplicitly(throwInst); 523 } else if (thrower instanceof ThrowStmt) { 524 ThrowStmt throwStmt = (ThrowStmt) thrower; 525 predThrowables = throwAnalysis.mightThrowImplicitly(throwStmt); 526 selfThrowables = throwAnalysis.mightThrowExplicitly(throwStmt); 527 } 528 529 for (Iterator destIt = dests.iterator(); destIt.hasNext(); ) { 530 ExceptionDest dest = (ExceptionDest) destIt.next(); 531 if (dest.getTrap() != null) { 532 Unit catcher = dest.getTrap().getHandlerUnit(); 533 RefType trapsType = dest.getTrap().getException().getType(); 534 if (predThrowables == null || 535 predThrowables.catchableAs(trapsType)) { 536 if (thrower == entryPoint) { 538 trapsThatAreHeads.add(catcher); 539 } 540 for (Iterator p = throwersPreds.iterator(); p.hasNext(); ) { 541 Unit pred = (Unit) p.next(); 542 addEdge(unitToSuccs, unitToPreds, pred, catcher); 543 } 544 } 545 if (alwaysAddSelfEdges || 546 (selfThrowables != null && 547 selfThrowables.catchableAs(trapsType))) { 548 addEdge(unitToSuccs, unitToPreds, thrower, catcher); 549 } 550 } 551 } 552 } 553 554 class CFGEdge { 559 Unit head; Unit tail; 566 567 CFGEdge(Unit head, Unit tail) { 568 if (tail == null) 569 throw new RuntimeException ("invalid CFGEdge(" 570 + head.toString() + ',' 571 + tail.toString() + ')'); 572 this.head = head; 573 this.tail = tail; 574 } 575 576 public boolean equals(Object rhs) { 577 if (rhs == this) { 578 return true; 579 } 580 if (! (rhs instanceof CFGEdge)) { 581 return false; 582 } 583 CFGEdge rhsEdge = (CFGEdge) rhs; 584 return ((this.head == rhsEdge.head) && 585 (this.tail == rhsEdge.tail)); 586 } 587 588 public int hashCode() { 589 int result = 17; 591 result = 37 * result + this.head.hashCode(); 592 result = 37 * result + this.tail.hashCode(); 593 return result; 594 } 595 } 596 597 LinkedList workList = new LinkedList(); 598 599 for (Iterator trapIt = body.getTraps().iterator(); trapIt.hasNext(); ) { 600 Trap trap = (Trap) trapIt.next(); 601 Unit handlerStart = trap.getHandlerUnit(); 602 if (mightThrowToIntraproceduralCatcher(handlerStart)) { 603 List handlerPreds = getUnexceptionalPredsOf(handlerStart); 604 for (Iterator it = handlerPreds.iterator(); it.hasNext(); ) { 605 Unit pred = (Unit) it.next(); 606 workList.addLast(new CFGEdge(pred, handlerStart)); 607 } 608 handlerPreds = getExceptionalPredsOf(handlerStart); 609 for (Iterator it = handlerPreds.iterator(); it.hasNext(); ) { 610 Unit pred = (Unit) it.next(); 611 workList.addLast(new CFGEdge(pred, handlerStart)); 612 } 613 if (trapsThatAreHeads.contains(handlerStart)) { 614 workList.addLast(new CFGEdge(null, handlerStart)); 615 } 616 } 617 } 618 619 while (workList.size() > 0) { 624 CFGEdge edgeToThrower = (CFGEdge) workList.removeFirst(); 625 Unit pred = edgeToThrower.head; 626 Unit thrower = edgeToThrower.tail; 627 Collection throwerDests = getExceptionDests(thrower); 628 for (Iterator i = throwerDests.iterator(); i.hasNext(); ) { 629 ExceptionDest dest = (ExceptionDest) i.next(); 630 if (dest.getTrap() != null) { 631 Unit handlerStart = dest.getTrap().getHandlerUnit(); 632 boolean edgeAdded = false; 633 if (pred == null) { 634 if (! trapsThatAreHeads.contains(handlerStart)) { 635 trapsThatAreHeads.add(handlerStart); 636 edgeAdded = true; 637 } 638 } else { 639 if (! getExceptionalSuccsOf(pred).contains(handlerStart)) { 640 addEdge(unitToSuccs, unitToPreds, pred, handlerStart); 641 edgeAdded = true; 642 } 643 } 644 if (edgeAdded && 645 mightThrowToIntraproceduralCatcher(handlerStart)) { 646 workList.addLast(new CFGEdge(pred, handlerStart)); 647 } 648 } 649 } 650 } 651 return trapsThatAreHeads; 652 } 653 654 655 671 static boolean mightHaveSideEffects(Unit u) { 672 if (u instanceof Inst) { 673 Inst i = (Inst) u; 674 return (i.containsInvokeExpr() || 675 (i instanceof StaticPutInst) || 676 (i instanceof StaticGetInst) || 677 (i instanceof NewInst)); 678 } else if (u instanceof Stmt) { 679 for (Iterator it = u.getUseBoxes().iterator(); it.hasNext(); ) { 680 Value v = ((ValueBox)(it.next())).getValue(); 681 if ((v instanceof StaticFieldRef) || 682 (v instanceof InvokeExpr) || 683 (v instanceof NewExpr)) { 684 return true; 685 } 686 } 687 } 688 return false; 689 } 690 691 692 701 private boolean mightThrowToIntraproceduralCatcher(Unit u) { 702 Collection dests = getExceptionDests(u); 703 for (Iterator i = dests.iterator(); i.hasNext(); ) { 704 ExceptionDest dest = (ExceptionDest) i.next(); 705 if (dest.getTrap() != null) { 706 return true; 707 } 708 } 709 return false; 710 } 711 712 713 733 protected void buildHeadsAndTails() throws IllegalStateException { 734 throw new IllegalStateException ("ExceptionalUnitGraph uses buildHeadsAndTails(List) instead of buildHeadsAndTails()"); 735 } 736 737 738 748 private void buildHeadsAndTails(Set additionalHeads) { 749 List headList = new ArrayList(additionalHeads.size() + 1); 750 headList.addAll(additionalHeads); 751 Unit entryPoint = (Unit) unitChain.getFirst(); 752 if (! headList.contains(entryPoint)) { 753 headList.add(entryPoint); 754 } 755 756 List tailList = new ArrayList(); 757 for (Iterator it = unitChain.iterator(); it.hasNext(); ) { 758 Unit u = (Unit) it.next(); 759 if (u instanceof soot.jimple.ReturnStmt || 760 u instanceof soot.jimple.ReturnVoidStmt || 761 u instanceof soot.baf.ReturnInst || 762 u instanceof soot.baf.ReturnVoidInst) { 763 tailList.add(u); 764 } else if (u instanceof soot.jimple.ThrowStmt || 765 u instanceof soot.baf.ThrowInst) { 766 Collection dests = getExceptionDests(u); 767 int escapeMethodCount = 0; 768 for (Iterator destIt = dests.iterator(); destIt.hasNext(); ) { 769 ExceptionDest dest = (ExceptionDest) destIt.next(); 770 if (dest.getTrap() == null) { 771 escapeMethodCount++; 772 } 773 } 774 if (escapeMethodCount > 0) { 775 tailList.add(u); 776 } 777 } 778 } 779 tails = Collections.unmodifiableList(tailList); 780 heads = Collections.unmodifiableList(headList); 781 } 782 783 784 799 public Collection getExceptionDests(Object u) { 800 Collection result = (Collection) unitToExceptionDests.get(u); 801 if (result == null) { 802 result = new LinkedList(); 803 result.add(new ExceptionDest(null, throwAnalysis.mightThrow((Unit) u))); 804 } 805 return result; 806 } 807 808 809 public static class ExceptionDest implements ExceptionalGraph.ExceptionDest { 810 private Trap trap; 811 private ThrowableSet throwables; 812 813 protected ExceptionDest(Trap trap, ThrowableSet throwables) { 814 this.trap = trap; 815 this.throwables = throwables; 816 } 817 818 public Trap getTrap() { 819 return trap; 820 } 821 822 public ThrowableSet getThrowables() { 823 return throwables; 824 } 825 826 public Object getHandlerNode() { 827 if (trap == null) { 828 return null; 829 } else { 830 return trap.getHandlerUnit(); 831 } 832 } 833 834 public String toString() { 835 StringBuffer buf = new StringBuffer (); 836 buf.append(throwables.toString()); 837 buf.append(" -> "); 838 if (trap == null) { 839 buf.append("(escapes)"); 840 } else { 841 buf.append(trap.toString()); 842 } 843 return buf.toString(); 844 } 845 } 846 847 848 public List getUnexceptionalPredsOf(Object u) { 849 if (!unitToUnexceptionalPreds.containsKey(u)) 850 throw new RuntimeException ("Invalid unit " + u); 851 852 return (List) unitToUnexceptionalPreds.get(u); 853 } 854 855 856 public List getUnexceptionalSuccsOf(Object u) { 857 if (!unitToUnexceptionalSuccs.containsKey(u)) 858 throw new RuntimeException ("Invalid unit " + u); 859 860 return (List) unitToUnexceptionalSuccs.get(u); 861 } 862 863 864 public List getExceptionalPredsOf(Object u) { 865 if (!unitToExceptionalPreds.containsKey(u)) { 866 return Collections.EMPTY_LIST; 867 } else { 868 return (List) unitToExceptionalPreds.get(u); 869 } 870 } 871 872 873 public List getExceptionalSuccsOf(Object u) { 874 if (!unitToExceptionalSuccs.containsKey(u)) { 875 return Collections.EMPTY_LIST; 876 } else { 877 return (List) unitToExceptionalSuccs.get(u); 878 } 879 } 880 881 882 903 ThrowAnalysis getThrowAnalysis() { 904 return throwAnalysis; 905 } 906 907 908 public String toString() { 909 Iterator it = unitChain.iterator(); 910 StringBuffer buf = new StringBuffer (); 911 while(it.hasNext()) { 912 Unit u = (Unit) it.next(); 913 914 buf.append("// preds: "+getPredsOf(u)+"\n"); 915 buf.append("// unexceptional preds: "+getUnexceptionalPredsOf(u)+"\n"); 916 buf.append("// exceptional preds: "+getExceptionalPredsOf(u)+"\n"); 917 buf.append(u.toString() + '\n'); 918 buf.append("// exception destinations: "+getExceptionDests(u)+"\n"); 919 buf.append("// unexceptional succs: "+getUnexceptionalPredsOf(u)+"\n"); 920 buf.append("// exceptional succs: "+getExceptionalPredsOf(u)+"\n"); 921 buf.append("// succs "+getSuccsOf(u)+"\n"); 922 } 923 924 return buf.toString(); 925 } 926 } 927 | Popular Tags |