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