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 * Annotations.
18 *
19 * We're not expecting to make much use of runtime annotations, so speed vs.
20 * space choices are weighted heavily toward small size.
21 *
22 * It would have been nice to treat "system" annotations in the same way
23 * we do "real" annotations, but that doesn't work. The chief difficulty
24 * is that some of them have member types that are not legal in annotations,
25 * such as Method and Annotation. Another source of pain comes from the
26 * AnnotationDefault annotation, which by virtue of being an annotation
27 * could itself have default values, requiring some additional checks to
28 * prevent recursion.
29 *
30 * It's simpler, and more efficient, to handle the system annotations
31 * entirely inside the VM. There are empty classes defined for the system
32 * annotation types, but their only purpose is to allow the system
33 * annotations to share name space with standard annotations.
34 */
35 #include "Dalvik.h"
36
37 // fwd
38 static Object* processEncodedAnnotation(const ClassObject* clazz,\
39 const u1** pPtr);
40 static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr);
41
42 /*
43 * System annotation descriptors.
44 */
45 static const char* kDescrAnnotationDefault
46 = "Ldalvik/annotation/AnnotationDefault;";
47 static const char* kDescrEnclosingClass
48 = "Ldalvik/annotation/EnclosingClass;";
49 static const char* kDescrEnclosingMethod
50 = "Ldalvik/annotation/EnclosingMethod;";
51 static const char* kDescrInnerClass = "Ldalvik/annotation/InnerClass;";
52 static const char* kDescrMemberClasses
53 = "Ldalvik/annotation/MemberClasses;";
54 static const char* kDescrSignature = "Ldalvik/annotation/Signature;";
55 static const char* kDescrThrows = "Ldalvik/annotation/Throws;";
56
57
58 /*
59 * Perform Annotation setup.
60 */
dvmReflectAnnotationStartup(void)61 bool dvmReflectAnnotationStartup(void)
62 {
63 Method* meth;
64
65 /*
66 * Find some standard Annotation classes.
67 */
68 gDvm.classJavaLangAnnotationAnnotationArray =
69 dvmFindArrayClass("[Ljava/lang/annotation/Annotation;", NULL);
70 gDvm.classJavaLangAnnotationAnnotationArrayArray =
71 dvmFindArrayClass("[[Ljava/lang/annotation/Annotation;", NULL);
72 if (gDvm.classJavaLangAnnotationAnnotationArray == NULL ||
73 gDvm.classJavaLangAnnotationAnnotationArrayArray == NULL)
74 {
75 LOGE("Could not find Annotation-array classes\n");
76 return false;
77 }
78
79 /*
80 * VM-specific annotation classes.
81 */
82 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory =
83 dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationFactory;");
84 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember =
85 dvmFindSystemClassNoInit("Lorg/apache/harmony/lang/annotation/AnnotationMember;");
86 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray =
87 dvmFindArrayClass("[Lorg/apache/harmony/lang/annotation/AnnotationMember;", NULL);
88 if (gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory == NULL ||
89 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember == NULL ||
90 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray == NULL)
91 {
92 LOGE("Could not find android.lang annotation classes\n");
93 return false;
94 }
95
96 meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory,
97 "createAnnotation",
98 "(Ljava/lang/Class;[Lorg/apache/harmony/lang/annotation/AnnotationMember;)Ljava/lang/annotation/Annotation;");
99 if (meth == NULL) {
100 LOGE("Unable to find createAnnotation() in android AnnotationFactory\n");
101 return false;
102 }
103 gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation = meth;
104
105 meth = dvmFindDirectMethodByDescriptor(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
106 "<init>",
107 "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/reflect/Method;)V");
108 if (meth == NULL) {
109 LOGE("Unable to find 4-arg constructor in android AnnotationMember\n");
110 return false;
111 }
112
113 gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init = meth;
114
115 return true;
116 }
117
118 /*
119 * Read an unsigned LEB128 value from a buffer. Advances "pBuf".
120 */
readUleb128(const u1 ** pBuf)121 static u4 readUleb128(const u1** pBuf)
122 {
123 u4 result = 0;
124 int shift = 0;
125 const u1* buf = *pBuf;
126 u1 val;
127
128 do {
129 /*
130 * Worst-case on bad data is we read too much data and return a bogus
131 * result. Safe to assume that we will encounter a byte with its
132 * high bit clear before the end of the mapped file.
133 */
134 assert(shift < 32);
135
136 val = *buf++;
137 result |= (val & 0x7f) << shift;
138 shift += 7;
139 } while ((val & 0x80) != 0);
140
141 *pBuf = buf;
142 return result;
143 }
144
145 /*
146 * Get the annotations directory item.
147 */
getAnnoDirectory(DexFile * pDexFile,const ClassObject * clazz)148 static const DexAnnotationsDirectoryItem* getAnnoDirectory(DexFile* pDexFile,
149 const ClassObject* clazz)
150 {
151 const DexClassDef* pClassDef;
152
153 /*
154 * Find the class def in the DEX file. For better performance we should
155 * stash this in the ClassObject.
156 */
157 pClassDef = dexFindClass(pDexFile, clazz->descriptor);
158 assert(pClassDef != NULL);
159 return dexGetAnnotationsDirectoryItem(pDexFile, pClassDef);
160 }
161
162 /*
163 * Return a zero-length array of Annotation objects.
164 *
165 * TODO: this currently allocates a new array each time, but I think we
166 * can get away with returning a canonical copy.
167 *
168 * Caller must call dvmReleaseTrackedAlloc().
169 */
emptyAnnoArray(void)170 static ArrayObject* emptyAnnoArray(void)
171 {
172 return dvmAllocArrayByClass(
173 gDvm.classJavaLangAnnotationAnnotationArray, 0, ALLOC_DEFAULT);
174 }
175
176 /*
177 * Return an array of empty arrays of Annotation objects.
178 *
179 * Caller must call dvmReleaseTrackedAlloc().
180 */
emptyAnnoArrayArray(int numElements)181 static ArrayObject* emptyAnnoArrayArray(int numElements)
182 {
183 Thread* self = dvmThreadSelf();
184 ArrayObject* arr;
185 int i;
186
187 arr = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArrayArray,
188 numElements, ALLOC_DEFAULT);
189 if (arr != NULL) {
190 ArrayObject** elems = (ArrayObject**) arr->contents;
191 for (i = 0; i < numElements; i++) {
192 elems[i] = emptyAnnoArray();
193 dvmReleaseTrackedAlloc((Object*)elems[i], self);
194 }
195 }
196
197 return arr;
198 }
199
200 /*
201 * Read a signed integer. "zwidth" is the zero-based byte count.
202 */
readSignedInt(const u1 * ptr,int zwidth)203 static s4 readSignedInt(const u1* ptr, int zwidth)
204 {
205 s4 val = 0;
206 int i;
207
208 for (i = zwidth; i >= 0; --i)
209 val = ((u4)val >> 8) | (((s4)*ptr++) << 24);
210 val >>= (3 - zwidth) * 8;
211
212 return val;
213 }
214
215 /*
216 * Read an unsigned integer. "zwidth" is the zero-based byte count,
217 * "fillOnRight" indicates which side we want to zero-fill from.
218 */
readUnsignedInt(const u1 * ptr,int zwidth,bool fillOnRight)219 static u4 readUnsignedInt(const u1* ptr, int zwidth, bool fillOnRight)
220 {
221 u4 val = 0;
222 int i;
223
224 if (!fillOnRight) {
225 for (i = zwidth; i >= 0; --i)
226 val = (val >> 8) | (((u4)*ptr++) << 24);
227 val >>= (3 - zwidth) * 8;
228 } else {
229 for (i = zwidth; i >= 0; --i)
230 val = (val >> 8) | (((u4)*ptr++) << 24);
231 }
232 return val;
233 }
234
235 /*
236 * Read a signed long. "zwidth" is the zero-based byte count.
237 */
readSignedLong(const u1 * ptr,int zwidth)238 static s8 readSignedLong(const u1* ptr, int zwidth)
239 {
240 s8 val = 0;
241 int i;
242
243 for (i = zwidth; i >= 0; --i)
244 val = ((u8)val >> 8) | (((s8)*ptr++) << 56);
245 val >>= (7 - zwidth) * 8;
246
247 return val;
248 }
249
250 /*
251 * Read an unsigned long. "zwidth" is the zero-based byte count,
252 * "fillOnRight" indicates which side we want to zero-fill from.
253 */
readUnsignedLong(const u1 * ptr,int zwidth,bool fillOnRight)254 static u8 readUnsignedLong(const u1* ptr, int zwidth, bool fillOnRight)
255 {
256 u8 val = 0;
257 int i;
258
259 if (!fillOnRight) {
260 for (i = zwidth; i >= 0; --i)
261 val = (val >> 8) | (((u8)*ptr++) << 56);
262 val >>= (7 - zwidth) * 8;
263 } else {
264 for (i = zwidth; i >= 0; --i)
265 val = (val >> 8) | (((u8)*ptr++) << 56);
266 }
267 return val;
268 }
269
270
271 /*
272 * ===========================================================================
273 * Element extraction
274 * ===========================================================================
275 */
276
277 /*
278 * An annotation in "clazz" refers to a method by index. This just gives
279 * us the name of the class and the name and signature of the method. We
280 * need to find the method's class, and then find the method within that
281 * class. If the method has been resolved before, we can just use the
282 * results of the previous lookup.
283 *
284 * Normally we do this as part of method invocation in the interpreter, which
285 * provides us with a bit of context: is it virtual or direct, do we need
286 * to initialize the class because it's a static method, etc. We don't have
287 * that information here, so we have to do a bit of searching.
288 *
289 * Returns NULL if the method was not found (exception may be pending).
290 */
resolveAmbiguousMethod(const ClassObject * referrer,u4 methodIdx)291 static Method* resolveAmbiguousMethod(const ClassObject* referrer, u4 methodIdx)
292 {
293 DexFile* pDexFile;
294 ClassObject* resClass;
295 Method* resMethod;
296 const DexMethodId* pMethodId;
297 const char* name;
298 const char* signature;
299
300 /* if we've already resolved this method, return it */
301 resMethod = dvmDexGetResolvedMethod(referrer->pDvmDex, methodIdx);
302 if (resMethod != NULL)
303 return resMethod;
304
305 pDexFile = referrer->pDvmDex->pDexFile;
306 pMethodId = dexGetMethodId(pDexFile, methodIdx);
307 resClass = dvmResolveClass(referrer, pMethodId->classIdx, true);
308 if (resClass == NULL) {
309 /* note exception will be pending */
310 LOGD("resolveAmbiguousMethod: unable to find class %d\n", methodIdx);
311 return NULL;
312 }
313 if (dvmIsInterfaceClass(resClass)) {
314 /* method is part of an interface -- not expecting that */
315 LOGD("resolveAmbiguousMethod: method in interface?\n");
316 return NULL;
317 }
318
319 // TODO - consider a method access flag that indicates direct vs. virtual
320 name = dexStringById(pDexFile, pMethodId->nameIdx);
321
322 DexProto proto;
323 dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
324
325 if (name[0] == '<') {
326 /*
327 * Constructor or class initializer. Only need to examine the
328 * "direct" list, and don't need to look up the class hierarchy.
329 */
330 resMethod = dvmFindDirectMethod(resClass, name, &proto);
331 } else {
332 /*
333 * Try both lists, and scan up the tree.
334 */
335 resMethod = dvmFindVirtualMethodHier(resClass, name, &proto);
336 if (resMethod == NULL)
337 resMethod = dvmFindDirectMethodHier(resClass, name, &proto);
338 }
339
340 return resMethod;
341 }
342
343 /*
344 * constants for processAnnotationValue indicating what style of
345 * result is wanted
346 */
347 typedef enum {
348 kAllObjects, /* return everything as an object */
349 kAllRaw, /* return everything as a raw value or index */
350 kPrimitivesOrObjects /* return primitives as-is but the rest as objects */
351 } AnnotationResultStyle;
352
353 /*
354 * Recursively process an annotation value.
355 *
356 * "clazz" is the class on which the annotations are defined. It may be
357 * NULL when "resultStyle" is "kAllRaw".
358 *
359 * If "resultStyle" is "kAllObjects", the result will always be an Object of an
360 * appropriate type (in pValue->value.l). For primitive types, the usual
361 * wrapper objects will be created.
362 *
363 * If "resultStyle" is "kAllRaw", numeric constants are stored directly into
364 * "pValue", and indexed values like String and Method are returned as
365 * indexes. Complex values like annotations and arrays are not handled.
366 *
367 * If "resultStyle" is "kPrimitivesOrObjects", numeric constants are stored
368 * directly into "pValue", and everything else is constructed as an Object
369 * of appropriate type (in pValue->value.l).
370 *
371 * The caller must call dvmReleaseTrackedAlloc on returned objects, when
372 * using "kAllObjects" or "kPrimitivesOrObjects".
373 *
374 * Returns "true" on success, "false" if the value could not be processed
375 * or an object could not be allocated. On allocation failure an exception
376 * will be raised.
377 */
processAnnotationValue(const ClassObject * clazz,const u1 ** pPtr,AnnotationValue * pValue,AnnotationResultStyle resultStyle)378 static bool processAnnotationValue(const ClassObject* clazz,
379 const u1** pPtr, AnnotationValue* pValue,
380 AnnotationResultStyle resultStyle)
381 {
382 Thread* self = dvmThreadSelf();
383 Object* elemObj = NULL;
384 bool setObject = false;
385 const u1* ptr = *pPtr;
386 u1 valueType, valueArg;
387 int width;
388 u4 idx;
389
390 valueType = *ptr++;
391 valueArg = valueType >> kDexAnnotationValueArgShift;
392 width = valueArg + 1; /* assume, correct later */
393
394 LOGV("----- type is 0x%02x %d, ptr=%p [0x%06x]\n",
395 valueType & kDexAnnotationValueTypeMask, valueArg, ptr-1,
396 (ptr-1) - (u1*)clazz->pDvmDex->pDexFile->baseAddr);
397
398 pValue->type = valueType & kDexAnnotationValueTypeMask;
399
400 switch (valueType & kDexAnnotationValueTypeMask) {
401 case kDexAnnotationByte:
402 pValue->value.i = (s1) readSignedInt(ptr, valueArg);
403 if (resultStyle == kAllObjects) {
404 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
405 dvmFindPrimitiveClass('B'));
406 setObject = true;
407 }
408 break;
409 case kDexAnnotationShort:
410 pValue->value.i = (s2) readSignedInt(ptr, valueArg);
411 if (resultStyle == kAllObjects) {
412 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
413 dvmFindPrimitiveClass('S'));
414 setObject = true;
415 }
416 break;
417 case kDexAnnotationChar:
418 pValue->value.i = (u2) readUnsignedInt(ptr, valueArg, false);
419 if (resultStyle == kAllObjects) {
420 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
421 dvmFindPrimitiveClass('C'));
422 setObject = true;
423 }
424 break;
425 case kDexAnnotationInt:
426 pValue->value.i = readSignedInt(ptr, valueArg);
427 if (resultStyle == kAllObjects) {
428 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
429 dvmFindPrimitiveClass('I'));
430 setObject = true;
431 }
432 break;
433 case kDexAnnotationLong:
434 pValue->value.j = readSignedLong(ptr, valueArg);
435 if (resultStyle == kAllObjects) {
436 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
437 dvmFindPrimitiveClass('J'));
438 setObject = true;
439 }
440 break;
441 case kDexAnnotationFloat:
442 pValue->value.i = readUnsignedInt(ptr, valueArg, true);
443 if (resultStyle == kAllObjects) {
444 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
445 dvmFindPrimitiveClass('F'));
446 setObject = true;
447 }
448 break;
449 case kDexAnnotationDouble:
450 pValue->value.j = readUnsignedLong(ptr, valueArg, true);
451 if (resultStyle == kAllObjects) {
452 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
453 dvmFindPrimitiveClass('D'));
454 setObject = true;
455 }
456 break;
457 case kDexAnnotationBoolean:
458 pValue->value.i = (valueArg != 0);
459 if (resultStyle == kAllObjects) {
460 elemObj = (Object*) dvmWrapPrimitive(pValue->value,
461 dvmFindPrimitiveClass('Z'));
462 setObject = true;
463 }
464 width = 0;
465 break;
466
467 case kDexAnnotationString:
468 idx = readUnsignedInt(ptr, valueArg, false);
469 if (resultStyle == kAllRaw) {
470 pValue->value.i = idx;
471 } else {
472 elemObj = (Object*) dvmResolveString(clazz, idx);
473 setObject = true;
474 if (elemObj == NULL)
475 return false;
476 dvmAddTrackedAlloc(elemObj, self); // balance the Release
477 }
478 break;
479 case kDexAnnotationType:
480 idx = readUnsignedInt(ptr, valueArg, false);
481 if (resultStyle == kAllRaw) {
482 pValue->value.i = idx;
483 } else {
484 elemObj = (Object*) dvmResolveClass(clazz, idx, true);
485 setObject = true;
486 if (elemObj == NULL) {
487 /* we're expected to throw a TypeNotPresentException here */
488 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
489 const char* desc = dexStringByTypeIdx(pDexFile, idx);
490 dvmClearException(self);
491 dvmThrowExceptionWithClassMessage(
492 "Ljava/lang/TypeNotPresentException;", desc);
493 return false;
494 } else {
495 dvmAddTrackedAlloc(elemObj, self); // balance the Release
496 }
497 }
498 break;
499 case kDexAnnotationMethod:
500 idx = readUnsignedInt(ptr, valueArg, false);
501 if (resultStyle == kAllRaw) {
502 pValue->value.i = idx;
503 } else {
504 Method* meth = resolveAmbiguousMethod(clazz, idx);
505 if (meth == NULL)
506 return false;
507 elemObj = dvmCreateReflectObjForMethod(clazz, meth);
508 setObject = true;
509 if (elemObj == NULL)
510 return false;
511 }
512 break;
513 case kDexAnnotationField:
514 idx = readUnsignedInt(ptr, valueArg, false);
515 assert(false); // TODO
516 break;
517 case kDexAnnotationEnum:
518 /* enum values are the contents of a static field */
519 idx = readUnsignedInt(ptr, valueArg, false);
520 if (resultStyle == kAllRaw) {
521 pValue->value.i = idx;
522 } else {
523 StaticField* sfield;
524
525 sfield = dvmResolveStaticField(clazz, idx);
526 if (sfield == NULL) {
527 return false;
528 } else {
529 assert(sfield->field.clazz->descriptor[0] == 'L');
530 elemObj = sfield->value.l;
531 setObject = true;
532 dvmAddTrackedAlloc(elemObj, self); // balance the Release
533 }
534 }
535 break;
536 case kDexAnnotationArray:
537 /*
538 * encoded_array format, which is a size followed by a stream
539 * of annotation_value.
540 *
541 * We create an array of Object, populate it, and return it.
542 */
543 if (resultStyle == kAllRaw) {
544 return false;
545 } else {
546 ArrayObject* newArray;
547 Object** pObj;
548 u4 size;
549
550 size = readUleb128(&ptr);
551 LOGVV("--- annotation array, size is %u at %p\n", size, ptr);
552 newArray = dvmAllocArrayByClass(gDvm.classJavaLangObjectArray,
553 size, ALLOC_DEFAULT);
554 if (newArray == NULL) {
555 LOGE("annotation element array alloc failed (%d)\n", size);
556 return false;
557 }
558 pObj = (Object**)newArray->contents;
559
560 AnnotationValue avalue;
561 while (size--) {
562 if (!processAnnotationValue(clazz, &ptr, &avalue,
563 kAllObjects)) {
564 dvmReleaseTrackedAlloc((Object*)newArray, self);
565 return false;
566 }
567 Object* obj = avalue.value.l;
568 dvmReleaseTrackedAlloc(obj, self);
569 *pObj++ = obj;
570 }
571
572 elemObj = (Object*) newArray;
573 setObject = true;
574 }
575 width = 0;
576 break;
577 case kDexAnnotationAnnotation:
578 /* encoded_annotation format */
579 if (resultStyle == kAllRaw)
580 return false;
581 elemObj = processEncodedAnnotation(clazz, &ptr);
582 setObject = true;
583 if (elemObj == NULL)
584 return false;
585 dvmAddTrackedAlloc(elemObj, self); // balance the Release
586 width = 0;
587 break;
588 case kDexAnnotationNull:
589 if (resultStyle == kAllRaw) {
590 pValue->value.i = 0;
591 } else {
592 assert(elemObj == NULL);
593 setObject = true;
594 }
595 width = 0;
596 break;
597 default:
598 LOGE("Bad annotation element value byte 0x%02x (0x%02x)\n",
599 valueType, valueType & kDexAnnotationValueTypeMask);
600 assert(false);
601 return false;
602 }
603
604 ptr += width;
605
606 *pPtr = ptr;
607 if (setObject)
608 pValue->value.l = elemObj;
609 return true;
610 }
611
612
613 /*
614 * For most object types, we have nothing to do here, and we just return
615 * "valueObj".
616 *
617 * For an array annotation, the type of the extracted object will always
618 * be java.lang.Object[], but we want it to match the type that the
619 * annotation member is expected to return. In theory we can just stomp
620 * the object's class to have the correct type, but this strikes me as a
621 * risky proposition (at the very least we would need to call instanceof()
622 * on every element).
623 *
624 * We allocate a second array with the correct type, then copy the data
625 * over. This releases the tracked allocation on "valueObj" and returns
626 * a new, tracked object.
627 *
628 * On failure, this releases the tracking on "valueObj" and returns NULL
629 * (allowing the call to say "foo = convertReturnType(foo, ..)").
630 */
convertReturnType(Object * valueObj,ClassObject * methodReturn)631 static Object* convertReturnType(Object* valueObj, ClassObject* methodReturn)
632 {
633 if (valueObj == NULL ||
634 !dvmIsArray((ArrayObject*)valueObj) || !dvmIsArrayClass(methodReturn))
635 {
636 return valueObj;
637 }
638
639 Thread* self = dvmThreadSelf();
640 ClassObject* srcElemClass;
641 ClassObject* dstElemClass;
642
643 /*
644 * Strip off one '[' to get element class. Note this is not the
645 * same as clazz->elementClass.
646 */
647 srcElemClass = dvmFindClass(valueObj->clazz->descriptor+1,
648 valueObj->clazz->classLoader);
649 dstElemClass = dvmFindClass(methodReturn->descriptor+1,
650 methodReturn->classLoader);
651 if (srcElemClass->primitiveType != PRIM_NOT ||
652 dstElemClass->primitiveType != PRIM_NOT)
653 {
654 LOGE("ERROR: array of primitives not expected here\n");
655 dvmAbort();
656 }
657 LOGV("HEY: converting valueObj from [%s to [%s\n",
658 srcElemClass->descriptor, dstElemClass->descriptor);
659
660 ArrayObject* srcArray = (ArrayObject*) valueObj;
661 u4 length = srcArray->length;
662 ArrayObject* newArray;
663
664 newArray = dvmAllocArrayByClass(methodReturn, length, ALLOC_DEFAULT);
665 if (newArray == NULL) {
666 LOGE("Failed creating duplicate annotation class (%s %d)\n",
667 methodReturn->descriptor, length);
668 goto bail;
669 }
670
671 if (!dvmCopyObjectArray(newArray, srcArray, dstElemClass)) {
672 LOGE("Annotation array copy failed\n");
673 dvmReleaseTrackedAlloc((Object*)newArray, self);
674 newArray = NULL;
675 goto bail;
676 }
677
678 bail:
679 /* replace old, return new */
680 dvmReleaseTrackedAlloc(valueObj, self);
681 return (Object*) newArray;
682 }
683
684 /*
685 * Create a new AnnotationMember.
686 *
687 * "clazz" is the class on which the annotations are defined. "pPtr"
688 * points to a pointer into the annotation data. "annoClass" is the
689 * annotation's class.
690 *
691 * We extract the annotation's value, create a new AnnotationMember object,
692 * and construct it.
693 *
694 * Returns NULL on failure; an exception may or may not be raised.
695 */
createAnnotationMember(const ClassObject * clazz,const ClassObject * annoClass,const u1 ** pPtr)696 static Object* createAnnotationMember(const ClassObject* clazz,
697 const ClassObject* annoClass, const u1** pPtr)
698 {
699 Thread* self = dvmThreadSelf();
700 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
701 StringObject* nameObj = NULL;
702 Object* valueObj = NULL;
703 Object* newMember = NULL;
704 Object* methodObj = NULL;
705 ClassObject* methodReturn = NULL;
706 u4 elementNameIdx;
707 const char* name;
708 AnnotationValue avalue;
709 JValue result;
710 bool failed = true;
711
712 elementNameIdx = readUleb128(pPtr);
713
714 if (!processAnnotationValue(clazz, pPtr, &avalue, kAllObjects)) {
715 LOGW("Failed processing annotation value\n");
716 goto bail;
717 }
718 valueObj = avalue.value.l;
719
720 /* new member to hold the element */
721 newMember =
722 dvmAllocObject(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
723 ALLOC_DEFAULT);
724 name = dexStringById(pDexFile, elementNameIdx);
725 nameObj = dvmCreateStringFromCstr(name, ALLOC_DEFAULT);
726
727 /* find the method in the annotation class, given only the name */
728 if (name != NULL) {
729 Method* annoMeth = dvmFindVirtualMethodByName(annoClass, name);
730 if (annoMeth == NULL) {
731 LOGW("WARNING: could not find annotation member %s in %s\n",
732 name, annoClass->descriptor);
733 } else {
734 methodObj = dvmCreateReflectMethodObject(annoMeth);
735 methodReturn = dvmGetBoxedReturnType(annoMeth);
736 }
737 }
738 if (newMember == NULL || nameObj == NULL || methodObj == NULL ||
739 methodReturn == NULL)
740 {
741 LOGE("Failed creating annotation element (m=%p n=%p a=%p r=%p)\n",
742 newMember, nameObj, methodObj, methodReturn);
743 goto bail;
744 }
745
746 /* convert the return type, if necessary */
747 valueObj = convertReturnType(valueObj, methodReturn);
748 if (valueObj == NULL)
749 goto bail;
750
751 /* call 4-argument constructor */
752 dvmCallMethod(self, gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
753 newMember, &result, nameObj, valueObj, methodReturn, methodObj);
754 if (dvmCheckException(self)) {
755 LOGD("Failed constructing annotation element\n");
756 goto bail;
757 }
758
759 failed = false;
760
761 bail:
762 /* release tracked allocations */
763 dvmReleaseTrackedAlloc(newMember, self);
764 dvmReleaseTrackedAlloc((Object*)nameObj, self);
765 dvmReleaseTrackedAlloc(valueObj, self);
766 dvmReleaseTrackedAlloc(methodObj, self);
767 if (failed)
768 return NULL;
769 else
770 return newMember;
771 }
772
773 /*
774 * Create a new Annotation object from what we find in the annotation item.
775 *
776 * "clazz" is the class on which the annotations are defined. "pPtr"
777 * points to a pointer into the annotation data.
778 *
779 * We use the AnnotationFactory class to create the annotation for us. The
780 * method we call is:
781 *
782 * public static Annotation createAnnotation(
783 * Class<? extends Annotation> annotationType,
784 * AnnotationMember[] elements)
785 *
786 * Returns a new Annotation, which will NOT be in the local ref table and
787 * not referenced elsewhere, so store it away soon. On failure, returns NULL
788 * with an exception raised.
789 */
processEncodedAnnotation(const ClassObject * clazz,const u1 ** pPtr)790 static Object* processEncodedAnnotation(const ClassObject* clazz,
791 const u1** pPtr)
792 {
793 Thread* self = dvmThreadSelf();
794 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
795 Object* newAnno = NULL;
796 ArrayObject* elementArray = NULL;
797 const ClassObject* annoClass;
798 const u1* ptr;
799 u4 typeIdx, size;
800
801 ptr = *pPtr;
802 typeIdx = readUleb128(&ptr);
803 size = readUleb128(&ptr);
804
805 LOGVV("----- processEnc ptr=%p type=%d size=%d\n", ptr, typeIdx, size);
806
807 annoClass = dvmDexGetResolvedClass(clazz->pDvmDex, typeIdx);
808 if (annoClass == NULL) {
809 annoClass = dvmResolveClass(clazz, typeIdx, true);
810 if (annoClass == NULL) {
811 LOGE("Unable to resolve %s annotation class %d\n",
812 clazz->descriptor, typeIdx);
813 assert(dvmCheckException(self));
814 return NULL;
815 }
816 }
817
818 LOGV("----- processEnc ptr=%p [0x%06x] typeIdx=%d size=%d class=%s\n",
819 *pPtr, *pPtr - (u1*) clazz->pDvmDex->pDexFile->baseAddr,
820 typeIdx, size, annoClass->descriptor);
821
822 /*
823 * Elements are parsed out and stored in an array. The Harmony
824 * constructor wants an array with just the declared elements --
825 * default values get merged in later.
826 */
827 JValue result;
828 Object** pElement = NULL;
829
830 if (size > 0) {
831 elementArray = dvmAllocArrayByClass(
832 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray,
833 size, ALLOC_DEFAULT);
834 if (elementArray == NULL) {
835 LOGE("failed to allocate annotation member array (%d elements)\n",
836 size);
837 goto bail;
838 }
839 pElement = (Object**) elementArray->contents;
840 }
841
842 /*
843 * "ptr" points to a byte stream with "size" occurrences of
844 * annotation_element.
845 */
846 while (size--) {
847 Object* newMember = createAnnotationMember(clazz, annoClass, &ptr);
848 if (newMember == NULL)
849 goto bail;
850
851 /* add it to the array */
852 *pElement++ = newMember;
853 }
854
855 dvmCallMethod(self,
856 gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation,
857 NULL, &result, annoClass, elementArray);
858 if (dvmCheckException(self)) {
859 LOGD("Failed creating an annotation\n");
860 //dvmLogExceptionStackTrace();
861 goto bail;
862 }
863
864 newAnno = result.l;
865
866 bail:
867 dvmReleaseTrackedAlloc((Object*) elementArray, NULL);
868 *pPtr = ptr;
869 if (newAnno == NULL && !dvmCheckException(self)) {
870 /* make sure an exception is raised */
871 dvmThrowException("Ljava/lang/RuntimeException;",
872 "failure in processEncodedAnnotation");
873 }
874 return newAnno;
875 }
876
877 /*
878 * Run through an annotation set and convert each entry into an Annotation
879 * object.
880 *
881 * Returns an array of Annotation objects, or NULL with an exception raised
882 * on alloc failure.
883 */
processAnnotationSet(const ClassObject * clazz,const DexAnnotationSetItem * pAnnoSet,int visibility)884 static ArrayObject* processAnnotationSet(const ClassObject* clazz,
885 const DexAnnotationSetItem* pAnnoSet, int visibility)
886 {
887 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
888 const DexAnnotationItem* pAnnoItem;
889 ArrayObject* annoArray;
890 Object** pContents;
891 int i, count;
892
893 /* we need these later; make sure they're initialized */
894 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory))
895 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory);
896 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember))
897 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember);
898
899 /* count up the number of visible elements */
900 for (i = count = 0; i < (int) pAnnoSet->size; i++) {
901 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
902 if (pAnnoItem->visibility == visibility)
903 count++;
904 }
905
906 annoArray =dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray,
907 count, ALLOC_DEFAULT);
908 if (annoArray == NULL)
909 return NULL;
910 pContents = (Object**) annoArray->contents;
911
912 /*
913 * Generate Annotation objects. We must put them into the array
914 * immediately (or add them to the tracked ref table).
915 */
916 for (i = 0; i < (int) pAnnoSet->size; i++) {
917 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
918 if (pAnnoItem->visibility != visibility)
919 continue;
920 const u1* ptr = pAnnoItem->annotation;
921 *pContents = processEncodedAnnotation(clazz, &ptr);
922 if (*pContents == NULL) {
923 dvmReleaseTrackedAlloc((Object*) annoArray, NULL);
924 return NULL;
925 }
926 pContents++;
927 }
928
929 return annoArray;
930 }
931
932
933 /*
934 * ===========================================================================
935 * Skipping and scanning
936 * ===========================================================================
937 */
938
939 /*
940 * Skip past an annotation value.
941 *
942 * "clazz" is the class on which the annotations are defined.
943 *
944 * Returns "true" on success, "false" on parsing failure.
945 */
skipAnnotationValue(const ClassObject * clazz,const u1 ** pPtr)946 static bool skipAnnotationValue(const ClassObject* clazz, const u1** pPtr)
947 {
948 const u1* ptr = *pPtr;
949 u1 valueType, valueArg;
950 int width;
951
952 valueType = *ptr++;
953 valueArg = valueType >> kDexAnnotationValueArgShift;
954 width = valueArg + 1; /* assume */
955
956 LOGV("----- type is 0x%02x %d, ptr=%p [0x%06x]\n",
957 valueType & kDexAnnotationValueTypeMask, valueArg, ptr-1,
958 (ptr-1) - (u1*)clazz->pDvmDex->pDexFile->baseAddr);
959
960 switch (valueType & kDexAnnotationValueTypeMask) {
961 case kDexAnnotationByte: break;
962 case kDexAnnotationShort: break;
963 case kDexAnnotationChar: break;
964 case kDexAnnotationInt: break;
965 case kDexAnnotationLong: break;
966 case kDexAnnotationFloat: break;
967 case kDexAnnotationDouble: break;
968 case kDexAnnotationString: break;
969 case kDexAnnotationType: break;
970 case kDexAnnotationMethod: break;
971 case kDexAnnotationField: break;
972 case kDexAnnotationEnum: break;
973
974 case kDexAnnotationArray:
975 /* encoded_array format */
976 {
977 u4 size = readUleb128(&ptr);
978 while (size--) {
979 if (!skipAnnotationValue(clazz, &ptr))
980 return false;
981 }
982 }
983 width = 0;
984 break;
985 case kDexAnnotationAnnotation:
986 /* encoded_annotation format */
987 if (!skipEncodedAnnotation(clazz, &ptr))
988 return false;
989 width = 0;
990 break;
991 case kDexAnnotationBoolean:
992 case kDexAnnotationNull:
993 width = 0;
994 break;
995 default:
996 LOGE("Bad annotation element value byte 0x%02x\n", valueType);
997 assert(false);
998 return false;
999 }
1000
1001 ptr += width;
1002
1003 *pPtr = ptr;
1004 return true;
1005 }
1006
1007 /*
1008 * Skip past an encoded annotation. Mainly useful for annotations embedded
1009 * in other annotations.
1010 */
skipEncodedAnnotation(const ClassObject * clazz,const u1 ** pPtr)1011 static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr)
1012 {
1013 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1014 const u1* ptr;
1015 u4 size;
1016
1017 ptr = *pPtr;
1018 (void) readUleb128(&ptr);
1019 size = readUleb128(&ptr);
1020
1021 /*
1022 * "ptr" points to a byte stream with "size" occurrences of
1023 * annotation_element.
1024 */
1025 while (size--) {
1026 (void) readUleb128(&ptr);
1027
1028 if (!skipAnnotationValue(clazz, &ptr))
1029 return false;
1030 }
1031
1032 *pPtr = ptr;
1033 return true;
1034 }
1035
1036
1037 /*
1038 * Compare the name of the class in the DEX file to the supplied descriptor.
1039 * Return value is equivalent to strcmp.
1040 */
compareClassDescriptor(DexFile * pDexFile,u4 typeIdx,const char * descriptor)1041 static int compareClassDescriptor(DexFile* pDexFile, u4 typeIdx,
1042 const char* descriptor)
1043 {
1044 const char* str = dexStringByTypeIdx(pDexFile, typeIdx);
1045
1046 return strcmp(str, descriptor);
1047 }
1048
1049 /*
1050 * Search through the annotation set for an annotation with a matching
1051 * descriptor.
1052 *
1053 * Comparing the string descriptor is slower than comparing an integer class
1054 * index. If annotation lists are expected to be long, we could look up
1055 * the class' index by name from the DEX file, rather than doing a class
1056 * lookup and string compare on each entry. (Note the index will be
1057 * different for each DEX file, so we can't cache annotation class indices
1058 * globally.)
1059 */
searchAnnotationSet(const ClassObject * clazz,const DexAnnotationSetItem * pAnnoSet,const char * descriptor,int visibility)1060 static const DexAnnotationItem* searchAnnotationSet(const ClassObject* clazz,
1061 const DexAnnotationSetItem* pAnnoSet, const char* descriptor,
1062 int visibility)
1063 {
1064 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1065 const DexAnnotationItem* result = NULL;
1066 u4 typeIdx;
1067 int i;
1068
1069 //printf("##### searchAnnotationSet %s %d\n", descriptor, visibility);
1070
1071 for (i = 0; i < (int) pAnnoSet->size; i++) {
1072 const DexAnnotationItem* pAnnoItem;
1073
1074 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
1075 if (pAnnoItem->visibility != visibility)
1076 continue;
1077 const u1* ptr = pAnnoItem->annotation;
1078 typeIdx = readUleb128(&ptr);
1079
1080 if (compareClassDescriptor(pDexFile, typeIdx, descriptor) == 0) {
1081 //printf("##### match on %x/%p at %d\n", typeIdx, pDexFile, i);
1082 result = pAnnoItem;
1083 break;
1084 }
1085 }
1086
1087 return result;
1088 }
1089
1090 /*
1091 * Find an annotation value in the annotation_item whose name matches "name".
1092 * A pointer to the annotation_value is returned, or NULL if it's not found.
1093 */
searchEncodedAnnotation(const ClassObject * clazz,const u1 * ptr,const char * name)1094 static const u1* searchEncodedAnnotation(const ClassObject* clazz,
1095 const u1* ptr, const char* name)
1096 {
1097 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1098 u4 typeIdx, size;
1099
1100 typeIdx = readUleb128(&ptr);
1101 size = readUleb128(&ptr);
1102 //printf("##### searching ptr=%p type=%u size=%u\n", ptr, typeIdx, size);
1103
1104 while (size--) {
1105 u4 elementNameIdx;
1106 const char* elemName;
1107
1108 elementNameIdx = readUleb128(&ptr);
1109 elemName = dexStringById(pDexFile, elementNameIdx);
1110 if (strcmp(name, elemName) == 0) {
1111 //printf("##### item match on %s\n", name);
1112 return ptr; /* points to start of value */
1113 }
1114
1115 skipAnnotationValue(clazz, &ptr);
1116 }
1117
1118 //printf("##### no item match on %s\n", name);
1119 return NULL;
1120 }
1121
1122 #define GAV_FAILED ((Object*) 0x10000001)
1123
1124 /*
1125 * Extract an encoded annotation value from the field specified by "annoName".
1126 *
1127 * "expectedType" is an annotation value type, e.g. kDexAnnotationString.
1128 * "debugAnnoName" is only used in debug messages.
1129 *
1130 * Returns GAV_FAILED on failure. If an allocation failed, an exception
1131 * will be raised.
1132 */
getAnnotationValue(const ClassObject * clazz,const DexAnnotationItem * pAnnoItem,const char * annoName,int expectedType,const char * debugAnnoName)1133 static Object* getAnnotationValue(const ClassObject* clazz,
1134 const DexAnnotationItem* pAnnoItem, const char* annoName,
1135 int expectedType, const char* debugAnnoName)
1136 {
1137 const u1* ptr;
1138 Object* obj;
1139 AnnotationValue avalue;
1140
1141 /* find the annotation */
1142 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, annoName);
1143 if (ptr == NULL) {
1144 LOGW("%s annotation lacks '%s' member\n", debugAnnoName, annoName);
1145 return GAV_FAILED;
1146 }
1147
1148 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects))
1149 return GAV_FAILED;
1150
1151 /* make sure it has the expected format */
1152 if (avalue.type != expectedType) {
1153 LOGW("%s %s has wrong type (0x%02x, expected 0x%02x)\n",
1154 debugAnnoName, annoName, avalue.type, expectedType);
1155 return GAV_FAILED;
1156 }
1157
1158 return avalue.value.l;
1159 }
1160
1161
1162 /*
1163 * Find the Signature attribute and extract its value. (Signatures can
1164 * be found in annotations on classes, constructors, methods, and fields.)
1165 *
1166 * Caller must call dvmReleaseTrackedAlloc().
1167 *
1168 * Returns NULL if not found. On memory alloc failure, returns NULL with an
1169 * exception raised.
1170 */
getSignatureValue(const ClassObject * clazz,const DexAnnotationSetItem * pAnnoSet)1171 static ArrayObject* getSignatureValue(const ClassObject* clazz,
1172 const DexAnnotationSetItem* pAnnoSet)
1173 {
1174 const DexAnnotationItem* pAnnoItem;
1175 Object* obj;
1176
1177 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrSignature,
1178 kDexVisibilitySystem);
1179 if (pAnnoItem == NULL)
1180 return NULL;
1181
1182 /*
1183 * The Signature annotation has one member, "String value".
1184 */
1185 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationArray,
1186 "Signature");
1187 if (obj == GAV_FAILED)
1188 return NULL;
1189 assert(obj->clazz == gDvm.classJavaLangObjectArray);
1190
1191 return (ArrayObject*)obj;
1192 }
1193
1194
1195 /*
1196 * ===========================================================================
1197 * Class
1198 * ===========================================================================
1199 */
1200
1201 /*
1202 * Find the DexAnnotationSetItem for this class.
1203 */
findAnnotationSetForClass(const ClassObject * clazz)1204 static const DexAnnotationSetItem* findAnnotationSetForClass(
1205 const ClassObject* clazz)
1206 {
1207 DexFile* pDexFile;
1208 const DexAnnotationsDirectoryItem* pAnnoDir;
1209
1210 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */
1211 return NULL;
1212
1213 pDexFile = clazz->pDvmDex->pDexFile;
1214 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1215 if (pAnnoDir != NULL)
1216 return dexGetClassAnnotationSet(pDexFile, pAnnoDir);
1217 else
1218 return NULL;
1219 }
1220
1221 /*
1222 * Return an array of Annotation objects for the class. Returns an empty
1223 * array if there are no annotations.
1224 *
1225 * Caller must call dvmReleaseTrackedAlloc().
1226 *
1227 * On allocation failure, this returns NULL with an exception raised.
1228 */
dvmGetClassAnnotations(const ClassObject * clazz)1229 ArrayObject* dvmGetClassAnnotations(const ClassObject* clazz)
1230 {
1231 ArrayObject* annoArray;
1232 const DexAnnotationSetItem* pAnnoSet = NULL;
1233
1234 pAnnoSet = findAnnotationSetForClass(clazz);
1235 if (pAnnoSet == NULL) {
1236 /* no annotations for anything in class, or no class annotations */
1237 annoArray = emptyAnnoArray();
1238 } else {
1239 annoArray = processAnnotationSet(clazz, pAnnoSet,
1240 kDexVisibilityRuntime);
1241 }
1242
1243 return annoArray;
1244 }
1245
1246 /*
1247 * Retrieve the Signature annotation, if any. Returns NULL if no signature
1248 * exists.
1249 *
1250 * Caller must call dvmReleaseTrackedAlloc().
1251 */
dvmGetClassSignatureAnnotation(const ClassObject * clazz)1252 ArrayObject* dvmGetClassSignatureAnnotation(const ClassObject* clazz)
1253 {
1254 ArrayObject* signature = NULL;
1255 const DexAnnotationSetItem* pAnnoSet;
1256
1257 pAnnoSet = findAnnotationSetForClass(clazz);
1258 if (pAnnoSet != NULL)
1259 signature = getSignatureValue(clazz, pAnnoSet);
1260
1261 return signature;
1262 }
1263
1264 /*
1265 * Get the EnclosingMethod attribute from an annotation. Returns a Method
1266 * object, or NULL.
1267 *
1268 * Caller must call dvmReleaseTrackedAlloc().
1269 */
dvmGetEnclosingMethod(const ClassObject * clazz)1270 Object* dvmGetEnclosingMethod(const ClassObject* clazz)
1271 {
1272 const DexAnnotationItem* pAnnoItem;
1273 const DexAnnotationSetItem* pAnnoSet;
1274 Object* obj;
1275
1276 pAnnoSet = findAnnotationSetForClass(clazz);
1277 if (pAnnoSet == NULL)
1278 return NULL;
1279
1280 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod,
1281 kDexVisibilitySystem);
1282 if (pAnnoItem == NULL)
1283 return NULL;
1284
1285 /*
1286 * The EnclosingMethod annotation has one member, "Method value".
1287 */
1288 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationMethod,
1289 "EnclosingMethod");
1290 if (obj == GAV_FAILED)
1291 return NULL;
1292 assert(obj->clazz == gDvm.classJavaLangReflectConstructor ||
1293 obj->clazz == gDvm.classJavaLangReflectMethod);
1294
1295 return obj;
1296 }
1297
1298 /*
1299 * Find a class' enclosing class. We return what we find in the
1300 * EnclosingClass attribute.
1301 *
1302 * Returns a Class object, or NULL.
1303 *
1304 * Caller must call dvmReleaseTrackedAlloc().
1305 */
dvmGetDeclaringClass(const ClassObject * clazz)1306 ClassObject* dvmGetDeclaringClass(const ClassObject* clazz)
1307 {
1308 const DexAnnotationItem* pAnnoItem;
1309 const DexAnnotationSetItem* pAnnoSet;
1310 Object* obj;
1311
1312 pAnnoSet = findAnnotationSetForClass(clazz);
1313 if (pAnnoSet == NULL)
1314 return NULL;
1315
1316 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass,
1317 kDexVisibilitySystem);
1318 if (pAnnoItem == NULL)
1319 return NULL;
1320
1321 /*
1322 * The EnclosingClass annotation has one member, "Class value".
1323 */
1324 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType,
1325 "EnclosingClass");
1326 if (obj == GAV_FAILED)
1327 return NULL;
1328
1329 assert(obj->clazz == gDvm.classJavaLangClass);
1330 return (ClassObject*)obj;
1331 }
1332
1333 /*
1334 * Find a class' enclosing class. We first search for an EnclosingClass
1335 * attribute, and if that's not found we look for an EnclosingMethod.
1336 *
1337 * Returns a Class object, or NULL.
1338 *
1339 * Caller must call dvmReleaseTrackedAlloc().
1340 */
dvmGetEnclosingClass(const ClassObject * clazz)1341 ClassObject* dvmGetEnclosingClass(const ClassObject* clazz)
1342 {
1343 const DexAnnotationItem* pAnnoItem;
1344 const DexAnnotationSetItem* pAnnoSet;
1345 Object* obj;
1346
1347 pAnnoSet = findAnnotationSetForClass(clazz);
1348 if (pAnnoSet == NULL)
1349 return NULL;
1350
1351 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass,
1352 kDexVisibilitySystem);
1353 if (pAnnoItem != NULL) {
1354 /*
1355 * The EnclosingClass annotation has one member, "Class value".
1356 */
1357 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType,
1358 "EnclosingClass");
1359 if (obj != GAV_FAILED) {
1360 assert(obj->clazz == gDvm.classJavaLangClass);
1361 return (ClassObject*)obj;
1362 }
1363 }
1364
1365 /*
1366 * That didn't work. Look for an EnclosingMethod.
1367 *
1368 * We could create a java.lang.reflect.Method object and extract the
1369 * declaringClass from it, but that's more work than we want to do.
1370 * Instead, we find the "value" item and parse the index out ourselves.
1371 */
1372 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod,
1373 kDexVisibilitySystem);
1374 if (pAnnoItem == NULL)
1375 return NULL;
1376
1377 /* find the value member */
1378 const u1* ptr;
1379 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value");
1380 if (ptr == NULL) {
1381 LOGW("EnclosingMethod annotation lacks 'value' member\n");
1382 return NULL;
1383 }
1384
1385 /* parse it, verify the type */
1386 AnnotationValue avalue;
1387 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) {
1388 LOGW("EnclosingMethod parse failed\n");
1389 return NULL;
1390 }
1391 if (avalue.type != kDexAnnotationMethod) {
1392 LOGW("EnclosingMethod value has wrong type (0x%02x, expected 0x%02x)\n",
1393 avalue.type, kDexAnnotationMethod);
1394 return NULL;
1395 }
1396
1397 /* pull out the method index and resolve the method */
1398 Method* meth = resolveAmbiguousMethod(clazz, avalue.value.i);
1399 if (meth == NULL)
1400 return NULL;
1401
1402 ClassObject* methClazz = meth->clazz;
1403 dvmAddTrackedAlloc((Object*) methClazz, NULL); // balance the Release
1404 return methClazz;
1405 }
1406
1407 /*
1408 * Get the EnclosingClass attribute from an annotation. If found, returns
1409 * "true". A String with the original name of the class and the original
1410 * access flags are returned through the arguments. (The name will be NULL
1411 * for an anonymous inner class.)
1412 *
1413 * Caller must call dvmReleaseTrackedAlloc().
1414 */
dvmGetInnerClass(const ClassObject * clazz,StringObject ** pName,int * pAccessFlags)1415 bool dvmGetInnerClass(const ClassObject* clazz, StringObject** pName,
1416 int* pAccessFlags)
1417 {
1418 const DexAnnotationItem* pAnnoItem;
1419 const DexAnnotationSetItem* pAnnoSet;
1420
1421 pAnnoSet = findAnnotationSetForClass(clazz);
1422 if (pAnnoSet == NULL)
1423 return false;
1424
1425 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrInnerClass,
1426 kDexVisibilitySystem);
1427 if (pAnnoItem == NULL)
1428 return false;
1429
1430 /*
1431 * The InnerClass annotation has two members, "String name" and
1432 * "int accessFlags". We don't want to get the access flags as an
1433 * Integer, so we process that as a simple value.
1434 */
1435 const u1* ptr;
1436 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "name");
1437 if (ptr == NULL) {
1438 LOGW("InnerClass annotation lacks 'name' member\n");
1439 return false;
1440 }
1441
1442 /* parse it into an Object */
1443 AnnotationValue avalue;
1444 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) {
1445 LOGD("processAnnotationValue failed on InnerClass member 'name'\n");
1446 return false;
1447 }
1448
1449 /* make sure it has the expected format */
1450 if (avalue.type != kDexAnnotationNull &&
1451 avalue.type != kDexAnnotationString)
1452 {
1453 LOGW("InnerClass name has bad type (0x%02x, expected STRING or NULL)\n",
1454 avalue.type);
1455 return false;
1456 }
1457
1458 *pName = (StringObject*) avalue.value.l;
1459 assert(*pName == NULL || (*pName)->obj.clazz == gDvm.classJavaLangString);
1460
1461 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "accessFlags");
1462 if (ptr == NULL) {
1463 LOGW("InnerClass annotation lacks 'accessFlags' member\n");
1464 return false;
1465 }
1466
1467 /* parse it, verify the type */
1468 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) {
1469 LOGW("InnerClass accessFlags parse failed\n");
1470 return false;
1471 }
1472 if (avalue.type != kDexAnnotationInt) {
1473 LOGW("InnerClass value has wrong type (0x%02x, expected 0x%02x)\n",
1474 avalue.type, kDexAnnotationInt);
1475 return false;
1476 }
1477
1478 *pAccessFlags = avalue.value.i;
1479
1480 return true;
1481 }
1482
1483 /*
1484 * Extract an array of Class objects from the MemberClasses annotation
1485 * for this class.
1486 *
1487 * Caller must call dvmReleaseTrackedAlloc().
1488 *
1489 * Returns NULL if we don't find any member classes.
1490 */
dvmGetDeclaredClasses(const ClassObject * clazz)1491 ArrayObject* dvmGetDeclaredClasses(const ClassObject* clazz)
1492 {
1493 const DexAnnotationSetItem* pAnnoSet;
1494 const DexAnnotationItem* pAnnoItem;
1495 Object* obj;
1496
1497 pAnnoSet = findAnnotationSetForClass(clazz);
1498 if (pAnnoSet == NULL)
1499 return NULL;
1500
1501 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrMemberClasses,
1502 kDexVisibilitySystem);
1503 if (pAnnoItem == NULL)
1504 return NULL;
1505
1506 /*
1507 * The MemberClasses annotation has one member, "Class[] value".
1508 */
1509 obj = getAnnotationValue(clazz, pAnnoItem, "value",
1510 kDexAnnotationArray, "MemberClasses");
1511 if (obj == GAV_FAILED)
1512 return NULL;
1513 assert(dvmIsArray((ArrayObject*)obj));
1514 obj = convertReturnType(obj, gDvm.classJavaLangClassArray);
1515 return (ArrayObject*)obj;
1516 }
1517
1518
1519 /*
1520 * ===========================================================================
1521 * Method (and Constructor)
1522 * ===========================================================================
1523 */
1524
1525 /*
1526 * Compare the attributes (class name, method name, method signature) of
1527 * the specified method to "method".
1528 */
compareMethodStr(DexFile * pDexFile,u4 methodIdx,const Method * method)1529 static int compareMethodStr(DexFile* pDexFile, u4 methodIdx,
1530 const Method* method)
1531 {
1532 const DexMethodId* pMethodId = dexGetMethodId(pDexFile, methodIdx);
1533 const char* str = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
1534 int result = strcmp(str, method->clazz->descriptor);
1535
1536 if (result == 0) {
1537 str = dexStringById(pDexFile, pMethodId->nameIdx);
1538 result = strcmp(str, method->name);
1539 if (result == 0) {
1540 DexProto proto;
1541 dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
1542 result = dexProtoCompare(&proto, &method->prototype);
1543 }
1544 }
1545
1546 return result;
1547 }
1548
1549 /*
1550 * Given a method, determine the method's index.
1551 *
1552 * We could simply store this in the Method*, but that would cost 4 bytes
1553 * per method. Instead we plow through the DEX data.
1554 *
1555 * We have two choices: look through the class method data, or look through
1556 * the global method_ids table. The former is awkward because the method
1557 * could have been defined in a superclass or interface. The latter works
1558 * out reasonably well because it's in sorted order, though we're still left
1559 * doing a fair number of string comparisons.
1560 */
getMethodIdx(const Method * method)1561 static u4 getMethodIdx(const Method* method)
1562 {
1563 DexFile* pDexFile = method->clazz->pDvmDex->pDexFile;
1564 u4 hi = pDexFile->pHeader->methodIdsSize -1;
1565 u4 lo = 0;
1566 u4 cur;
1567
1568 while (hi >= lo) {
1569 int cmp;
1570 cur = (lo + hi) / 2;
1571
1572 cmp = compareMethodStr(pDexFile, cur, method);
1573 if (cmp < 0) {
1574 lo = cur + 1;
1575 } else if (cmp > 0) {
1576 hi = cur - 1;
1577 } else {
1578 break;
1579 }
1580 }
1581
1582 if (hi < lo) {
1583 /* this should be impossible -- the method came out of this DEX */
1584 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1585 LOGE("Unable to find method %s.%s %s in DEX file!\n",
1586 method->clazz->descriptor, method->name, desc);
1587 free(desc);
1588 dvmAbort();
1589 }
1590
1591 return cur;
1592 }
1593
1594 /*
1595 * Find the DexAnnotationSetItem for this method.
1596 *
1597 * Returns NULL if none found.
1598 */
findAnnotationSetForMethod(const Method * method)1599 static const DexAnnotationSetItem* findAnnotationSetForMethod(
1600 const Method* method)
1601 {
1602 ClassObject* clazz = method->clazz;
1603 DexFile* pDexFile;
1604 const DexAnnotationsDirectoryItem* pAnnoDir;
1605 const DexMethodAnnotationsItem* pMethodList;
1606 const DexAnnotationSetItem* pAnnoSet = NULL;
1607
1608 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */
1609 return NULL;
1610 pDexFile = clazz->pDvmDex->pDexFile;
1611
1612 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1613 if (pAnnoDir != NULL) {
1614 pMethodList = dexGetMethodAnnotations(pDexFile, pAnnoDir);
1615 if (pMethodList != NULL) {
1616 /*
1617 * Run through the list and find a matching method. We compare the
1618 * method ref indices in the annotation list with the method's DEX
1619 * method_idx value.
1620 *
1621 * TODO: use a binary search for long lists
1622 *
1623 * Alternate approach: for each entry in the annotations list,
1624 * find the method definition in the DEX file and perform string
1625 * comparisons on class name, method name, and signature.
1626 */
1627 u4 methodIdx = getMethodIdx(method);
1628 u4 count = dexGetMethodAnnotationsSize(pDexFile, pAnnoDir);
1629 u4 idx;
1630
1631 for (idx = 0; idx < count; idx++) {
1632 if (pMethodList[idx].methodIdx == methodIdx) {
1633 /* found! */
1634 pAnnoSet = dexGetMethodAnnotationSetItem(pDexFile,
1635 &pMethodList[idx]);
1636 break;
1637 }
1638 }
1639 }
1640 }
1641
1642 return pAnnoSet;
1643 }
1644
1645 /*
1646 * Return an array of Annotation objects for the method. Returns an empty
1647 * array if there are no annotations.
1648 *
1649 * Caller must call dvmReleaseTrackedAlloc().
1650 *
1651 * On allocation failure, this returns NULL with an exception raised.
1652 */
dvmGetMethodAnnotations(const Method * method)1653 ArrayObject* dvmGetMethodAnnotations(const Method* method)
1654 {
1655 ClassObject* clazz = method->clazz;
1656 const DexAnnotationSetItem* pAnnoSet;
1657 ArrayObject* annoArray = NULL;
1658
1659 pAnnoSet = findAnnotationSetForMethod(method);
1660 if (pAnnoSet == NULL) {
1661 /* no matching annotations found */
1662 annoArray = emptyAnnoArray();
1663 } else {
1664 annoArray = processAnnotationSet(clazz, pAnnoSet,kDexVisibilityRuntime);
1665 }
1666
1667 return annoArray;
1668 }
1669
1670 /*
1671 * Retrieve the Signature annotation, if any. Returns NULL if no signature
1672 * exists.
1673 *
1674 * Caller must call dvmReleaseTrackedAlloc().
1675 */
dvmGetMethodSignatureAnnotation(const Method * method)1676 ArrayObject* dvmGetMethodSignatureAnnotation(const Method* method)
1677 {
1678 ClassObject* clazz = method->clazz;
1679 const DexAnnotationSetItem* pAnnoSet;
1680 ArrayObject* signature = NULL;
1681
1682 pAnnoSet = findAnnotationSetForMethod(method);
1683 if (pAnnoSet != NULL)
1684 signature = getSignatureValue(clazz, pAnnoSet);
1685
1686 return signature;
1687 }
1688
1689 /*
1690 * Extract an array of exception classes from the "system" annotation list
1691 * for this method.
1692 *
1693 * Caller must call dvmReleaseTrackedAlloc().
1694 *
1695 * Returns NULL if we don't find any exceptions for this method.
1696 */
dvmGetMethodThrows(const Method * method)1697 ArrayObject* dvmGetMethodThrows(const Method* method)
1698 {
1699 ClassObject* clazz = method->clazz;
1700 const DexAnnotationSetItem* pAnnoSet;
1701 const DexAnnotationItem* pAnnoItem;
1702
1703 /* find the set for this method */
1704 pAnnoSet = findAnnotationSetForMethod(method);
1705 if (pAnnoSet == NULL)
1706 return NULL; /* nothing for this method */
1707
1708 /* find the "Throws" annotation, if any */
1709 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrThrows,
1710 kDexVisibilitySystem);
1711 if (pAnnoItem == NULL)
1712 return NULL; /* no Throws */
1713
1714 /*
1715 * The Throws annotation has one member, "Class[] value".
1716 */
1717 Object* obj = getAnnotationValue(clazz, pAnnoItem, "value",
1718 kDexAnnotationArray, "Throws");
1719 if (obj == GAV_FAILED)
1720 return NULL;
1721 assert(dvmIsArray((ArrayObject*)obj));
1722 obj = convertReturnType(obj, gDvm.classJavaLangClassArray);
1723 return (ArrayObject*)obj;
1724 }
1725
1726 /*
1727 * Given an Annotation's method, find the default value, if any.
1728 *
1729 * If this is a CLASS annotation, and we can't find a match for the
1730 * default class value, we need to throw a TypeNotPresentException.
1731 *
1732 * Caller must call dvmReleaseTrackedAlloc().
1733 */
dvmGetAnnotationDefaultValue(const Method * method)1734 Object* dvmGetAnnotationDefaultValue(const Method* method)
1735 {
1736 const ClassObject* clazz = method->clazz;
1737 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1738 const DexAnnotationsDirectoryItem* pAnnoDir;
1739 const DexAnnotationSetItem* pAnnoSet = NULL;
1740
1741 /*
1742 * The method's declaring class (the annotation) will have an
1743 * AnnotationDefault "system" annotation associated with it if any
1744 * of its methods have default values. Start by finding the
1745 * DexAnnotationItem associated with the class.
1746 */
1747 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1748 if (pAnnoDir != NULL)
1749 pAnnoSet = dexGetClassAnnotationSet(pDexFile, pAnnoDir);
1750 if (pAnnoSet == NULL) {
1751 /* no annotations for anything in class, or no class annotations */
1752 return NULL;
1753 }
1754
1755 /* find the "AnnotationDefault" annotation, if any */
1756 const DexAnnotationItem* pAnnoItem;
1757 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrAnnotationDefault,
1758 kDexVisibilitySystem);
1759 if (pAnnoItem == NULL) {
1760 /* no default values for any member in this annotation */
1761 //printf("##### no default annotations for %s.%s\n",
1762 // method->clazz->descriptor, method->name);
1763 return NULL;
1764 }
1765
1766 /*
1767 * The AnnotationDefault annotation has one member, "Annotation value".
1768 * We need to pull that out.
1769 */
1770 const u1* ptr;
1771 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value");
1772 if (ptr == NULL) {
1773 LOGW("AnnotationDefault annotation lacks 'value'\n");
1774 return NULL;
1775 }
1776 if ((*ptr & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) {
1777 LOGW("AnnotationDefault value has wrong type (0x%02x)\n",
1778 *ptr & kDexAnnotationValueTypeMask);
1779 return NULL;
1780 }
1781
1782 /*
1783 * The value_type byte for VALUE_ANNOTATION is followed by
1784 * encoded_annotation data. We want to scan through it to find an
1785 * entry whose name matches our method name.
1786 */
1787 ptr++;
1788 ptr = searchEncodedAnnotation(clazz, ptr, method->name);
1789 if (ptr == NULL)
1790 return NULL; /* no default annotation for this method */
1791
1792 /* got it, pull it out */
1793 AnnotationValue avalue;
1794 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) {
1795 LOGD("processAnnotationValue failed on default for '%s'\n",
1796 method->name);
1797 return NULL;
1798 }
1799
1800 /* convert the return type, if necessary */
1801 ClassObject* methodReturn = dvmGetBoxedReturnType(method);
1802 Object* obj = avalue.value.l;
1803 obj = convertReturnType(obj, methodReturn);
1804
1805 return obj;
1806 }
1807
1808
1809 /*
1810 * ===========================================================================
1811 * Field
1812 * ===========================================================================
1813 */
1814
1815 /*
1816 * Compare the attributes (class name, field name, field signature) of
1817 * the specified field to "field".
1818 */
compareFieldStr(DexFile * pDexFile,u4 idx,const Field * field)1819 static int compareFieldStr(DexFile* pDexFile, u4 idx, const Field* field)
1820 {
1821 const DexFieldId* pFieldId = dexGetFieldId(pDexFile, idx);
1822 const char* str = dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
1823 int result = strcmp(str, field->clazz->descriptor);
1824
1825 if (result == 0) {
1826 str = dexStringById(pDexFile, pFieldId->nameIdx);
1827 result = strcmp(str, field->name);
1828 if (result == 0) {
1829 str = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
1830 result = strcmp(str, field->signature);
1831 }
1832 }
1833
1834 return result;
1835 }
1836
1837 /*
1838 * Given a field, determine the field's index.
1839 *
1840 * This has the same tradeoffs as getMethodIdx.
1841 */
getFieldIdx(const Field * field)1842 static u4 getFieldIdx(const Field* field)
1843 {
1844 DexFile* pDexFile = field->clazz->pDvmDex->pDexFile;
1845 u4 hi = pDexFile->pHeader->fieldIdsSize -1;
1846 u4 lo = 0;
1847 u4 cur;
1848
1849 while (hi >= lo) {
1850 int cmp;
1851 cur = (lo + hi) / 2;
1852
1853 cmp = compareFieldStr(pDexFile, cur, field);
1854 if (cmp < 0) {
1855 lo = cur + 1;
1856 } else if (cmp > 0) {
1857 hi = cur - 1;
1858 } else {
1859 break;
1860 }
1861 }
1862
1863 if (hi < lo) {
1864 /* this should be impossible -- the field came out of this DEX */
1865 LOGE("Unable to find field %s.%s %s in DEX file!\n",
1866 field->clazz->descriptor, field->name, field->signature);
1867 dvmAbort();
1868 }
1869
1870 return cur;
1871 }
1872
1873 /*
1874 * Find the DexAnnotationSetItem for this field.
1875 *
1876 * Returns NULL if none found.
1877 */
findAnnotationSetForField(const Field * field)1878 static const DexAnnotationSetItem* findAnnotationSetForField(const Field* field)
1879 {
1880 ClassObject* clazz = field->clazz;
1881 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1882 const DexAnnotationsDirectoryItem* pAnnoDir;
1883 const DexFieldAnnotationsItem* pFieldList;
1884 const DexAnnotationSetItem* pAnnoSet = NULL;
1885
1886 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1887 if (pAnnoDir == NULL)
1888 return NULL;
1889
1890 pFieldList = dexGetFieldAnnotations(pDexFile, pAnnoDir);
1891 if (pFieldList == NULL)
1892 return NULL;
1893
1894 /*
1895 * Run through the list and find a matching field. We compare the
1896 * field ref indices in the annotation list with the field's DEX
1897 * field_idx value.
1898 *
1899 * TODO: use a binary search for long lists
1900 *
1901 * Alternate approach: for each entry in the annotations list,
1902 * find the field definition in the DEX file and perform string
1903 * comparisons on class name, field name, and signature.
1904 */
1905 u4 fieldIdx = getFieldIdx(field);
1906 u4 count = dexGetFieldAnnotationsSize(pDexFile, pAnnoDir);
1907 u4 idx;
1908
1909 for (idx = 0; idx < count; idx++) {
1910 if (pFieldList[idx].fieldIdx == fieldIdx) {
1911 /* found! */
1912 return dexGetFieldAnnotationSetItem(pDexFile, &pFieldList[idx]);
1913 }
1914 }
1915
1916 return NULL;
1917 }
1918
1919 /*
1920 * Return an array of Annotation objects for the field. Returns an empty
1921 * array if there are no annotations.
1922 *
1923 * Caller must call dvmReleaseTrackedAlloc().
1924 *
1925 * On allocation failure, this returns NULL with an exception raised.
1926 */
dvmGetFieldAnnotations(const Field * field)1927 ArrayObject* dvmGetFieldAnnotations(const Field* field)
1928 {
1929 ClassObject* clazz = field->clazz;
1930 ArrayObject* annoArray = NULL;
1931 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1932 const DexAnnotationsDirectoryItem* pAnnoDir;
1933 const DexAnnotationSetItem* pAnnoSet = NULL;
1934
1935 pAnnoSet = findAnnotationSetForField(field);
1936 if (pAnnoSet == NULL) {
1937 /* no matching annotations found */
1938 annoArray = emptyAnnoArray();
1939 } else {
1940 annoArray = processAnnotationSet(clazz, pAnnoSet,
1941 kDexVisibilityRuntime);
1942 }
1943
1944 return annoArray;
1945 }
1946
1947 /*
1948 * Retrieve the Signature annotation, if any. Returns NULL if no signature
1949 * exists.
1950 *
1951 * Caller must call dvmReleaseTrackedAlloc().
1952 */
dvmGetFieldSignatureAnnotation(const Field * field)1953 ArrayObject* dvmGetFieldSignatureAnnotation(const Field* field)
1954 {
1955 ClassObject* clazz = field->clazz;
1956 const DexAnnotationSetItem* pAnnoSet;
1957 ArrayObject* signature = NULL;
1958
1959 pAnnoSet = findAnnotationSetForField(field);
1960 if (pAnnoSet != NULL)
1961 signature = getSignatureValue(clazz, pAnnoSet);
1962
1963 return signature;
1964 }
1965
1966
1967 /*
1968 * ===========================================================================
1969 * Parameter
1970 * ===========================================================================
1971 */
1972
1973 /*
1974 * We have an annotation_set_ref_list, which is essentially a list of
1975 * entries that we pass to processAnnotationSet().
1976 *
1977 * The returned object must be released with dvmReleaseTrackedAlloc.
1978 */
processAnnotationSetRefList(const ClassObject * clazz,const DexAnnotationSetRefList * pAnnoSetList,u4 count)1979 static ArrayObject* processAnnotationSetRefList(const ClassObject* clazz,
1980 const DexAnnotationSetRefList* pAnnoSetList, u4 count)
1981 {
1982 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1983 ArrayObject* annoArrayArray = NULL;
1984 ArrayObject** pContents;
1985 u4 idx;
1986
1987 /* allocate an array of Annotation arrays to hold results */
1988 annoArrayArray = dvmAllocArrayByClass(
1989 gDvm.classJavaLangAnnotationAnnotationArrayArray, count, ALLOC_DEFAULT);
1990 if (annoArrayArray == NULL) {
1991 LOGW("annotation set ref array alloc failed\n");
1992 goto bail;
1993 }
1994
1995 pContents = (ArrayObject**) annoArrayArray->contents;
1996
1997 for (idx = 0; idx < count; idx++) {
1998 Thread* self = dvmThreadSelf();
1999 const DexAnnotationSetRefItem* pItem;
2000 const DexAnnotationSetItem* pAnnoSet;
2001
2002 pItem = dexGetParameterAnnotationSetRef(pAnnoSetList, idx);
2003 pAnnoSet = dexGetSetRefItemItem(pDexFile, pItem);
2004 *pContents = processAnnotationSet(clazz, pAnnoSet,
2005 kDexVisibilityRuntime);
2006 if (*pContents == NULL) {
2007 LOGW("processAnnotationSet failed\n");
2008 annoArrayArray = NULL;
2009 goto bail;
2010 }
2011 dvmReleaseTrackedAlloc((Object*) *pContents, self);
2012 pContents++;
2013 }
2014
2015 bail:
2016 return annoArrayArray;
2017 }
2018
2019 /*
2020 * Find the DexAnnotationSetItem for this parameter.
2021 *
2022 * Returns NULL if none found.
2023 */
findAnnotationsItemForMethod(const Method * method)2024 static const DexParameterAnnotationsItem* findAnnotationsItemForMethod(
2025 const Method* method)
2026 {
2027 ClassObject* clazz = method->clazz;
2028 DexFile* pDexFile;
2029 const DexAnnotationsDirectoryItem* pAnnoDir;
2030 const DexParameterAnnotationsItem* pParameterList;
2031
2032 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */
2033 return NULL;
2034
2035 pDexFile = clazz->pDvmDex->pDexFile;
2036 pAnnoDir = getAnnoDirectory(pDexFile, clazz);
2037 if (pAnnoDir == NULL)
2038 return NULL;
2039
2040 pParameterList = dexGetParameterAnnotations(pDexFile, pAnnoDir);
2041 if (pParameterList == NULL)
2042 return NULL;
2043
2044 /*
2045 * Run through the list and find a matching method. We compare the
2046 * method ref indices in the annotation list with the method's DEX
2047 * method_idx value.
2048 *
2049 * TODO: use a binary search for long lists
2050 *
2051 * Alternate approach: for each entry in the annotations list,
2052 * find the method definition in the DEX file and perform string
2053 * comparisons on class name, method name, and signature.
2054 */
2055 u4 methodIdx = getMethodIdx(method);
2056 u4 count = dexGetParameterAnnotationsSize(pDexFile, pAnnoDir);
2057 u4 idx;
2058
2059 for (idx = 0; idx < count; idx++) {
2060 if (pParameterList[idx].methodIdx == methodIdx) {
2061 /* found! */
2062 return &pParameterList[idx];
2063 }
2064 }
2065
2066 return NULL;
2067 }
2068
2069
2070 /*
2071 * Count up the number of arguments the method takes. The "this" pointer
2072 * doesn't count.
2073 */
countMethodArguments(const Method * method)2074 static int countMethodArguments(const Method* method)
2075 {
2076 /* method->shorty[0] is the return type */
2077 return strlen(method->shorty + 1);
2078 }
2079
2080 /*
2081 * Return an array of arrays of Annotation objects. The outer array has
2082 * one entry per method parameter, the inner array has the list of annotations
2083 * associated with that parameter.
2084 *
2085 * If the method has no parameters, we return an array of length zero. If
2086 * the method has one or more parameters, we return an array whose length
2087 * is equal to the number of parameters; if a given parameter does not have
2088 * an annotation, the corresponding entry will be null.
2089 *
2090 * Caller must call dvmReleaseTrackedAlloc().
2091 */
dvmGetParameterAnnotations(const Method * method)2092 ArrayObject* dvmGetParameterAnnotations(const Method* method)
2093 {
2094 ClassObject* clazz = method->clazz;
2095 const DexParameterAnnotationsItem* pItem;
2096 ArrayObject* annoArrayArray = NULL;
2097
2098 pItem = findAnnotationsItemForMethod(method);
2099 if (pItem != NULL) {
2100 DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2101 const DexAnnotationSetRefList* pAnnoSetList;
2102 u4 size;
2103
2104 size = dexGetParameterAnnotationSetRefSize(pDexFile, pItem);
2105 pAnnoSetList = dexGetParameterAnnotationSetRefList(pDexFile, pItem);
2106 annoArrayArray = processAnnotationSetRefList(clazz, pAnnoSetList, size);
2107 } else {
2108 /* no matching annotations found */
2109 annoArrayArray = emptyAnnoArrayArray(countMethodArguments(method));
2110 }
2111
2112 return annoArrayArray;
2113 }
2114
2115
2116 /*
2117 * ===========================================================================
2118 * DexEncodedArray interpretation
2119 * ===========================================================================
2120 */
2121
2122 /**
2123 * Initializes an encoded array iterator.
2124 *
2125 * @param iterator iterator to initialize
2126 * @param encodedArray encoded array to iterate over
2127 * @param clazz class to use when resolving strings and types
2128 */
dvmEncodedArrayIteratorInitialize(EncodedArrayIterator * iterator,const DexEncodedArray * encodedArray,const ClassObject * clazz)2129 void dvmEncodedArrayIteratorInitialize(EncodedArrayIterator* iterator,
2130 const DexEncodedArray* encodedArray, const ClassObject* clazz) {
2131 iterator->encodedArray = encodedArray;
2132 iterator->cursor = encodedArray->array;
2133 iterator->size = readUleb128(&iterator->cursor);
2134 iterator->elementsLeft = iterator->size;
2135 iterator->clazz = clazz;
2136 }
2137
2138 /**
2139 * Returns whether there are more elements to be read.
2140 */
dvmEncodedArrayIteratorHasNext(const EncodedArrayIterator * iterator)2141 bool dvmEncodedArrayIteratorHasNext(const EncodedArrayIterator* iterator) {
2142 return (iterator->elementsLeft != 0);
2143 }
2144
2145 /**
2146 * Returns the next decoded value from the iterator, advancing its
2147 * cursor. This returns primitive values in their corresponding union
2148 * slots, and returns everything else (including nulls) as object
2149 * references in the "l" union slot.
2150 *
2151 * The caller must call dvmReleaseTrackedAlloc() on any returned reference.
2152 *
2153 * @param value pointer to store decoded value into
2154 * @returns true if a value was decoded and the cursor advanced; false if
2155 * the last value had already been decoded or if there was a problem decoding
2156 */
dvmEncodedArrayIteratorGetNext(EncodedArrayIterator * iterator,AnnotationValue * value)2157 bool dvmEncodedArrayIteratorGetNext(EncodedArrayIterator* iterator,
2158 AnnotationValue* value) {
2159 bool processed;
2160
2161 if (iterator->elementsLeft == 0) {
2162 return false;
2163 }
2164
2165 processed = processAnnotationValue(iterator->clazz, &iterator->cursor,
2166 value, kPrimitivesOrObjects);
2167
2168 if (! processed) {
2169 LOGE("Failed to process array element %d from %p",
2170 iterator->size - iterator->elementsLeft,
2171 iterator->encodedArray);
2172 iterator->elementsLeft = 0;
2173 return false;
2174 }
2175
2176 iterator->elementsLeft--;
2177 return true;
2178 }
2179
2180