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