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