KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > SootResolver


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2000 Patrice Pominville
3  * Copyright (C) 2004 Ondrej Lhotak, Ganesh Sittampalam
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */

20
21 /*
22  * Modified by the Sable Research Group and others 1997-1999.
23  * See the 'credits' file distributed with Soot for the complete list of
24  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
25  */

26
27
28 package soot;
29 import soot.*;
30 import soot.options.*;
31
32 import soot.coffi.*;
33 import java.util.*;
34 import java.io.*;
35 import soot.util.*;
36 import soot.jimple.*;
37 import soot.javaToJimple.*;
38
39 /** Loads symbols for SootClasses from either class files or jimple files. */
40 public class SootResolver
41 {
42     /** Maps each resolved class to a list of all references in it. */
43     private Map classToReferences = new HashMap();
44     
45     /** SootClasses waiting to be resolved. */
46     private LinkedList/*SootClass*/[] worklist = new LinkedList[4];
47
48     public SootResolver (Singletons.Global g) {
49         worklist[SootClass.HIERARCHY] = new LinkedList();
50         worklist[SootClass.SIGNATURES] = new LinkedList();
51         worklist[SootClass.BODIES] = new LinkedList();
52     }
53
54     public static SootResolver v() { return G.v().soot_SootResolver();}
55     
56     /** Returns true if we are resolving all class refs recursively. */
57     private boolean resolveEverything() {
58         return( Options.v().whole_program() || Options.v().whole_shimple()
59     || Options.v().full_resolver()
60     || Options.v().output_format() == Options.v().output_format_dava );
61     }
62
63     /** Returns a (possibly not yet resolved) SootClass to be used in references
64      * to a class. If/when the class is resolved, it will be resolved into this
65      * SootClass.
66      * */

67     public SootClass makeClassRef(String JavaDoc className)
68     {
69         if(Scene.v().containsClass(className))
70             return Scene.v().getSootClass(className);
71
72         SootClass newClass;
73         newClass = new SootClass(className);
74         newClass.setResolvingLevel(SootClass.DANGLING);
75         Scene.v().addClass(newClass);
76
77         return newClass;
78     }
79
80
81     /**
82      * Resolves the given class. Depending on the resolver settings, may
83      * decide to resolve other classes as well. If the class has already
84      * been resolved, just returns the class that was already resolved.
85      * */

86     public SootClass resolveClass(String JavaDoc className, int desiredLevel) {
87         SootClass resolvedClass = makeClassRef(className);
88         addToResolveWorklist(resolvedClass, desiredLevel);
89         processResolveWorklist();
90         return resolvedClass;
91     }
92
93     /** Resolve all classes on toResolveWorklist. */
94     private void processResolveWorklist() {
95         for( int i = SootClass.BODIES; i >= SootClass.HIERARCHY; i-- ) {
96             while( !worklist[i].isEmpty() ) {
97                 SootClass sc = (SootClass) worklist[i].removeFirst();
98                 if( resolveEverything() ) {
99                     if( sc.isPhantom() ) bringToSignatures(sc);
100                     else bringToBodies(sc);
101                 } else {
102                     switch(i) {
103                         case SootClass.BODIES: bringToBodies(sc); break;
104                         case SootClass.SIGNATURES: bringToSignatures(sc); break;
105                         case SootClass.HIERARCHY: bringToHierarchy(sc); break;
106                     }
107                 }
108             }
109         }
110     }
111
112     private void addToResolveWorklist(Type type, int level) {
113         if( type instanceof RefType )
114             addToResolveWorklist(((RefType) type).getClassName(), level);
115         else if( type instanceof ArrayType )
116             addToResolveWorklist(((ArrayType) type).baseType, level);
117     }
118     private void addToResolveWorklist(String JavaDoc className, int level) {
119         addToResolveWorklist(makeClassRef(className), level);
120     }
121     private void addToResolveWorklist(SootClass sc, int desiredLevel) {
122         if( sc.resolvingLevel() >= desiredLevel ) return;
123         worklist[desiredLevel].add(sc);
124     }
125
126     /** Hierarchy - we know the hierarchy of the class and that's it
127      * requires at least Hierarchy for all supertypes and enclosing types.
128      * */

129     private void bringToHierarchy(SootClass sc) {
130         if(sc.resolvingLevel() >= SootClass.HIERARCHY ) return;
131         if(Options.v().debug_resolver())
132             G.v().out.println("bringing to HIERARCHY: "+sc);
133         sc.setResolvingLevel(SootClass.HIERARCHY);
134
135         String JavaDoc className = sc.getName();
136         ClassSource is = SourceLocator.v().getClassSource(className);
137         if( is == null ) {
138             if(!Scene.v().allowsPhantomRefs()) {
139                 throw new RuntimeException JavaDoc("couldn't find class: " +
140                     className + " (is your soot-class-path set properly?)");
141             } else {
142                 G.v().out.println(
143                         "Warning: " + className + " is a phantom class!");
144                 sc.setPhantomClass();
145                 classToReferences.put( sc, new ArrayList() );
146             }
147         } else {
148             Collection references = is.resolve(sc);
149             classToReferences.put( sc, new ArrayList(new HashSet(references)) );
150         }
151         reResolveHierarchy(sc);
152     }
153
154     public void reResolveHierarchy(SootClass sc) {
155         // Bring superclasses to hierarchy
156
if(sc.hasSuperclass())
157             addToResolveWorklist(sc.getSuperclass(), SootClass.HIERARCHY);
158         if(sc.hasOuterClass())
159             addToResolveWorklist(sc.getOuterClass(), SootClass.HIERARCHY);
160         for( Iterator ifaceIt = sc.getInterfaces().iterator(); ifaceIt.hasNext(); ) {
161             final SootClass iface = (SootClass) ifaceIt.next();
162             addToResolveWorklist(iface, SootClass.HIERARCHY);
163         }
164
165     }
166
167     /** Signatures - we know the signatures of all methods and fields
168     * requires at least Hierarchy for all referred to types in these signatures.
169     * */

170     private void bringToSignatures(SootClass sc) {
171         if(sc.resolvingLevel() >= SootClass.SIGNATURES ) return;
172         bringToHierarchy(sc);
173         if(Options.v().debug_resolver())
174             G.v().out.println("bringing to SIGNATURES: "+sc);
175         sc.setResolvingLevel(SootClass.SIGNATURES);
176
177         for( Iterator fIt = sc.getFields().iterator(); fIt.hasNext(); ) {
178
179             final SootField f = (SootField) fIt.next();
180             addToResolveWorklist( f.getType(), SootClass.HIERARCHY );
181         }
182         for( Iterator mIt = sc.getMethods().iterator(); mIt.hasNext(); ) {
183             final SootMethod m = (SootMethod) mIt.next();
184             addToResolveWorklist( m.getReturnType(), SootClass.HIERARCHY );
185             for( Iterator ptypeIt = m.getParameterTypes().iterator(); ptypeIt.hasNext(); ) {
186                 final Type ptype = (Type) ptypeIt.next();
187                 addToResolveWorklist( ptype, SootClass.HIERARCHY );
188             }
189             for( Iterator exceptionIt = m.getExceptions().iterator(); exceptionIt.hasNext(); ) {
190                 final SootClass exception = (SootClass) exceptionIt.next();
191                 addToResolveWorklist( exception, SootClass.HIERARCHY );
192             }
193         }
194
195         // Bring superclasses to signatures
196
if(sc.hasSuperclass())
197             addToResolveWorklist(sc.getSuperclass(), SootClass.SIGNATURES);
198         for( Iterator ifaceIt = sc.getInterfaces().iterator(); ifaceIt.hasNext(); ) {
199             final SootClass iface = (SootClass) ifaceIt.next();
200             addToResolveWorklist(iface, SootClass.SIGNATURES);
201         }
202     }
203
204     /** Bodies - we can now start loading the bodies of methods
205     * for all referred to methods and fields in the bodies, requires
206     * signatures for the method receiver and field container, and
207     * hierarchy for all other classes referenced in method references.
208     * Current implementation does not distinguish between the receiver
209     * and other references. Therefore, it is conservative and brings all
210     * of them to signatures. But this could/should be improved.
211     * */

212     private void bringToBodies(SootClass sc) {
213         if(sc.resolvingLevel() >= SootClass.BODIES ) return;
214         bringToSignatures(sc);
215         if(Options.v().debug_resolver())
216             G.v().out.println("bringing to BODIES: "+sc);
217         sc.setResolvingLevel(SootClass.BODIES);
218
219         Collection references = (Collection) classToReferences.get(sc);
220         if( references == null ) return;
221
222         Iterator it = references.iterator();
223         while( it.hasNext() ) {
224             final Object JavaDoc o = it.next();
225
226             if( o instanceof String JavaDoc ) {
227                 addToResolveWorklist((String JavaDoc) o, SootClass.SIGNATURES);
228             } else if( o instanceof Type ) {
229                 addToResolveWorklist((Type) o, SootClass.SIGNATURES);
230             } else throw new RuntimeException JavaDoc(o.toString());
231         }
232     }
233
234     public void reResolve(SootClass cl) {
235         int resolvingLevel = cl.resolvingLevel();
236         if( resolvingLevel < SootClass.HIERARCHY ) return;
237         reResolveHierarchy(cl);
238         cl.setResolvingLevel(SootClass.HIERARCHY);
239         addToResolveWorklist(cl, resolvingLevel);
240         processResolveWorklist();
241     }
242 }
243
244
245
Popular Tags