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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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