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