• 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     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