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