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 */
dvmResolveClass(const ClassObject * referrer,u4 classIdx,bool fromUnverifiedConstant)63 ClassObject* 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 */
dvmResolveMethod(const ClassObject * referrer,u4 methodIdx,MethodType methodType)176 Method* 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 */
dvmResolveInterfaceMethod(const ClassObject * referrer,u4 methodIdx)284 Method* 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 */
dvmResolveInstField(const ClassObject * referrer,u4 ifieldIdx)398 InstField* 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 */
dvmResolveStaticField(const ClassObject * referrer,u4 sfieldIdx)460 StaticField* 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 */
dvmResolveString(const ClassObject * referrer,u4 stringIdx)526 StringObject* 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
570 bail:
571 return strObj;
572 }
573
574 /*
575 * For debugging: return a string representing the methodType.
576 */
dvmMethodTypeStr(MethodType methodType)577 const 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