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