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 */
63ClassObject* 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 */
176Method* 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 */
284Method* 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 */
398InstField* 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 */
460StaticField* 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 */
526StringObject* 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
570bail:
571    return strObj;
572}
573
574/*
575 * For debugging: return a string representing the methodType.
576 */
577const 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