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