1 19 20 package soot.jimple.toolkits.callgraph; 21 import soot.*; 22 import soot.jimple.*; 23 import java.util.*; 24 import soot.util.*; 25 import soot.util.queue.*; 26 27 30 public final class VirtualCalls 31 { 32 public VirtualCalls( Singletons.Global g ) {} 33 public static VirtualCalls v() { return G.v().soot_jimple_toolkits_callgraph_VirtualCalls(); } 34 35 private LargeNumberedMap typeToVtbl = 36 new LargeNumberedMap( Scene.v().getTypeNumberer() ); 37 38 public SootMethod resolveSpecial( SpecialInvokeExpr iie, NumberedString subSig, SootMethod container ) { 39 SootMethod target = iie.getMethod(); 40 41 if( Scene.v().getOrMakeFastHierarchy() 42 .canStoreType( container.getDeclaringClass().getType(), 43 target.getDeclaringClass().getType() ) 44 && container.getDeclaringClass().getType() != 45 target.getDeclaringClass().getType() 46 && !target.getName().equals( "<init>" ) 47 && subSig != sigClinit ) { 48 49 return resolveNonSpecial( 50 container.getDeclaringClass().getSuperclass().getType(), 51 subSig ); 52 } else { 53 return target; 54 } 55 } 56 57 public SootMethod resolveNonSpecial( RefType t, NumberedString subSig ) { 58 SmallNumberedMap vtbl = (SmallNumberedMap) typeToVtbl.get( t ); 59 if( vtbl == null ) { 60 typeToVtbl.put( t, vtbl = 61 new SmallNumberedMap( Scene.v().getMethodNumberer() ) ); 62 } 63 SootMethod ret = (SootMethod) vtbl.get( subSig ); 64 if( ret != null ) return ret; 65 SootClass cls = ((RefType)t).getSootClass(); 66 if( cls.declaresMethod( subSig ) ) { 67 SootMethod m = cls.getMethod( subSig ); 68 if( m.isConcrete() || m.isNative() ) { 69 ret = cls.getMethod( subSig ); 70 } 71 } else { 72 if( cls.hasSuperclass() ) { 73 ret = resolveNonSpecial( cls.getSuperclass().getType(), subSig ); 74 } 75 } 76 vtbl.put( subSig, ret ); 77 return ret; 78 } 79 80 private Map baseToSubTypes = new HashMap(); 81 82 public void resolve( Type t, Type declaredType, NumberedString subSig, SootMethod container, ChunkedQueue targets ) { 83 resolve(t, declaredType, null, subSig, container, targets); 84 } 85 public void resolve( Type t, Type declaredType, Type sigType, NumberedString subSig, SootMethod container, ChunkedQueue targets ) { 86 if( declaredType instanceof ArrayType ) declaredType = RefType.v("java.lang.Object"); 87 if( sigType instanceof ArrayType ) sigType = RefType.v("java.lang.Object"); 88 if( t instanceof ArrayType ) t = RefType.v( "java.lang.Object" ); 89 if( declaredType != null && !Scene.v().getOrMakeFastHierarchy() 90 .canStoreType( t, declaredType ) ) { 91 return; 92 } 93 if( sigType != null && !Scene.v().getOrMakeFastHierarchy() 94 .canStoreType( t, sigType ) ) { 95 return; 96 } 97 if( t instanceof RefType ) { 98 SootMethod target = resolveNonSpecial( (RefType) t, subSig ); 99 if( target != null ) targets.add( target ); 100 } else if( t instanceof AnySubType ) { 101 RefType base = ((AnySubType)t).getBase(); 102 103 List subTypes = (List) baseToSubTypes.get(base); 104 if( subTypes != null ) { 105 for( Iterator stIt = subTypes.iterator(); stIt.hasNext(); ) { 106 final Type st = (Type) stIt.next(); 107 resolve( st, declaredType, sigType, subSig, container, targets ); 108 } 109 return; 110 } 111 112 baseToSubTypes.put(base, subTypes = new ArrayList() ); 113 114 subTypes.add(base); 115 116 LinkedList worklist = new LinkedList(); 117 HashSet workset = new HashSet(); 118 FastHierarchy fh = Scene.v().getOrMakeFastHierarchy(); 119 SootClass cl = base.getSootClass(); 120 121 if( workset.add( cl ) ) worklist.add( cl ); 122 while( !worklist.isEmpty() ) { 123 cl = (SootClass) worklist.removeFirst(); 124 if( cl.isInterface() ) { 125 for( Iterator cIt = fh.getAllImplementersOfInterface(cl).iterator(); cIt.hasNext(); ) { 126 final SootClass c = (SootClass) cIt.next(); 127 if( workset.add( c ) ) worklist.add( c ); 128 } 129 } else { 130 if( cl.isConcrete() ) { 131 resolve( cl.getType(), declaredType, sigType, subSig, container, targets ); 132 subTypes.add(cl.getType()); 133 } 134 for( Iterator cIt = fh.getSubclassesOf( cl ).iterator(); cIt.hasNext(); ) { 135 final SootClass c = (SootClass) cIt.next(); 136 if( workset.add( c ) ) worklist.add( c ); 137 } 138 } 139 } 140 } else if( t instanceof NullType ) { 141 } else { 142 throw new RuntimeException ( "oops "+t ); 143 } 144 } 145 146 public final NumberedString sigClinit = 147 Scene.v().getSubSigNumberer().findOrAdd("void <clinit>()"); 148 public final NumberedString sigStart = 149 Scene.v().getSubSigNumberer().findOrAdd("void start()"); 150 public final NumberedString sigRun = 151 Scene.v().getSubSigNumberer().findOrAdd("void run()"); 152 } 153 154 155 | Popular Tags |