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