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