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)",
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 ALOGW("Class resolved by unexpected DEX:"
129 " %s(%p):%p ref [%s] %s(%p):%p",
130 referrer->descriptor, referrer->classLoader,
131 referrer->pDvmDex,
132 resClass->descriptor, resClassCheck->descriptor,
133 resClassCheck->classLoader, resClassCheck->pDvmDex);
134 ALOGW("(%s had used a different %s during pre-verification)",
135 referrer->descriptor, resClass->descriptor);
136 dvmThrowIllegalAccessError(
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",
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",
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)", 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 dvmThrowIncompatibleClassChangeErrorWithClassMessage(
199 resClass->descriptor);
200 return NULL;
201 }
202
203 const char* name = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
204 DexProto proto;
205 dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
206
207 /*
208 * We need to chase up the class hierarchy to find methods defined
209 * in super-classes. (We only want to check the current class
210 * if we're looking for a constructor; since DIRECT calls are only
211 * for constructors and private methods, we don't want to walk up.)
212 */
213 if (methodType == METHOD_DIRECT) {
214 resMethod = dvmFindDirectMethod(resClass, name, &proto);
215 } else if (methodType == METHOD_STATIC) {
216 resMethod = dvmFindDirectMethodHier(resClass, name, &proto);
217 } else {
218 resMethod = dvmFindVirtualMethodHier(resClass, name, &proto);
219 }
220
221 if (resMethod == NULL) {
222 dvmThrowNoSuchMethodError(name);
223 return NULL;
224 }
225
226 LOGVV("--- found method %d (%s.%s)",
227 methodIdx, resClass->descriptor, resMethod->name);
228
229 /* see if this is a pure-abstract method */
230 if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
231 dvmThrowAbstractMethodError(name);
232 return NULL;
233 }
234
235 /*
236 * If we're the first to resolve this class, we need to initialize
237 * it now. Only necessary for METHOD_STATIC.
238 */
239 if (methodType == METHOD_STATIC) {
240 if (!dvmIsClassInitialized(resMethod->clazz) &&
241 !dvmInitClass(resMethod->clazz))
242 {
243 assert(dvmCheckException(dvmThreadSelf()));
244 return NULL;
245 } else {
246 assert(!dvmCheckException(dvmThreadSelf()));
247 }
248 } else {
249 /*
250 * Edge case: if the <clinit> for a class creates an instance
251 * of itself, we will call <init> on a class that is still being
252 * initialized by us.
253 */
254 assert(dvmIsClassInitialized(resMethod->clazz) ||
255 dvmIsClassInitializing(resMethod->clazz));
256 }
257
258 /*
259 * If the class has been initialized, add a pointer to our data structure
260 * so we don't have to jump through the hoops again. If this is a
261 * static method and the defining class is still initializing (i.e. this
262 * thread is executing <clinit>), don't do the store, otherwise other
263 * threads could call the method without waiting for class init to finish.
264 */
265 if (methodType == METHOD_STATIC && !dvmIsClassInitialized(resMethod->clazz))
266 {
267 LOGVV("--- not caching resolved method %s.%s (class init=%d/%d)",
268 resMethod->clazz->descriptor, resMethod->name,
269 dvmIsClassInitializing(resMethod->clazz),
270 dvmIsClassInitialized(resMethod->clazz));
271 } else {
272 dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
273 }
274
275 return resMethod;
276 }
277
278 /*
279 * Resolve an interface method reference.
280 *
281 * Returns NULL with an exception raised on failure.
282 */
dvmResolveInterfaceMethod(const ClassObject * referrer,u4 methodIdx)283 Method* dvmResolveInterfaceMethod(const ClassObject* referrer, u4 methodIdx)
284 {
285 DvmDex* pDvmDex = referrer->pDvmDex;
286 ClassObject* resClass;
287 const DexMethodId* pMethodId;
288 Method* resMethod;
289
290 LOGVV("--- resolving interface method %d (referrer=%s)",
291 methodIdx, referrer->descriptor);
292 pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
293
294 resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
295 if (resClass == NULL) {
296 /* can't find the class that the method is a part of */
297 assert(dvmCheckException(dvmThreadSelf()));
298 return NULL;
299 }
300 if (!dvmIsInterfaceClass(resClass)) {
301 /* whoops */
302 dvmThrowIncompatibleClassChangeErrorWithClassMessage(
303 resClass->descriptor);
304 return NULL;
305 }
306
307 /*
308 * This is the first time the method has been resolved. Set it in our
309 * resolved-method structure. It always resolves to the same thing,
310 * so looking it up and storing it doesn't create a race condition.
311 *
312 * If we scan into the interface's superclass -- which is always
313 * java/lang/Object -- we will catch things like:
314 * interface I ...
315 * I myobj = (something that implements I)
316 * myobj.hashCode()
317 * However, the Method->methodIndex will be an offset into clazz->vtable,
318 * rather than an offset into clazz->iftable. The invoke-interface
319 * code can test to see if the method returned is abstract or concrete,
320 * and use methodIndex accordingly. I'm not doing this yet because
321 * (a) we waste time in an unusual case, and (b) we're probably going
322 * to fix it in the DEX optimizer.
323 *
324 * We do need to scan the superinterfaces, in case we're invoking a
325 * superinterface method on an interface reference. The class in the
326 * DexTypeId is for the static type of the object, not the class in
327 * which the method is first defined. We have the full, flattened
328 * list in "iftable".
329 */
330 const char* methodName =
331 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
332
333 DexProto proto;
334 dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
335
336 LOGVV("+++ looking for '%s' '%s' in resClass='%s'",
337 methodName, methodSig, resClass->descriptor);
338 resMethod = dvmFindInterfaceMethodHier(resClass, methodName, &proto);
339 if (resMethod == NULL) {
340 dvmThrowNoSuchMethodError(methodName);
341 return NULL;
342 }
343
344 LOGVV("--- found interface method %d (%s.%s)",
345 methodIdx, resClass->descriptor, resMethod->name);
346
347 /* we're expecting this to be abstract */
348 assert(dvmIsAbstractMethod(resMethod));
349
350 /* interface methods are always public; no need to check access */
351
352 /*
353 * The interface class *may* be initialized. According to VM spec
354 * v2 2.17.4, the interfaces a class refers to "need not" be initialized
355 * when the class is initialized.
356 *
357 * It isn't necessary for an interface class to be initialized before
358 * we resolve methods on that interface.
359 *
360 * We choose not to do the initialization now.
361 */
362 //assert(dvmIsClassInitialized(resMethod->clazz));
363
364 /*
365 * Add a pointer to our data structure so we don't have to jump
366 * through the hoops again.
367 *
368 * As noted above, no need to worry about whether the interface that
369 * defines the method has been or is currently executing <clinit>.
370 */
371 dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
372
373 return resMethod;
374 }
375
376 /*
377 * Resolve an instance field reference.
378 *
379 * Returns NULL and throws an exception on error (no such field, illegal
380 * access).
381 */
dvmResolveInstField(const ClassObject * referrer,u4 ifieldIdx)382 InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx)
383 {
384 DvmDex* pDvmDex = referrer->pDvmDex;
385 ClassObject* resClass;
386 const DexFieldId* pFieldId;
387 InstField* resField;
388
389 LOGVV("--- resolving field %u (referrer=%s cl=%p)",
390 ifieldIdx, referrer->descriptor, referrer->classLoader);
391
392 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx);
393
394 /*
395 * Find the field's class.
396 */
397 resClass = dvmResolveClass(referrer, pFieldId->classIdx, false);
398 if (resClass == NULL) {
399 assert(dvmCheckException(dvmThreadSelf()));
400 return NULL;
401 }
402
403 resField = dvmFindInstanceFieldHier(resClass,
404 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
405 dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
406 if (resField == NULL) {
407 dvmThrowNoSuchFieldError(
408 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
409 return NULL;
410 }
411
412 /*
413 * Class must be initialized by now (unless verifier is buggy). We
414 * could still be in the process of initializing it if the field
415 * access is from a static initializer.
416 */
417 assert(dvmIsClassInitialized(resField->clazz) ||
418 dvmIsClassInitializing(resField->clazz));
419
420 /*
421 * The class is initialized (or initializing), the field has been
422 * found. Add a pointer to our data structure so we don't have to
423 * jump through the hoops again.
424 *
425 * Anything that uses the resolved table entry must have an instance
426 * of the class, so any class init activity has already happened (or
427 * been deliberately bypassed when <clinit> created an instance).
428 * So it's always okay to update the table.
429 */
430 dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*)resField);
431 LOGVV(" field %u is %s.%s",
432 ifieldIdx, resField->clazz->descriptor, resField->name);
433
434 return resField;
435 }
436
437 /*
438 * Resolve a static field reference. The DexFile format doesn't distinguish
439 * between static and instance field references, so the "resolved" pointer
440 * in the Dex struct will have the wrong type. We trivially cast it here.
441 *
442 * Causes the field's class to be initialized.
443 */
dvmResolveStaticField(const ClassObject * referrer,u4 sfieldIdx)444 StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx)
445 {
446 DvmDex* pDvmDex = referrer->pDvmDex;
447 ClassObject* resClass;
448 const DexFieldId* pFieldId;
449 StaticField* resField;
450
451 pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx);
452
453 /*
454 * Find the field's class.
455 */
456 resClass = dvmResolveClass(referrer, pFieldId->classIdx, false);
457 if (resClass == NULL) {
458 assert(dvmCheckException(dvmThreadSelf()));
459 return NULL;
460 }
461
462 resField = dvmFindStaticFieldHier(resClass,
463 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
464 dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
465 if (resField == NULL) {
466 dvmThrowNoSuchFieldError(
467 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
468 return NULL;
469 }
470
471 /*
472 * If we're the first to resolve the field in which this class resides,
473 * we need to do it now. Note that, if the field was inherited from
474 * a superclass, it is not necessarily the same as "resClass".
475 */
476 if (!dvmIsClassInitialized(resField->clazz) &&
477 !dvmInitClass(resField->clazz))
478 {
479 assert(dvmCheckException(dvmThreadSelf()));
480 return NULL;
481 }
482
483 /*
484 * If the class has been initialized, add a pointer to our data structure
485 * so we don't have to jump through the hoops again. If it's still
486 * initializing (i.e. this thread is executing <clinit>), don't do
487 * the store, otherwise other threads could use the field without waiting
488 * for class init to finish.
489 */
490 if (dvmIsClassInitialized(resField->clazz)) {
491 dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField);
492 } else {
493 LOGVV("--- not caching resolved field %s.%s (class init=%d/%d)",
494 resField->clazz->descriptor, resField->name,
495 dvmIsClassInitializing(resField->clazz),
496 dvmIsClassInitialized(resField->clazz));
497 }
498
499 return resField;
500 }
501
502
503 /*
504 * Resolve a string reference.
505 *
506 * Finding the string is easy. We need to return a reference to a
507 * java/lang/String object, not a bunch of characters, which means the
508 * first time we get here we need to create an interned string.
509 */
dvmResolveString(const ClassObject * referrer,u4 stringIdx)510 StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx)
511 {
512 DvmDex* pDvmDex = referrer->pDvmDex;
513 StringObject* strObj;
514 StringObject* internStrObj;
515 const char* utf8;
516 u4 utf16Size;
517
518 LOGVV("+++ resolving string, referrer is %s", referrer->descriptor);
519
520 /*
521 * Create a UTF-16 version so we can trivially compare it to what's
522 * already interned.
523 */
524 utf8 = dexStringAndSizeById(pDvmDex->pDexFile, stringIdx, &utf16Size);
525 strObj = dvmCreateStringFromCstrAndLength(utf8, utf16Size);
526 if (strObj == NULL) {
527 /* ran out of space in GC heap? */
528 assert(dvmCheckException(dvmThreadSelf()));
529 goto bail;
530 }
531
532 /*
533 * Add it to the intern list. The return value is the one in the
534 * intern list, which (due to race conditions) may or may not be
535 * the one we just created. The intern list is synchronized, so
536 * there will be only one "live" version.
537 *
538 * By requesting an immortal interned string, we guarantee that
539 * the returned object will never be collected by the GC.
540 *
541 * A NULL return here indicates some sort of hashing failure.
542 */
543 internStrObj = dvmLookupImmortalInternedString(strObj);
544 dvmReleaseTrackedAlloc((Object*) strObj, NULL);
545 strObj = internStrObj;
546 if (strObj == NULL) {
547 assert(dvmCheckException(dvmThreadSelf()));
548 goto bail;
549 }
550
551 /* save a reference so we can go straight to the object next time */
552 dvmDexSetResolvedString(pDvmDex, stringIdx, strObj);
553
554 bail:
555 return strObj;
556 }
557
558 /*
559 * For debugging: return a string representing the methodType.
560 */
dvmMethodTypeStr(MethodType methodType)561 const char* dvmMethodTypeStr(MethodType methodType)
562 {
563 switch (methodType) {
564 case METHOD_DIRECT: return "direct";
565 case METHOD_STATIC: return "static";
566 case METHOD_VIRTUAL: return "virtual";
567 case METHOD_INTERFACE: return "interface";
568 case METHOD_UNKNOWN: return "UNKNOWN";
569 }
570 assert(false);
571 return "BOGUS";
572 }
573