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