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