Annotation.cpp revision ee817c75a2afbdf3d6ce05b4bf0326215135025c
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 38static Object* processEncodedAnnotation(const ClassObject* clazz,\ 39 const u1** pPtr); 40static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr); 41 42/* 43 * System annotation descriptors. 44 */ 45static const char* kDescrAnnotationDefault 46 = "Ldalvik/annotation/AnnotationDefault;"; 47static const char* kDescrEnclosingClass 48 = "Ldalvik/annotation/EnclosingClass;"; 49static const char* kDescrEnclosingMethod 50 = "Ldalvik/annotation/EnclosingMethod;"; 51static const char* kDescrInnerClass = "Ldalvik/annotation/InnerClass;"; 52static const char* kDescrMemberClasses 53 = "Ldalvik/annotation/MemberClasses;"; 54static const char* kDescrSignature = "Ldalvik/annotation/Signature;"; 55static const char* kDescrThrows = "Ldalvik/annotation/Throws;"; 56 57/* 58 * Read an unsigned LEB128 value from a buffer. Advances "pBuf". 59 */ 60static 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 */ 87static 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 */ 109static 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 */ 120static 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 */ 142static 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 */ 158static 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 */ 177static 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 */ 193static 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 */ 230static 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 */ 286enum 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 */ 317static 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 */ 565static 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 626bail: 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 */ 644static 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 707bail: 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 */ 736static 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 809bail: 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 */ 826static 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 */ 895static 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 */ 945static 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 */ 971static 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 */ 1036static 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 */ 1065static 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 */ 1084static 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 */ 1118static 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 */ 1157static 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 */ 1194static 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 */ 1227static 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 */ 1252ArrayObject* 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 */ 1272Object* 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 */ 1286bool 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 */ 1304ArrayObject* 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 */ 1322Object* 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 */ 1358ClassObject* 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 */ 1393ClassObject* 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 */ 1467bool 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 */ 1543ArrayObject* 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 */ 1581static 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 */ 1613static u4 getMethodIdx(const Method* method) 1614{ 1615 DexFile* pDexFile = method->clazz->pDvmDex->pDexFile; 1616 u4 hi = pDexFile->pHeader->methodIdsSize -1; 1617 u4 lo = 0; 1618 u4 cur; 1619 1620 while (hi >= lo) { 1621 int cmp; 1622 cur = (lo + hi) / 2; 1623 1624 cmp = compareMethodStr(pDexFile, cur, method); 1625 if (cmp < 0) { 1626 lo = cur + 1; 1627 } else if (cmp > 0) { 1628 hi = cur - 1; 1629 } else { 1630 break; 1631 } 1632 } 1633 1634 if (hi < lo) { 1635 /* this should be impossible -- the method came out of this DEX */ 1636 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 1637 ALOGE("Unable to find method %s.%s %s in DEX file!", 1638 method->clazz->descriptor, method->name, desc); 1639 free(desc); 1640 dvmAbort(); 1641 } 1642 1643 return cur; 1644} 1645 1646/* 1647 * Find the DexAnnotationSetItem for this method. 1648 * 1649 * Returns NULL if none found. 1650 */ 1651static const DexAnnotationSetItem* findAnnotationSetForMethod( 1652 const Method* method) 1653{ 1654 ClassObject* clazz = method->clazz; 1655 DexFile* pDexFile; 1656 const DexAnnotationsDirectoryItem* pAnnoDir; 1657 const DexMethodAnnotationsItem* pMethodList; 1658 const DexAnnotationSetItem* pAnnoSet = NULL; 1659 1660 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */ 1661 return NULL; 1662 pDexFile = clazz->pDvmDex->pDexFile; 1663 1664 pAnnoDir = getAnnoDirectory(pDexFile, clazz); 1665 if (pAnnoDir != NULL) { 1666 pMethodList = dexGetMethodAnnotations(pDexFile, pAnnoDir); 1667 if (pMethodList != NULL) { 1668 /* 1669 * Run through the list and find a matching method. We compare the 1670 * method ref indices in the annotation list with the method's DEX 1671 * method_idx value. 1672 * 1673 * TODO: use a binary search for long lists 1674 * 1675 * Alternate approach: for each entry in the annotations list, 1676 * find the method definition in the DEX file and perform string 1677 * comparisons on class name, method name, and signature. 1678 */ 1679 u4 methodIdx = getMethodIdx(method); 1680 u4 count = dexGetMethodAnnotationsSize(pDexFile, pAnnoDir); 1681 u4 idx; 1682 1683 for (idx = 0; idx < count; idx++) { 1684 if (pMethodList[idx].methodIdx == methodIdx) { 1685 /* found! */ 1686 pAnnoSet = dexGetMethodAnnotationSetItem(pDexFile, 1687 &pMethodList[idx]); 1688 break; 1689 } 1690 } 1691 } 1692 } 1693 1694 return pAnnoSet; 1695} 1696 1697/* 1698 * Return an array of Annotation objects for the method. Returns an empty 1699 * array if there are no annotations. 1700 * 1701 * Caller must call dvmReleaseTrackedAlloc(). 1702 * 1703 * On allocation failure, this returns NULL with an exception raised. 1704 */ 1705ArrayObject* dvmGetMethodAnnotations(const Method* method) 1706{ 1707 ClassObject* clazz = method->clazz; 1708 const DexAnnotationSetItem* pAnnoSet; 1709 ArrayObject* annoArray = NULL; 1710 1711 pAnnoSet = findAnnotationSetForMethod(method); 1712 if (pAnnoSet == NULL) { 1713 /* no matching annotations found */ 1714 annoArray = emptyAnnoArray(); 1715 } else { 1716 annoArray = processAnnotationSet(clazz, pAnnoSet,kDexVisibilityRuntime); 1717 } 1718 1719 return annoArray; 1720} 1721 1722/* 1723 * Returns the annotation or NULL if it doesn't exist. 1724 */ 1725Object* dvmGetMethodAnnotation(const ClassObject* clazz, const Method* method, 1726 const ClassObject* annotationClazz) 1727{ 1728 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method); 1729 if (pAnnoSet == NULL) { 1730 return NULL; 1731 } 1732 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet, 1733 kDexVisibilityRuntime, annotationClazz); 1734} 1735 1736/* 1737 * Returns true if the annotation exists. 1738 */ 1739bool dvmIsMethodAnnotationPresent(const ClassObject* clazz, 1740 const Method* method, const ClassObject* annotationClazz) 1741{ 1742 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method); 1743 if (pAnnoSet == NULL) { 1744 return NULL; 1745 } 1746 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet( 1747 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz); 1748 return (pAnnoItem != NULL); 1749} 1750 1751/* 1752 * Retrieve the Signature annotation, if any. Returns NULL if no signature 1753 * exists. 1754 * 1755 * Caller must call dvmReleaseTrackedAlloc(). 1756 */ 1757ArrayObject* dvmGetMethodSignatureAnnotation(const Method* method) 1758{ 1759 ClassObject* clazz = method->clazz; 1760 const DexAnnotationSetItem* pAnnoSet; 1761 ArrayObject* signature = NULL; 1762 1763 pAnnoSet = findAnnotationSetForMethod(method); 1764 if (pAnnoSet != NULL) 1765 signature = getSignatureValue(clazz, pAnnoSet); 1766 1767 return signature; 1768} 1769 1770/* 1771 * Extract an array of exception classes from the "system" annotation list 1772 * for this method. 1773 * 1774 * Caller must call dvmReleaseTrackedAlloc(). 1775 * 1776 * Returns NULL if we don't find any exceptions for this method. 1777 */ 1778ArrayObject* dvmGetMethodThrows(const Method* method) 1779{ 1780 ClassObject* clazz = method->clazz; 1781 const DexAnnotationSetItem* pAnnoSet; 1782 const DexAnnotationItem* pAnnoItem; 1783 1784 /* find the set for this method */ 1785 pAnnoSet = findAnnotationSetForMethod(method); 1786 if (pAnnoSet == NULL) 1787 return NULL; /* nothing for this method */ 1788 1789 /* find the "Throws" annotation, if any */ 1790 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrThrows, 1791 kDexVisibilitySystem); 1792 if (pAnnoItem == NULL) 1793 return NULL; /* no Throws */ 1794 1795 /* 1796 * The Throws annotation has one member, "Class[] value". 1797 */ 1798 Object* obj = getAnnotationValue(clazz, pAnnoItem, "value", 1799 kDexAnnotationArray, "Throws"); 1800 if (obj == GAV_FAILED) 1801 return NULL; 1802 assert(dvmIsArray((ArrayObject*)obj)); 1803 obj = convertReturnType(obj, gDvm.classJavaLangClassArray); 1804 return (ArrayObject*)obj; 1805} 1806 1807/* 1808 * Given an Annotation's method, find the default value, if any. 1809 * 1810 * If this is a CLASS annotation, and we can't find a match for the 1811 * default class value, we need to throw a TypeNotPresentException. 1812 * 1813 * Caller must call dvmReleaseTrackedAlloc(). 1814 */ 1815Object* dvmGetAnnotationDefaultValue(const Method* method) 1816{ 1817 const ClassObject* clazz = method->clazz; 1818 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 1819 const DexAnnotationsDirectoryItem* pAnnoDir; 1820 const DexAnnotationSetItem* pAnnoSet = NULL; 1821 1822 /* 1823 * The method's declaring class (the annotation) will have an 1824 * AnnotationDefault "system" annotation associated with it if any 1825 * of its methods have default values. Start by finding the 1826 * DexAnnotationItem associated with the class. 1827 */ 1828 pAnnoDir = getAnnoDirectory(pDexFile, clazz); 1829 if (pAnnoDir != NULL) 1830 pAnnoSet = dexGetClassAnnotationSet(pDexFile, pAnnoDir); 1831 if (pAnnoSet == NULL) { 1832 /* no annotations for anything in class, or no class annotations */ 1833 return NULL; 1834 } 1835 1836 /* find the "AnnotationDefault" annotation, if any */ 1837 const DexAnnotationItem* pAnnoItem; 1838 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrAnnotationDefault, 1839 kDexVisibilitySystem); 1840 if (pAnnoItem == NULL) { 1841 /* no default values for any member in this annotation */ 1842 //printf("##### no default annotations for %s.%s\n", 1843 // method->clazz->descriptor, method->name); 1844 return NULL; 1845 } 1846 1847 /* 1848 * The AnnotationDefault annotation has one member, "Annotation value". 1849 * We need to pull that out. 1850 */ 1851 const u1* ptr; 1852 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value"); 1853 if (ptr == NULL) { 1854 ALOGW("AnnotationDefault annotation lacks 'value'"); 1855 return NULL; 1856 } 1857 if ((*ptr & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) { 1858 ALOGW("AnnotationDefault value has wrong type (0x%02x)", 1859 *ptr & kDexAnnotationValueTypeMask); 1860 return NULL; 1861 } 1862 1863 /* 1864 * The value_type byte for VALUE_ANNOTATION is followed by 1865 * encoded_annotation data. We want to scan through it to find an 1866 * entry whose name matches our method name. 1867 */ 1868 ptr++; 1869 ptr = searchEncodedAnnotation(clazz, ptr, method->name); 1870 if (ptr == NULL) 1871 return NULL; /* no default annotation for this method */ 1872 1873 /* got it, pull it out */ 1874 AnnotationValue avalue; 1875 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) { 1876 ALOGD("processAnnotationValue failed on default for '%s'", 1877 method->name); 1878 return NULL; 1879 } 1880 1881 /* convert the return type, if necessary */ 1882 ClassObject* methodReturn = dvmGetBoxedReturnType(method); 1883 Object* obj = (Object*)avalue.value.l; 1884 obj = convertReturnType(obj, methodReturn); 1885 1886 return obj; 1887} 1888 1889 1890/* 1891 * =========================================================================== 1892 * Field 1893 * =========================================================================== 1894 */ 1895 1896/* 1897 * Compare the attributes (class name, field name, field signature) of 1898 * the specified field to "field". 1899 */ 1900static int compareFieldStr(DexFile* pDexFile, u4 idx, const Field* field) 1901{ 1902 const DexFieldId* pFieldId = dexGetFieldId(pDexFile, idx); 1903 const char* str = dexStringByTypeIdx(pDexFile, pFieldId->classIdx); 1904 int result = strcmp(str, field->clazz->descriptor); 1905 1906 if (result == 0) { 1907 str = dexStringById(pDexFile, pFieldId->nameIdx); 1908 result = strcmp(str, field->name); 1909 if (result == 0) { 1910 str = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx); 1911 result = strcmp(str, field->signature); 1912 } 1913 } 1914 1915 return result; 1916} 1917 1918/* 1919 * Given a field, determine the field's index. 1920 * 1921 * This has the same tradeoffs as getMethodIdx. 1922 */ 1923static u4 getFieldIdx(const Field* field) 1924{ 1925 DexFile* pDexFile = field->clazz->pDvmDex->pDexFile; 1926 u4 hi = pDexFile->pHeader->fieldIdsSize -1; 1927 u4 lo = 0; 1928 u4 cur; 1929 1930 while (hi >= lo) { 1931 int cmp; 1932 cur = (lo + hi) / 2; 1933 1934 cmp = compareFieldStr(pDexFile, cur, field); 1935 if (cmp < 0) { 1936 lo = cur + 1; 1937 } else if (cmp > 0) { 1938 hi = cur - 1; 1939 } else { 1940 break; 1941 } 1942 } 1943 1944 if (hi < lo) { 1945 /* this should be impossible -- the field came out of this DEX */ 1946 ALOGE("Unable to find field %s.%s %s in DEX file!", 1947 field->clazz->descriptor, field->name, field->signature); 1948 dvmAbort(); 1949 } 1950 1951 return cur; 1952} 1953 1954/* 1955 * Find the DexAnnotationSetItem for this field. 1956 * 1957 * Returns NULL if none found. 1958 */ 1959static const DexAnnotationSetItem* findAnnotationSetForField(const Field* field) 1960{ 1961 ClassObject* clazz = field->clazz; 1962 DvmDex* pDvmDex = clazz->pDvmDex; 1963 if (pDvmDex == NULL) { 1964 return NULL; 1965 } 1966 1967 DexFile* pDexFile = pDvmDex->pDexFile; 1968 1969 const DexAnnotationsDirectoryItem* pAnnoDir = getAnnoDirectory(pDexFile, clazz); 1970 if (pAnnoDir == NULL) { 1971 return NULL; 1972 } 1973 1974 const DexFieldAnnotationsItem* pFieldList = dexGetFieldAnnotations(pDexFile, pAnnoDir); 1975 if (pFieldList == NULL) { 1976 return NULL; 1977 } 1978 1979 /* 1980 * Run through the list and find a matching field. We compare the 1981 * field ref indices in the annotation list with the field's DEX 1982 * field_idx value. 1983 * 1984 * TODO: use a binary search for long lists 1985 * 1986 * Alternate approach: for each entry in the annotations list, 1987 * find the field definition in the DEX file and perform string 1988 * comparisons on class name, field name, and signature. 1989 */ 1990 u4 fieldIdx = getFieldIdx(field); 1991 u4 count = dexGetFieldAnnotationsSize(pDexFile, pAnnoDir); 1992 u4 idx; 1993 1994 for (idx = 0; idx < count; idx++) { 1995 if (pFieldList[idx].fieldIdx == fieldIdx) { 1996 /* found! */ 1997 return dexGetFieldAnnotationSetItem(pDexFile, &pFieldList[idx]); 1998 } 1999 } 2000 2001 return NULL; 2002} 2003 2004/* 2005 * Return an array of Annotation objects for the field. Returns an empty 2006 * array if there are no annotations. 2007 * 2008 * Caller must call dvmReleaseTrackedAlloc(). 2009 * 2010 * On allocation failure, this returns NULL with an exception raised. 2011 */ 2012ArrayObject* dvmGetFieldAnnotations(const Field* field) 2013{ 2014 ClassObject* clazz = field->clazz; 2015 ArrayObject* annoArray = NULL; 2016 const DexAnnotationSetItem* pAnnoSet = NULL; 2017 2018 pAnnoSet = findAnnotationSetForField(field); 2019 if (pAnnoSet == NULL) { 2020 /* no matching annotations found */ 2021 annoArray = emptyAnnoArray(); 2022 } else { 2023 annoArray = processAnnotationSet(clazz, pAnnoSet, 2024 kDexVisibilityRuntime); 2025 } 2026 2027 return annoArray; 2028} 2029 2030/* 2031 * Returns the annotation or NULL if it doesn't exist. 2032 */ 2033Object* dvmGetFieldAnnotation(const ClassObject* clazz, const Field* field, 2034 const ClassObject* annotationClazz) 2035{ 2036 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field); 2037 if (pAnnoSet == NULL) { 2038 return NULL; 2039 } 2040 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet, 2041 kDexVisibilityRuntime, annotationClazz); 2042} 2043 2044/* 2045 * Returns true if the annotation exists. 2046 */ 2047bool dvmIsFieldAnnotationPresent(const ClassObject* clazz, 2048 const Field* field, const ClassObject* annotationClazz) 2049{ 2050 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field); 2051 if (pAnnoSet == NULL) { 2052 return NULL; 2053 } 2054 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet( 2055 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz); 2056 return (pAnnoItem != NULL); 2057} 2058 2059/* 2060 * Retrieve the Signature annotation, if any. Returns NULL if no signature 2061 * exists. 2062 * 2063 * Caller must call dvmReleaseTrackedAlloc(). 2064 */ 2065ArrayObject* dvmGetFieldSignatureAnnotation(const Field* field) 2066{ 2067 ClassObject* clazz = field->clazz; 2068 const DexAnnotationSetItem* pAnnoSet; 2069 ArrayObject* signature = NULL; 2070 2071 pAnnoSet = findAnnotationSetForField(field); 2072 if (pAnnoSet != NULL) 2073 signature = getSignatureValue(clazz, pAnnoSet); 2074 2075 return signature; 2076} 2077 2078 2079/* 2080 * =========================================================================== 2081 * Parameter 2082 * =========================================================================== 2083 */ 2084 2085/* 2086 * We have an annotation_set_ref_list, which is essentially a list of 2087 * entries that we pass to processAnnotationSet(). 2088 * 2089 * The returned object must be released with dvmReleaseTrackedAlloc. 2090 */ 2091static ArrayObject* processAnnotationSetRefList(const ClassObject* clazz, 2092 const DexAnnotationSetRefList* pAnnoSetList, u4 count) 2093{ 2094 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 2095 ArrayObject* annoArrayArray = NULL; 2096 u4 idx; 2097 2098 /* allocate an array of Annotation arrays to hold results */ 2099 annoArrayArray = dvmAllocArrayByClass( 2100 gDvm.classJavaLangAnnotationAnnotationArrayArray, count, ALLOC_DEFAULT); 2101 if (annoArrayArray == NULL) { 2102 ALOGW("annotation set ref array alloc failed"); 2103 goto bail; 2104 } 2105 2106 for (idx = 0; idx < count; idx++) { 2107 Thread* self = dvmThreadSelf(); 2108 const DexAnnotationSetRefItem* pItem; 2109 const DexAnnotationSetItem* pAnnoSet; 2110 Object *annoSet; 2111 DexAnnotationSetItem emptySet; 2112 emptySet.size = 0; 2113 2114 pItem = dexGetParameterAnnotationSetRef(pAnnoSetList, idx); 2115 pAnnoSet = dexGetSetRefItemItem(pDexFile, pItem); 2116 if (pAnnoSet == NULL) { 2117 pAnnoSet = &emptySet; 2118 } 2119 2120 annoSet = (Object *)processAnnotationSet(clazz, 2121 pAnnoSet, 2122 kDexVisibilityRuntime); 2123 if (annoSet == NULL) { 2124 ALOGW("processAnnotationSet failed"); 2125 annoArrayArray = NULL; 2126 goto bail; 2127 } 2128 dvmSetObjectArrayElement(annoArrayArray, idx, annoSet); 2129 dvmReleaseTrackedAlloc((Object*) annoSet, self); 2130 } 2131 2132bail: 2133 return annoArrayArray; 2134} 2135 2136/* 2137 * Find the DexAnnotationSetItem for this parameter. 2138 * 2139 * Returns NULL if none found. 2140 */ 2141static const DexParameterAnnotationsItem* findAnnotationsItemForMethod( 2142 const Method* method) 2143{ 2144 ClassObject* clazz = method->clazz; 2145 DexFile* pDexFile; 2146 const DexAnnotationsDirectoryItem* pAnnoDir; 2147 const DexParameterAnnotationsItem* pParameterList; 2148 2149 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */ 2150 return NULL; 2151 2152 pDexFile = clazz->pDvmDex->pDexFile; 2153 pAnnoDir = getAnnoDirectory(pDexFile, clazz); 2154 if (pAnnoDir == NULL) 2155 return NULL; 2156 2157 pParameterList = dexGetParameterAnnotations(pDexFile, pAnnoDir); 2158 if (pParameterList == NULL) 2159 return NULL; 2160 2161 /* 2162 * Run through the list and find a matching method. We compare the 2163 * method ref indices in the annotation list with the method's DEX 2164 * method_idx value. 2165 * 2166 * TODO: use a binary search for long lists 2167 * 2168 * Alternate approach: for each entry in the annotations list, 2169 * find the method definition in the DEX file and perform string 2170 * comparisons on class name, method name, and signature. 2171 */ 2172 u4 methodIdx = getMethodIdx(method); 2173 u4 count = dexGetParameterAnnotationsSize(pDexFile, pAnnoDir); 2174 u4 idx; 2175 2176 for (idx = 0; idx < count; idx++) { 2177 if (pParameterList[idx].methodIdx == methodIdx) { 2178 /* found! */ 2179 return &pParameterList[idx]; 2180 } 2181 } 2182 2183 return NULL; 2184} 2185 2186 2187/* 2188 * Count up the number of arguments the method takes. The "this" pointer 2189 * doesn't count. 2190 */ 2191static int countMethodArguments(const Method* method) 2192{ 2193 /* method->shorty[0] is the return type */ 2194 return strlen(method->shorty + 1); 2195} 2196 2197/* 2198 * Return an array of arrays of Annotation objects. The outer array has 2199 * one entry per method parameter, the inner array has the list of annotations 2200 * associated with that parameter. 2201 * 2202 * If the method has no parameters, we return an array of length zero. If 2203 * the method has one or more parameters, we return an array whose length 2204 * is equal to the number of parameters; if a given parameter does not have 2205 * an annotation, the corresponding entry will be null. 2206 * 2207 * Caller must call dvmReleaseTrackedAlloc(). 2208 */ 2209ArrayObject* dvmGetParameterAnnotations(const Method* method) 2210{ 2211 ClassObject* clazz = method->clazz; 2212 const DexParameterAnnotationsItem* pItem; 2213 ArrayObject* annoArrayArray = NULL; 2214 2215 pItem = findAnnotationsItemForMethod(method); 2216 if (pItem != NULL) { 2217 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 2218 const DexAnnotationSetRefList* pAnnoSetList; 2219 u4 size; 2220 2221 size = dexGetParameterAnnotationSetRefSize(pDexFile, pItem); 2222 pAnnoSetList = dexGetParameterAnnotationSetRefList(pDexFile, pItem); 2223 annoArrayArray = processAnnotationSetRefList(clazz, pAnnoSetList, size); 2224 } else { 2225 /* no matching annotations found */ 2226 annoArrayArray = emptyAnnoArrayArray(countMethodArguments(method)); 2227 } 2228 2229 return annoArrayArray; 2230} 2231 2232 2233/* 2234 * =========================================================================== 2235 * DexEncodedArray interpretation 2236 * =========================================================================== 2237 */ 2238 2239/** 2240 * Initializes an encoded array iterator. 2241 * 2242 * @param iterator iterator to initialize 2243 * @param encodedArray encoded array to iterate over 2244 * @param clazz class to use when resolving strings and types 2245 */ 2246void dvmEncodedArrayIteratorInitialize(EncodedArrayIterator* iterator, 2247 const DexEncodedArray* encodedArray, const ClassObject* clazz) { 2248 iterator->encodedArray = encodedArray; 2249 iterator->cursor = encodedArray->array; 2250 iterator->size = readUleb128(&iterator->cursor); 2251 iterator->elementsLeft = iterator->size; 2252 iterator->clazz = clazz; 2253} 2254 2255/** 2256 * Returns whether there are more elements to be read. 2257 */ 2258bool dvmEncodedArrayIteratorHasNext(const EncodedArrayIterator* iterator) { 2259 return (iterator->elementsLeft != 0); 2260} 2261 2262/** 2263 * Returns the next decoded value from the iterator, advancing its 2264 * cursor. This returns primitive values in their corresponding union 2265 * slots, and returns everything else (including nulls) as object 2266 * references in the "l" union slot. 2267 * 2268 * The caller must call dvmReleaseTrackedAlloc() on any returned reference. 2269 * 2270 * @param value pointer to store decoded value into 2271 * @returns true if a value was decoded and the cursor advanced; false if 2272 * the last value had already been decoded or if there was a problem decoding 2273 */ 2274bool dvmEncodedArrayIteratorGetNext(EncodedArrayIterator* iterator, 2275 AnnotationValue* value) { 2276 bool processed; 2277 2278 if (iterator->elementsLeft == 0) { 2279 return false; 2280 } 2281 2282 processed = processAnnotationValue(iterator->clazz, &iterator->cursor, 2283 value, kPrimitivesOrObjects); 2284 2285 if (! processed) { 2286 ALOGE("Failed to process array element %d from %p", 2287 iterator->size - iterator->elementsLeft, 2288 iterator->encodedArray); 2289 iterator->elementsLeft = 0; 2290 return false; 2291 } 2292 2293 iterator->elementsLeft--; 2294 return true; 2295} 2296