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