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