• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Resolve classes, methods, fields, and strings.
19  *
20  * According to the VM spec (v2 5.5), classes may be initialized by use
21  * of the "new", "getstatic", "putstatic", or "invokestatic" instructions.
22  * If we are resolving a static method or static field, we make the
23  * initialization check here.
24  *
25  * (NOTE: the verifier has its own resolve functions, which can be invoked
26  * if a class isn't pre-verified.  Those functions must not update the
27  * "resolved stuff" tables for static fields and methods, because they do
28  * not perform initialization.)
29  */
30 #include "Dalvik.h"
31 
32 #include <stdlib.h>
33 
34 
35 /*
36  * Find the class corresponding to "classIdx", which maps to a class name
37  * string.  It might be in the same DEX file as "referrer", in a different
38  * DEX file, generated by a class loader, or generated by the VM (e.g.
39  * array classes).
40  *
41  * Because the DexTypeId is associated with the referring class' DEX file,
42  * we may have to resolve the same class more than once if it's referred
43  * to from classes in multiple DEX files.  This is a necessary property for
44  * DEX files associated with different class loaders.
45  *
46  * We cache a copy of the lookup in the DexFile's "resolved class" table,
47  * so future references to "classIdx" are faster.
48  *
49  * Note that "referrer" may be in the process of being linked.
50  *
51  * Traditional VMs might do access checks here, but in Dalvik the class
52  * "constant pool" is shared between all classes in the DEX file.  We rely
53  * on the verifier to do the checks for us.
54  *
55  * Does not initialize the class.
56  *
57  * "fromUnverifiedConstant" should only be set if this call is the direct
58  * result of executing a "const-class" or "instance-of" instruction, which
59  * use class constants not resolved by the bytecode verifier.
60  *
61  * Returns NULL with an exception raised on failure.
62  */
dvmResolveClass(const ClassObject * referrer,u4 classIdx,bool fromUnverifiedConstant)63 ClassObject* dvmResolveClass(const ClassObject* referrer, u4 classIdx,
64     bool fromUnverifiedConstant)
65 {
66     DvmDex* pDvmDex = referrer->pDvmDex;
67     ClassObject* resClass;
68     const char* className;
69 
70     /*
71      * Check the table first -- this gets called from the other "resolve"
72      * methods.
73      */
74     resClass = dvmDexGetResolvedClass(pDvmDex, classIdx);
75     if (resClass != NULL)
76         return resClass;
77 
78     LOGVV("--- resolving class %u (referrer=%s cl=%p)\n",
79         classIdx, referrer->descriptor, referrer->classLoader);
80 
81     /*
82      * Class hasn't been loaded yet, or is in the process of being loaded
83      * and initialized now.  Try to get a copy.  If we find one, put the
84      * pointer in the DexTypeId.  There isn't a race condition here --
85      * 32-bit writes are guaranteed atomic on all target platforms.  Worst
86      * case we have two threads storing the same value.
87      *
88      * If this is an array class, we'll generate it here.
89      */
90     className = dexStringByTypeIdx(pDvmDex->pDexFile, classIdx);
91     if (className[0] != '\0' && className[1] == '\0') {
92         /* primitive type */
93         resClass = dvmFindPrimitiveClass(className[0]);
94     } else {
95         resClass = dvmFindClassNoInit(className, referrer->classLoader);
96     }
97 
98     if (resClass != NULL) {
99         /*
100          * If the referrer was pre-verified, the resolved class must come
101          * from the same DEX or from a bootstrap class.  The pre-verifier
102          * makes assumptions that could be invalidated by a wacky class
103          * loader.  (See the notes at the top of oo/Class.c.)
104          *
105          * The verifier does *not* fail a class for using a const-class
106          * or instance-of instruction referring to an unresolveable class,
107          * because the result of the instruction is simply a Class object
108          * or boolean -- there's no need to resolve the class object during
109          * verification.  Instance field and virtual method accesses can
110          * break dangerously if we get the wrong class, but const-class and
111          * instance-of are only interesting at execution time.  So, if we
112          * we got here as part of executing one of the "unverified class"
113          * instructions, we skip the additional check.
114          *
115          * Ditto for class references from annotations and exception
116          * handler lists.
117          */
118         if (!fromUnverifiedConstant &&
119             IS_CLASS_FLAG_SET(referrer, CLASS_ISPREVERIFIED))
120         {
121             ClassObject* resClassCheck = resClass;
122             if (dvmIsArrayClass(resClassCheck))
123                 resClassCheck = resClassCheck->elementClass;
124 
125             if (referrer->pDvmDex != resClassCheck->pDvmDex &&
126                 resClassCheck->classLoader != NULL)
127             {
128                 LOGW("Class resolved by unexpected DEX:"
129                      " %s(%p):%p ref [%s] %s(%p):%p\n",
130                     referrer->descriptor, referrer->classLoader,
131                     referrer->pDvmDex,
132                     resClass->descriptor, resClassCheck->descriptor,
133                     resClassCheck->classLoader, resClassCheck->pDvmDex);
134                 LOGW("(%s had used a different %s during pre-verification)\n",
135                     referrer->descriptor, resClass->descriptor);
136                 dvmThrowException("Ljava/lang/IllegalAccessError;",
137                     "Class ref in pre-verified class resolved to unexpected "
138                     "implementation");
139                 return NULL;
140             }
141         }
142 
143         LOGVV("##### +ResolveClass(%s): referrer=%s dex=%p ldr=%p ref=%d\n",
144             resClass->descriptor, referrer->descriptor, referrer->pDvmDex,
145             referrer->classLoader, classIdx);
146 
147         /*
148          * Add what we found to the list so we can skip the class search
149          * next time through.
150          *
151          * TODO: should we be doing this when fromUnverifiedConstant==true?
152          * (see comments at top of oo/Class.c)
153          */
154         dvmDexSetResolvedClass(pDvmDex, classIdx, resClass);
155     } else {
156         /* not found, exception should be raised */
157         LOGVV("Class not found: %s\n",
158             dexStringByTypeIdx(pDvmDex->pDexFile, classIdx));
159         assert(dvmCheckException(dvmThreadSelf()));
160     }
161 
162     return resClass;
163 }
164 
165 
166 /*
167  * Find the method corresponding to "methodRef".
168  *
169  * We use "referrer" to find the DexFile with the constant pool that
170  * "methodRef" is an index into.  We also use its class loader.  The method
171  * being resolved may very well be in a different DEX file.
172  *
173  * If this is a static method, we ensure that the method's class is
174  * initialized.
175  */
dvmResolveMethod(const ClassObject * referrer,u4 methodIdx,MethodType methodType)176 Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx,
177     MethodType methodType)
178 {
179     DvmDex* pDvmDex = referrer->pDvmDex;
180     ClassObject* resClass;
181     const DexMethodId* pMethodId;
182     Method* resMethod;
183 
184     assert(methodType != METHOD_INTERFACE);
185 
186     LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx,
187         referrer->descriptor);
188     pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
189 
190     resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
191     if (resClass == NULL) {
192         /* can't find the class that the method is a part of */
193         assert(dvmCheckException(dvmThreadSelf()));
194         return NULL;
195     }
196     if (dvmIsInterfaceClass(resClass)) {
197         /* method is part of an interface */
198         dvmThrowExceptionWithClassMessage(
199             "Ljava/lang/IncompatibleClassChangeError;",
200             resClass->descriptor);
201         return NULL;
202     }
203 
204     const char* name = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
205     DexProto proto;
206     dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
207 
208     /*
209      * We need to chase up the class hierarchy to find methods defined
210      * in super-classes.  (We only want to check the current class
211      * if we're looking for a constructor; since DIRECT calls are only
212      * for constructors and private methods, we don't want to walk up.)
213      */
214     if (methodType == METHOD_DIRECT) {
215         resMethod = dvmFindDirectMethod(resClass, name, &proto);
216     } else if (methodType == METHOD_STATIC) {
217         resMethod = dvmFindDirectMethodHier(resClass, name, &proto);
218     } else {
219         resMethod = dvmFindVirtualMethodHier(resClass, name, &proto);
220     }
221 
222     if (resMethod == NULL) {
223         dvmThrowException("Ljava/lang/NoSuchMethodError;", name);
224         return NULL;
225     }
226 
227     LOGVV("--- found method %d (%s.%s)\n",
228         methodIdx, resClass->descriptor, resMethod->name);
229 
230     /* see if this is a pure-abstract method */
231     if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
232         dvmThrowException("Ljava/lang/AbstractMethodError;", name);
233         return NULL;
234     }
235 
236     /*
237      * If we're the first to resolve this class, we need to initialize
238      * it now.  Only necessary for METHOD_STATIC.
239      */
240     if (methodType == METHOD_STATIC) {
241         if (!dvmIsClassInitialized(resMethod->clazz) &&
242             !dvmInitClass(resMethod->clazz))
243         {
244             assert(dvmCheckException(dvmThreadSelf()));
245             return NULL;
246         } else {
247             assert(!dvmCheckException(dvmThreadSelf()));
248         }
249     } else {
250         /*
251          * Edge case: if the <clinit> for a class creates an instance
252          * of itself, we will call <init> on a class that is still being
253          * initialized by us.
254          */
255         assert(dvmIsClassInitialized(resMethod->clazz) ||
256                dvmIsClassInitializing(resMethod->clazz));
257     }
258 
259     /*
260      * If the class has been initialized, add a pointer to our data structure
261      * so we don't have to jump through the hoops again.  If this is a
262      * static method and the defining class is still initializing (i.e. this
263      * thread is executing <clinit>), don't do the store, otherwise other
264      * threads could call the method without waiting for class init to finish.
265      */
266     if (methodType == METHOD_STATIC && !dvmIsClassInitialized(resMethod->clazz))
267     {
268         LOGVV("--- not caching resolved method %s.%s (class init=%d/%d)\n",
269             resMethod->clazz->descriptor, resMethod->name,
270             dvmIsClassInitializing(resMethod->clazz),
271             dvmIsClassInitialized(resMethod->clazz));
272     } else {
273         dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
274     }
275 
276     return resMethod;
277 }
278 
279 /*
280  * Resolve an interface method reference.
281  *
282  * Returns NULL with an exception raised on failure.
283  */
dvmResolveInterfaceMethod(const ClassObject * referrer,u4 methodIdx)284 Method* dvmResolveInterfaceMethod(const ClassObject* referrer, u4 methodIdx)
285 {
286     DvmDex* pDvmDex = referrer->pDvmDex;
287     ClassObject* resClass;
288     const DexMethodId* pMethodId;
289     Method* resMethod;
290     int i;
291 
292     LOGVV("--- resolving interface method %d (referrer=%s)\n",
293         methodIdx, referrer->descriptor);
294     pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
295 
296     resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
297     if (resClass == NULL) {
298         /* can't find the class that the method is a part of */
299         assert(dvmCheckException(dvmThreadSelf()));
300         return NULL;
301     }
302     if (!dvmIsInterfaceClass(resClass)) {
303         /* whoops */
304         dvmThrowExceptionWithClassMessage(
305             "Ljava/lang/IncompatibleClassChangeError;",
306             resClass->descriptor);
307         return NULL;
308     }
309 
310     /*
311      * This is the first time the method has been resolved.  Set it in our
312      * resolved-method structure.  It always resolves to the same thing,
313      * so looking it up and storing it doesn't create a race condition.
314      *
315      * If we scan into the interface's superclass -- which is always
316      * java/lang/Object -- we will catch things like:
317      *   interface I ...
318      *   I myobj = (something that implements I)
319      *   myobj.hashCode()
320      * However, the Method->methodIndex will be an offset into clazz->vtable,
321      * rather than an offset into clazz->iftable.  The invoke-interface
322      * code can test to see if the method returned is abstract or concrete,
323      * and use methodIndex accordingly.  I'm not doing this yet because
324      * (a) we waste time in an unusual case, and (b) we're probably going
325      * to fix it in the DEX optimizer.
326      *
327      * We do need to scan the superinterfaces, in case we're invoking a
328      * superinterface method on an interface reference.  The class in the
329      * DexTypeId is for the static type of the object, not the class in
330      * which the method is first defined.  We have the full, flattened
331      * list in "iftable".
332      */
333     const char* methodName =
334         dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
335 
336     DexProto proto;
337     dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
338 
339     LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n",
340         methodName, methodSig, resClass->descriptor);
341     resMethod = dvmFindVirtualMethod(resClass, methodName, &proto);
342     if (resMethod == NULL) {
343         LOGVV("+++ did not resolve immediately\n");
344         for (i = 0; i < resClass->iftableCount; i++) {
345             resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz,
346                             methodName, &proto);
347             if (resMethod != NULL)
348                 break;
349         }
350 
351         if (resMethod == NULL) {
352             dvmThrowException("Ljava/lang/NoSuchMethodError;", methodName);
353             return NULL;
354         }
355     } else {
356         LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name,
357             resMethod->clazz->descriptor, (u4) resMethod->methodIndex);
358     }
359 
360     LOGVV("--- found interface method %d (%s.%s)\n",
361         methodIdx, resClass->descriptor, resMethod->name);
362 
363     /* we're expecting this to be abstract */
364     assert(dvmIsAbstractMethod(resMethod));
365 
366     /* interface methods are always public; no need to check access */
367 
368     /*
369      * The interface class *may* be initialized.  According to VM spec
370      * v2 2.17.4, the interfaces a class refers to "need not" be initialized
371      * when the class is initialized.
372      *
373      * It isn't necessary for an interface class to be initialized before
374      * we resolve methods on that interface.
375      *
376      * We choose not to do the initialization now.
377      */
378     //assert(dvmIsClassInitialized(resMethod->clazz));
379 
380     /*
381      * Add a pointer to our data structure so we don't have to jump
382      * through the hoops again.
383      *
384      * As noted above, no need to worry about whether the interface that
385      * defines the method has been or is currently executing <clinit>.
386      */
387     dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
388 
389     return resMethod;
390 }
391 
392 /*
393  * Resolve an instance field reference.
394  *
395  * Returns NULL and throws an exception on error (no such field, illegal
396  * access).
397  */
dvmResolveInstField(const ClassObject * referrer,u4 ifieldIdx)398 InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx)
399 {
400     DvmDex* pDvmDex = referrer->pDvmDex;
401     ClassObject* resClass;
402     const DexFieldId* pFieldId;
403     InstField* resField;
404 
405     LOGVV("--- resolving field %u (referrer=%s cl=%p)\n",
406         ifieldIdx, referrer->descriptor, referrer->classLoader);
407 
408     pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx);
409 
410     /*
411      * Find the field's class.
412      */
413     resClass = dvmResolveClass(referrer, pFieldId->classIdx, false);
414     if (resClass == NULL) {
415         assert(dvmCheckException(dvmThreadSelf()));
416         return NULL;
417     }
418 
419     resField = dvmFindInstanceFieldHier(resClass,
420         dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
421         dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
422     if (resField == NULL) {
423         dvmThrowException("Ljava/lang/NoSuchFieldError;",
424             dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
425         return NULL;
426     }
427 
428     /*
429      * Class must be initialized by now (unless verifier is buggy).  We
430      * could still be in the process of initializing it if the field
431      * access is from a static initializer.
432      */
433     assert(dvmIsClassInitialized(resField->field.clazz) ||
434            dvmIsClassInitializing(resField->field.clazz));
435 
436     /*
437      * The class is initialized (or initializing), the field has been
438      * found.  Add a pointer to our data structure so we don't have to
439      * jump through the hoops again.
440      *
441      * Anything that uses the resolved table entry must have an instance
442      * of the class, so any class init activity has already happened (or
443      * been deliberately bypassed when <clinit> created an instance).
444      * So it's always okay to update the table.
445      */
446     dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*)resField);
447     LOGVV("    field %u is %s.%s\n",
448         ifieldIdx, resField->field.clazz->descriptor, resField->field.name);
449 
450     return resField;
451 }
452 
453 /*
454  * Resolve a static field reference.  The DexFile format doesn't distinguish
455  * between static and instance field references, so the "resolved" pointer
456  * in the Dex struct will have the wrong type.  We trivially cast it here.
457  *
458  * Causes the field's class to be initialized.
459  */
dvmResolveStaticField(const ClassObject * referrer,u4 sfieldIdx)460 StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx)
461 {
462     DvmDex* pDvmDex = referrer->pDvmDex;
463     ClassObject* resClass;
464     const DexFieldId* pFieldId;
465     StaticField* resField;
466 
467     pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx);
468 
469     /*
470      * Find the field's class.
471      */
472     resClass = dvmResolveClass(referrer, pFieldId->classIdx, false);
473     if (resClass == NULL) {
474         assert(dvmCheckException(dvmThreadSelf()));
475         return NULL;
476     }
477 
478     resField = dvmFindStaticFieldHier(resClass,
479                 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
480                 dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
481     if (resField == NULL) {
482         dvmThrowException("Ljava/lang/NoSuchFieldError;",
483             dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
484         return NULL;
485     }
486 
487     /*
488      * If we're the first to resolve the field in which this class resides,
489      * we need to do it now.  Note that, if the field was inherited from
490      * a superclass, it is not necessarily the same as "resClass".
491      */
492     if (!dvmIsClassInitialized(resField->field.clazz) &&
493         !dvmInitClass(resField->field.clazz))
494     {
495         assert(dvmCheckException(dvmThreadSelf()));
496         return NULL;
497     }
498 
499     /*
500      * If the class has been initialized, add a pointer to our data structure
501      * so we don't have to jump through the hoops again.  If it's still
502      * initializing (i.e. this thread is executing <clinit>), don't do
503      * the store, otherwise other threads could use the field without waiting
504      * for class init to finish.
505      */
506     if (dvmIsClassInitialized(resField->field.clazz)) {
507         dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField);
508     } else {
509         LOGVV("--- not caching resolved field %s.%s (class init=%d/%d)\n",
510             resField->field.clazz->descriptor, resField->field.name,
511             dvmIsClassInitializing(resField->field.clazz),
512             dvmIsClassInitialized(resField->field.clazz));
513     }
514 
515     return resField;
516 }
517 
518 
519 /*
520  * Resolve a string reference.
521  *
522  * Finding the string is easy.  We need to return a reference to a
523  * java/lang/String object, not a bunch of characters, which means the
524  * first time we get here we need to create an interned string.
525  */
dvmResolveString(const ClassObject * referrer,u4 stringIdx)526 StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx)
527 {
528     DvmDex* pDvmDex = referrer->pDvmDex;
529     StringObject* strObj;
530     StringObject* internStrObj;
531     const char* utf8;
532     u4 utf16Size;
533 
534     LOGVV("+++ resolving string, referrer is %s\n", referrer->descriptor);
535 
536     /*
537      * Create a UTF-16 version so we can trivially compare it to what's
538      * already interned.
539      */
540     utf8 = dexStringAndSizeById(pDvmDex->pDexFile, stringIdx, &utf16Size);
541     strObj = dvmCreateStringFromCstrAndLength(utf8, utf16Size);
542     if (strObj == NULL) {
543         /* ran out of space in GC heap? */
544         assert(dvmCheckException(dvmThreadSelf()));
545         goto bail;
546     }
547 
548     /*
549      * Add it to the intern list.  The return value is the one in the
550      * intern list, which (due to race conditions) may or may not be
551      * the one we just created.  The intern list is synchronized, so
552      * there will be only one "live" version.
553      *
554      * By requesting an immortal interned string, we guarantee that
555      * the returned object will never be collected by the GC.
556      *
557      * A NULL return here indicates some sort of hashing failure.
558      */
559     internStrObj = dvmLookupImmortalInternedString(strObj);
560     dvmReleaseTrackedAlloc((Object*) strObj, NULL);
561     strObj = internStrObj;
562     if (strObj == NULL) {
563         assert(dvmCheckException(dvmThreadSelf()));
564         goto bail;
565     }
566 
567     /* save a reference so we can go straight to the object next time */
568     dvmDexSetResolvedString(pDvmDex, stringIdx, strObj);
569 
570 bail:
571     return strObj;
572 }
573 
574 /*
575  * For debugging: return a string representing the methodType.
576  */
dvmMethodTypeStr(MethodType methodType)577 const char* dvmMethodTypeStr(MethodType methodType)
578 {
579     switch (methodType) {
580     case METHOD_DIRECT:         return "direct";
581     case METHOD_STATIC:         return "static";
582     case METHOD_VIRTUAL:        return "virtual";
583     case METHOD_INTERFACE:      return "interface";
584     case METHOD_UNKNOWN:        return "UNKNOWN";
585     }
586     assert(false);
587     return "BOGUS";
588 }
589